From 1021814a75173d1efae47bc2f71ac5cabdc559c5 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 22 Jan 2021 17:37:57 +0530 Subject: [PATCH 01/46] [MessageSendingStatus] lowercase enum values --- packages/dart_client/lib/src/api/channel.dart | 4 +- .../dart_client/lib/src/api/retry_queue.dart | 42 +++++++++---------- packages/dart_client/lib/src/client.dart | 10 ++--- .../dart_client/lib/src/db/models.part.dart | 28 ++++++------- .../dart_client/lib/src/models/message.dart | 16 +++---- .../lib/src/message_actions_modal.dart | 12 +++--- .../lib/src/message_input.dart | 2 +- .../lib/src/message_reactions_modal.dart | 4 +- .../lib/src/message_widget.dart | 14 +++---- .../lib/src/sending_indicator.dart | 6 +-- 10 files changed, 69 insertions(+), 69 deletions(-) diff --git a/packages/dart_client/lib/src/api/channel.dart b/packages/dart_client/lib/src/api/channel.dart index d8ef1a03..01911b83 100644 --- a/packages/dart_client/lib/src/api/channel.dart +++ b/packages/dart_client/lib/src/api/channel.dart @@ -183,7 +183,7 @@ class Channel { user: _client.state.user, id: messageId, quotedMessage: quotedMessage, - status: MessageSendingStatus.SENDING, + status: MessageSendingStatus.sending, ); if (message.parentId != null && message.id == null) { @@ -978,7 +978,7 @@ class ChannelClientState { [...messages, ...threads.values.expand((v) => v)] .where((message) => message.status != null && - message.status != MessageSendingStatus.SENT && + message.status != MessageSendingStatus.sent && message.createdAt.isBefore(DateTime.now().subtract(Duration( seconds: 1, )))) diff --git a/packages/dart_client/lib/src/api/retry_queue.dart b/packages/dart_client/lib/src/api/retry_queue.dart index 12e8377a..376854af 100644 --- a/packages/dart_client/lib/src/api/retry_queue.dart +++ b/packages/dart_client/lib/src/api/retry_queue.dart @@ -113,30 +113,30 @@ class RetryQueue { } void _sendFailedEvent(Message message) { - final newStatus = message.status == MessageSendingStatus.SENDING - ? MessageSendingStatus.FAILED - : (message.status == MessageSendingStatus.UPDATING - ? MessageSendingStatus.FAILED_UPDATE - : MessageSendingStatus.FAILED_DELETE); + final newStatus = message.status == MessageSendingStatus.sending + ? MessageSendingStatus.failed + : (message.status == MessageSendingStatus.updating + ? MessageSendingStatus.failed_update + : MessageSendingStatus.failed_delete); channel.state.addMessage(message.copyWith( status: newStatus, )); } Future _sendMessage(Message message) async { - if (message.status == MessageSendingStatus.FAILED_UPDATE || - message.status == MessageSendingStatus.UPDATING) { + if (message.status == MessageSendingStatus.failed_update || + message.status == MessageSendingStatus.updating) { await channel.client.updateMessage( message, channel.cid, ); - } else if (message.status == MessageSendingStatus.FAILED || - message.status == MessageSendingStatus.SENDING) { + } else if (message.status == MessageSendingStatus.failed || + message.status == MessageSendingStatus.sending) { await channel.sendMessage( message, ); - } else if (message.status == MessageSendingStatus.FAILED_DELETE || - message.status == MessageSendingStatus.DELETING) { + } else if (message.status == MessageSendingStatus.failed_delete || + message.status == MessageSendingStatus.deleting) { await channel.client.deleteMessage( message, channel.cid, @@ -152,15 +152,15 @@ class RetryQueue { messageList.indexWhere((m) => m.id == event.message.id); if (messageIndex == -1 && [ - MessageSendingStatus.FAILED_UPDATE, - MessageSendingStatus.FAILED, - MessageSendingStatus.FAILED_DELETE, + MessageSendingStatus.failed_update, + MessageSendingStatus.failed, + MessageSendingStatus.failed_delete, ].contains(event.message.status)) { logger?.info('add message from events'); add([event.message]); } else if (messageIndex != -1 && [ - MessageSendingStatus.SENT, + MessageSendingStatus.sent, null, ].contains(event.message.status)) { _messageQueue.remove(messageList[messageIndex]); @@ -184,16 +184,16 @@ class RetryQueue { static DateTime _getMessageDate(Message m1) { switch (m1.status) { - case MessageSendingStatus.FAILED_DELETE: - case MessageSendingStatus.DELETING: + case MessageSendingStatus.failed_delete: + case MessageSendingStatus.deleting: return m1.deletedAt; - case MessageSendingStatus.FAILED: - case MessageSendingStatus.SENDING: + case MessageSendingStatus.failed: + case MessageSendingStatus.sending: return m1.createdAt; - case MessageSendingStatus.FAILED_UPDATE: - case MessageSendingStatus.UPDATING: + case MessageSendingStatus.failed_update: + case MessageSendingStatus.updating: return m1.updatedAt; default: return null; diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index 09ea4232..bb026ee7 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -1198,7 +1198,7 @@ class Client { String cid, ]) async { message = message.copyWith( - status: MessageSendingStatus.UPDATING, + status: MessageSendingStatus.updating, updatedAt: message.updatedAt ?? DateTime.now(), ); @@ -1229,10 +1229,10 @@ class Client { /// Deletes the given message Future deleteMessage(Message message, [String cid]) async { - if (message.status == MessageSendingStatus.FAILED) { + if (message.status == MessageSendingStatus.failed) { state.channels[cid].state.addMessage(message.copyWith( type: 'deleted', - status: MessageSendingStatus.SENT, + status: MessageSendingStatus.sent, )); return EmptyResponse(); } @@ -1240,7 +1240,7 @@ class Client { try { message = message.copyWith( type: 'deleted', - status: MessageSendingStatus.DELETING, + status: MessageSendingStatus.deleting, deletedAt: message.deletedAt ?? DateTime.now(), ); @@ -1252,7 +1252,7 @@ class Client { if (state?.channels != null) { state.channels[cid]?.state - ?.addMessage(message.copyWith(status: MessageSendingStatus.SENT)); + ?.addMessage(message.copyWith(status: MessageSendingStatus.sent)); } return decode(response.data, EmptyResponse.fromJson); diff --git a/packages/dart_client/lib/src/db/models.part.dart b/packages/dart_client/lib/src/db/models.part.dart index 98fced53..9a8c5e8e 100644 --- a/packages/dart_client/lib/src/db/models.part.dart +++ b/packages/dart_client/lib/src/db/models.part.dart @@ -216,19 +216,19 @@ class _MessageSendingStatusConverter MessageSendingStatus mapToDart(int fromDb) { switch (fromDb) { case 0: - return MessageSendingStatus.SENDING; + return MessageSendingStatus.sending; case 1: - return MessageSendingStatus.SENT; + return MessageSendingStatus.sent; case 2: - return MessageSendingStatus.FAILED; + return MessageSendingStatus.failed; case 3: - return MessageSendingStatus.UPDATING; + return MessageSendingStatus.updating; case 4: - return MessageSendingStatus.FAILED_UPDATE; + return MessageSendingStatus.failed_update; case 5: - return MessageSendingStatus.DELETING; + return MessageSendingStatus.deleting; case 6: - return MessageSendingStatus.FAILED_DELETE; + return MessageSendingStatus.failed_delete; default: return null; } @@ -237,19 +237,19 @@ class _MessageSendingStatusConverter @override int mapToSql(MessageSendingStatus value) { switch (value) { - case MessageSendingStatus.SENDING: + case MessageSendingStatus.sending: return 0; - case MessageSendingStatus.SENT: + case MessageSendingStatus.sent: return 1; - case MessageSendingStatus.FAILED: + case MessageSendingStatus.failed: return 2; - case MessageSendingStatus.UPDATING: + case MessageSendingStatus.updating: return 3; - case MessageSendingStatus.FAILED_UPDATE: + case MessageSendingStatus.failed_update: return 4; - case MessageSendingStatus.DELETING: + case MessageSendingStatus.deleting: return 5; - case MessageSendingStatus.FAILED_DELETE: + case MessageSendingStatus.failed_delete: return 6; default: return null; diff --git a/packages/dart_client/lib/src/models/message.dart b/packages/dart_client/lib/src/models/message.dart index e23eb51a..df188e35 100644 --- a/packages/dart_client/lib/src/models/message.dart +++ b/packages/dart_client/lib/src/models/message.dart @@ -10,25 +10,25 @@ part 'message.g.dart'; /// Enum defining the status of a sending message enum MessageSendingStatus { /// Message is being sent - SENDING, + sending, /// Message is being updated - UPDATING, + updating, /// Message is being deleted - DELETING, + deleting, /// Message failed to send - FAILED, + failed, /// Message failed to updated - FAILED_UPDATE, + failed_update, /// Message failed to delete - FAILED_DELETE, + failed_delete, /// Message correctly sent - SENT, + sent, } /// The class that contains the information about a message @@ -186,7 +186,7 @@ class Message { this.user, this.extraData, this.deletedAt, - this.status = MessageSendingStatus.SENT, + this.status = MessageSendingStatus.sent, }); /// Create a new instance from a json diff --git a/packages/flutter_widgets/lib/src/message_actions_modal.dart b/packages/flutter_widgets/lib/src/message_actions_modal.dart index 0cda4e9d..4aa2cde4 100644 --- a/packages/flutter_widgets/lib/src/message_actions_modal.dart +++ b/packages/flutter_widgets/lib/src/message_actions_modal.dart @@ -127,7 +127,7 @@ class _MessageActionsModalState extends State { children: [ if (widget.showReactions && (widget.message.status == - MessageSendingStatus.SENT || + MessageSendingStatus.sent || widget.message.status == null)) Align( alignment: Alignment( @@ -175,7 +175,7 @@ class _MessageActionsModalState extends State { showReactionPickerIndicator: widget.showReactions && (widget.message.status == - MessageSendingStatus.SENT || + MessageSendingStatus.sent || widget.message.status == null), showInChannelIndicator: false, showSendingIndicator: false, @@ -204,13 +204,13 @@ class _MessageActionsModalState extends State { children: [ if (widget.showReplyMessage && (widget.message.status == - MessageSendingStatus.SENT || + MessageSendingStatus.sent || widget.message.status == null) && widget.message.parentId == null) _buildReplyButton(context), if (widget.showThreadReplyMessage && (widget.message.status == - MessageSendingStatus.SENT || + MessageSendingStatus.sent || widget.message.status == null) && widget.message.parentId == null) _buildThreadReplyButton(context), @@ -487,7 +487,7 @@ class _MessageActionsModalState extends State { Widget _buildDeleteButton(BuildContext context) { final isDeleteFailed = - widget.message.status == MessageSendingStatus.FAILED_DELETE; + widget.message.status == MessageSendingStatus.failed_delete; return InkWell( onTap: () => _showDeleteDialog(), child: Padding( @@ -562,7 +562,7 @@ class _MessageActionsModalState extends State { Widget _buildResendMessage(BuildContext context) { final isUpdateFailed = - widget.message.status == MessageSendingStatus.FAILED_UPDATE; + widget.message.status == MessageSendingStatus.failed_update; return InkWell( onTap: () { Navigator.pop(context); diff --git a/packages/flutter_widgets/lib/src/message_input.dart b/packages/flutter_widgets/lib/src/message_input.dart index 01ae3d3a..70b8b46f 100644 --- a/packages/flutter_widgets/lib/src/message_input.dart +++ b/packages/flutter_widgets/lib/src/message_input.dart @@ -2211,7 +2211,7 @@ class MessageInputState extends State { _mentionedUsers.clear(); if (widget.editMessage == null || - widget.editMessage.status == MessageSendingStatus.FAILED) { + widget.editMessage.status == MessageSendingStatus.failed) { sendingFuture = channel.sendMessage(message); } else { sendingFuture = StreamChat.of(context).client.updateMessage( diff --git a/packages/flutter_widgets/lib/src/message_reactions_modal.dart b/packages/flutter_widgets/lib/src/message_reactions_modal.dart index 1ee3486d..2f117aca 100644 --- a/packages/flutter_widgets/lib/src/message_reactions_modal.dart +++ b/packages/flutter_widgets/lib/src/message_reactions_modal.dart @@ -93,7 +93,7 @@ class MessageReactionsModal extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (showReactions && - (message.status == MessageSendingStatus.SENT || + (message.status == MessageSendingStatus.sent || message.status == null)) Align( alignment: Alignment( @@ -141,7 +141,7 @@ class MessageReactionsModal extends StatelessWidget { ), showReactionPickerIndicator: showReactions && (message.status == - MessageSendingStatus.SENT || + MessageSendingStatus.sent || message.status == null), ), ), diff --git a/packages/flutter_widgets/lib/src/message_widget.dart b/packages/flutter_widgets/lib/src/message_widget.dart index 2a15f898..c2cbdc35 100644 --- a/packages/flutter_widgets/lib/src/message_widget.dart +++ b/packages/flutter_widgets/lib/src/message_widget.dart @@ -263,13 +263,13 @@ class _MessageWidgetState extends State { bool get hasQuotedMessage => widget.message?.quotedMessage != null; - bool get isSendFailed => widget.message.status == MessageSendingStatus.FAILED; + bool get isSendFailed => widget.message.status == MessageSendingStatus.failed; bool get isUpdateFailed => - widget.message.status == MessageSendingStatus.FAILED_UPDATE; + widget.message.status == MessageSendingStatus.failed_update; bool get isDeleteFailed => - widget.message.status == MessageSendingStatus.FAILED_DELETE; + widget.message.status == MessageSendingStatus.failed_delete; bool get isFailedState => isSendFailed || isUpdateFailed || isDeleteFailed; @@ -875,7 +875,7 @@ class _MessageWidgetState extends State { void onLongPress(BuildContext context) { if (widget.message.isEphemeral || - widget.message.status == MessageSendingStatus.SENDING) { + widget.message.status == MessageSendingStatus.sending) { return; } @@ -986,11 +986,11 @@ class _MessageWidgetState extends State { void retryMessage(BuildContext context) { final channel = StreamChannel.of(context).channel; - if (widget.message.status == MessageSendingStatus.FAILED) { + if (widget.message.status == MessageSendingStatus.failed) { channel.sendMessage(widget.message); return; } - if (widget.message.status == MessageSendingStatus.FAILED_UPDATE) { + if (widget.message.status == MessageSendingStatus.failed_update) { StreamChat.of(context).client.updateMessage( widget.message, channel.cid, @@ -998,7 +998,7 @@ class _MessageWidgetState extends State { return; } - if (widget.message.status == MessageSendingStatus.FAILED_DELETE) { + if (widget.message.status == MessageSendingStatus.failed_delete) { StreamChat.of(context).client.deleteMessage( widget.message, channel.cid, diff --git a/packages/flutter_widgets/lib/src/sending_indicator.dart b/packages/flutter_widgets/lib/src/sending_indicator.dart index 83e02bb3..3fca2fa9 100644 --- a/packages/flutter_widgets/lib/src/sending_indicator.dart +++ b/packages/flutter_widgets/lib/src/sending_indicator.dart @@ -22,14 +22,14 @@ class SendingIndicator extends StatelessWidget { color: StreamChatTheme.of(context).colorTheme.accentBlue, ); } - if (message.status == MessageSendingStatus.SENT || message.status == null) { + if (message.status == MessageSendingStatus.sent || message.status == null) { return StreamSvgIcon.check( size: size, color: IconTheme.of(context).color.withOpacity(0.5), ); } - if (message.status == MessageSendingStatus.SENDING || - message.status == MessageSendingStatus.UPDATING) { + if (message.status == MessageSendingStatus.sending || + message.status == MessageSendingStatus.updating) { return Icon( Icons.access_time, size: size, From 657b58af8b2888406ef224aa33e6e85e9c74e164 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 25 Jan 2021 19:14:55 +0530 Subject: [PATCH 02/46] [StreamChatPersistence] Add initial implementation Signed-off-by: Sahil Kumar --- .../lib/src/db/stream_chat_database.dart | 97 ++++++++ .../dart_client/lib/src/utils/result.dart | 45 ++++ packages/dart_client/lib/stream_chat.dart | 4 +- packages/dart_client/pubspec.yaml | 3 + packages/stream_chat_persistence/.gitignore | 74 ++++++ packages/stream_chat_persistence/.metadata | 10 + packages/stream_chat_persistence/CHANGELOG.md | 3 + packages/stream_chat_persistence/LICENSE | 1 + packages/stream_chat_persistence/README.md | 14 ++ packages/stream_chat_persistence/build.yaml | 6 + .../lib/src/converter/list_converter.dart | 22 ++ .../lib/src/converter/map_converter.dart | 22 ++ .../message_sending_status_converter.dart | 50 ++++ .../lib/src/dao/channel_dao.dart | 57 +++++ .../lib/src/dao/channel_query_dao.dart | 126 ++++++++++ .../lib/src/dao/connection_event_dao.dart | 58 +++++ .../lib/src/dao/dao.dart | 8 + .../lib/src/dao/member_dao.dart | 43 ++++ .../lib/src/dao/message_dao.dart | 143 +++++++++++ .../lib/src/dao/reaction_dao.dart | 50 ++++ .../lib/src/dao/read_dao.dart | 42 ++++ .../lib/src/dao/user_dao.dart | 25 ++ .../lib/src/db/moor_chat_database.dart | 83 +++++++ .../lib/src/db/shared/native_db.dart | 87 +++++++ .../lib/src/db/shared/shared_db.dart | 3 + .../lib/src/db/shared/unsupported_db.dart | 18 ++ .../lib/src/db/shared/web_db.dart | 21 ++ .../lib/src/db/stream_chat_database_impl.dart | 222 ++++++++++++++++++ .../lib/src/entity/channel_queries.dart | 14 ++ .../lib/src/entity/channels.dart | 32 +++ .../lib/src/entity/connection_events.dart | 19 ++ .../lib/src/entity/entity.dart | 8 + .../lib/src/entity/members.dart | 33 +++ .../lib/src/entity/messages.dart | 54 +++++ .../lib/src/entity/reactions.dart | 25 ++ .../lib/src/entity/reads.dart | 19 ++ .../lib/src/entity/users.dart | 24 ++ .../lib/src/mapper/channel_mapper.dart | 61 +++++ .../lib/src/mapper/event_mapper.dart | 15 ++ .../lib/src/mapper/mapper.dart | 7 + .../lib/src/mapper/member_mapper.dart | 43 ++++ .../lib/src/mapper/message_mapper.dart | 70 ++++++ .../lib/src/mapper/reaction_mapper.dart | 33 +++ .../lib/src/mapper/read_mapper.dart | 28 +++ .../lib/src/mapper/user_mapper.dart | 36 +++ .../lib/stream_chat_persistence.dart | 3 + packages/stream_chat_persistence/pubspec.yaml | 18 ++ 47 files changed, 1878 insertions(+), 1 deletion(-) create mode 100644 packages/dart_client/lib/src/db/stream_chat_database.dart create mode 100644 packages/dart_client/lib/src/utils/result.dart create mode 100644 packages/stream_chat_persistence/.gitignore create mode 100644 packages/stream_chat_persistence/.metadata create mode 100644 packages/stream_chat_persistence/CHANGELOG.md create mode 100644 packages/stream_chat_persistence/LICENSE create mode 100644 packages/stream_chat_persistence/README.md create mode 100644 packages/stream_chat_persistence/build.yaml create mode 100644 packages/stream_chat_persistence/lib/src/converter/list_converter.dart create mode 100644 packages/stream_chat_persistence/lib/src/converter/map_converter.dart create mode 100644 packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/channel_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/member_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/message_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/read_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/user_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart create mode 100644 packages/stream_chat_persistence/lib/src/db/shared/native_db.dart create mode 100644 packages/stream_chat_persistence/lib/src/db/shared/shared_db.dart create mode 100644 packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart create mode 100644 packages/stream_chat_persistence/lib/src/db/shared/web_db.dart create mode 100644 packages/stream_chat_persistence/lib/src/db/stream_chat_database_impl.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/channel_queries.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/channels.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/connection_events.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/entity.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/members.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/messages.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/reactions.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/reads.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/users.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/mapper.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart create mode 100644 packages/stream_chat_persistence/lib/stream_chat_persistence.dart create mode 100644 packages/stream_chat_persistence/pubspec.yaml diff --git a/packages/dart_client/lib/src/db/stream_chat_database.dart b/packages/dart_client/lib/src/db/stream_chat_database.dart new file mode 100644 index 00000000..87ab828e --- /dev/null +++ b/packages/dart_client/lib/src/db/stream_chat_database.dart @@ -0,0 +1,97 @@ +import 'package:stream_chat/src/api/requests.dart'; +import 'package:stream_chat/src/models/channel_model.dart'; +import 'package:stream_chat/src/models/channel_state.dart'; +import 'package:stream_chat/src/models/event.dart'; +import 'package:stream_chat/src/models/member.dart'; +import 'package:stream_chat/src/models/message.dart'; +import 'package:stream_chat/src/models/reaction.dart'; +import 'package:stream_chat/src/models/read.dart'; +import 'package:stream_chat/src/models/user.dart'; + +/// +abstract class StreamChatDatabase { + /// Creates a new connection to the database + Future connect({ + bool connectBackground = false, + bool logStatements = false, + }); + + /// Closes the database instance + /// If [flush] is true, the database data will be deleted + Future disconnect({bool flush = false}); + + /// Get stored replies by messageId + Future> getReplies( + String parentId, { + String lessThan, + }); + + /// Get stored connection event + Future getConnectionInfo(); + + /// Get stored lastSyncAt + Future getLastSyncAt(); + + /// Update stored connection event + Future updateConnectionInfo(Event event); + + /// Update stored lastSyncAt + Future updateLastSyncAt(DateTime lastSyncAt); + + /// Get the channel cids saved in the offline storage + Future> getChannelCids(); + + Future getChannelByCid(String cid); + + Future> getMembersByCid(String cid); + + Future> getReadsByCid(String cid); + + Future> getMessagesByCid( + String cid, { + int limit = 20, + String messageLessThan, + String messageGreaterThan, + }); + + /// Get list of channels by filter, sort and paginationParams + Future> getChannelStates({ + Map filter, + List sort = const [], + PaginationParams paginationParams, + }); + + /// Update list of channel queries + /// If [clearQueryCache] is true before the insert + /// the list of matching rows will be deleted + Future updateChannelQueries( + Map filter, + List cids, + bool clearQueryCache, + ); + + /// Remove a message by message id + Future deleteMessageByIds(List messageIds); + + /// Remove a message by message id + Future deleteMessageByCids(List cids); + + /// Remove a channel by cid + Future deleteChannelByCids(List cids); + + /// Update messages data from a list + Future updateMessages(String cid, List messages); + + /// Get the info about channel threads + Future>> getChannelThreads(String cid); + + Future updateChannels(List channels); + + Future updateMembers(String cid, List members); + + Future updateReads(String cid, List reads); + + Future updateUsers(List users); + + Future updateReactions(List reactions); +} diff --git a/packages/dart_client/lib/src/utils/result.dart b/packages/dart_client/lib/src/utils/result.dart new file mode 100644 index 00000000..a2961ec4 --- /dev/null +++ b/packages/dart_client/lib/src/utils/result.dart @@ -0,0 +1,45 @@ +import 'package:flutter/foundation.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../exceptions.dart'; + +part 'result.freezed.dart'; + +/// +@freezed +abstract class Result with _$Result { + /// + const factory Result.success({@required T data}) = Success; + + /// + const factory Result.error({@required ApiError error}) = Error; +} + +/// +extension ResultX on Result { + /// + bool get isSuccess => this is Success; + + /// + bool get isError => this is Error; + + /// + T get data { + if (isError) { + throw Exception( + 'Result is not successful. Check result.isSuccess before reading the data.', + ); + } + return (this as Success).data; + } + + /// + ApiError get error { + if (isSuccess) { + throw Exception( + 'Result is successful, not an error. Check result.isError before reading the error.', + ); + } + return (this as Error).error; + } +} diff --git a/packages/dart_client/lib/stream_chat.dart b/packages/dart_client/lib/stream_chat.dart index 101e9440..8bac944f 100644 --- a/packages/dart_client/lib/stream_chat.dart +++ b/packages/dart_client/lib/stream_chat.dart @@ -2,7 +2,7 @@ library stream_chat; export 'package:dio/src/dio_error.dart'; export 'package:dio/src/multipart_file.dart'; -export 'package:logging/src/level.dart'; +export 'package:logging/logging.dart' show Logger, Level; export './src/api/channel.dart'; export './src/api/connection_status.dart'; @@ -27,3 +27,5 @@ export './src/models/reaction.dart'; export './src/models/read.dart'; export './src/models/user.dart'; export './src/notifications.dart'; +export './src/db/stream_chat_database.dart'; +export './src/utils/result.dart'; diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index 9fd0d9e0..d4734e44 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -26,6 +26,9 @@ dependencies: collection: ^1.14.12 sqlite3_flutter_libs: ^0.3.0 pedantic: ^1.9.2 + freezed: ^0.12.7 + stream_chat_persistence: + path: ../stream_chat_persistence dev_dependencies: build_runner: ^1.10.0 diff --git a/packages/stream_chat_persistence/.gitignore b/packages/stream_chat_persistence/.gitignore new file mode 100644 index 00000000..1985397a --- /dev/null +++ b/packages/stream_chat_persistence/.gitignore @@ -0,0 +1,74 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 diff --git a/packages/stream_chat_persistence/.metadata b/packages/stream_chat_persistence/.metadata new file mode 100644 index 00000000..5eb50347 --- /dev/null +++ b/packages/stream_chat_persistence/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 78910062997c3a836feee883712c241a5fd22983 + channel: stable + +project_type: package diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md new file mode 100644 index 00000000..ac071598 --- /dev/null +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -0,0 +1,3 @@ +## [0.0.1] - TODO: Add release date. + +* TODO: Describe initial release. diff --git a/packages/stream_chat_persistence/LICENSE b/packages/stream_chat_persistence/LICENSE new file mode 100644 index 00000000..ba75c69f --- /dev/null +++ b/packages/stream_chat_persistence/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/stream_chat_persistence/README.md b/packages/stream_chat_persistence/README.md new file mode 100644 index 00000000..3e3f0c7c --- /dev/null +++ b/packages/stream_chat_persistence/README.md @@ -0,0 +1,14 @@ +# stream_chat_persistence + +A new Flutter package. + +## Getting Started + +This project is a starting point for a Dart +[package](https://flutter.dev/developing-packages/), +a library module containing code that can be shared easily across +multiple Flutter or Dart projects. + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/stream_chat_persistence/build.yaml b/packages/stream_chat_persistence/build.yaml new file mode 100644 index 00000000..b07425b6 --- /dev/null +++ b/packages/stream_chat_persistence/build.yaml @@ -0,0 +1,6 @@ +targets: + $default: + builders: + moor_generator: + options: + generate_connect_constructor: true diff --git a/packages/stream_chat_persistence/lib/src/converter/list_converter.dart b/packages/stream_chat_persistence/lib/src/converter/list_converter.dart new file mode 100644 index 00000000..5d0a628f --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/converter/list_converter.dart @@ -0,0 +1,22 @@ +import 'dart:convert'; + +import 'package:moor/moor.dart'; + +/// +class ListConverter extends TypeConverter, String> { + @override + List mapToDart(fromDb) { + if (fromDb == null) { + return null; + } + return List.from(jsonDecode(fromDb) ?? []); + } + + @override + String mapToSql(value) { + if (value == null) { + return null; + } + return jsonEncode(value); + } +} diff --git a/packages/stream_chat_persistence/lib/src/converter/map_converter.dart b/packages/stream_chat_persistence/lib/src/converter/map_converter.dart new file mode 100644 index 00000000..9fde0003 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/converter/map_converter.dart @@ -0,0 +1,22 @@ +import 'dart:convert'; + +import 'package:moor/moor.dart'; + +/// +class MapConverter extends TypeConverter, String> { + @override + Map mapToDart(fromDb) { + if (fromDb == null) { + return null; + } + return Map.from(jsonDecode(fromDb) ?? {}); + } + + @override + String mapToSql(value) { + if (value == null) { + return null; + } + return jsonEncode(value); + } +} diff --git a/packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart b/packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart new file mode 100644 index 00000000..b8d92b82 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart @@ -0,0 +1,50 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; + +/// +class MessageSendingStatusConverter + extends TypeConverter { + @override + MessageSendingStatus mapToDart(int fromDb) { + switch (fromDb) { + case 0: + return MessageSendingStatus.sending; + case 1: + return MessageSendingStatus.sent; + case 2: + return MessageSendingStatus.failed; + case 3: + return MessageSendingStatus.updating; + case 4: + return MessageSendingStatus.failed_update; + case 5: + return MessageSendingStatus.deleting; + case 6: + return MessageSendingStatus.failed_delete; + default: + return null; + } + } + + @override + int mapToSql(MessageSendingStatus value) { + switch (value) { + case MessageSendingStatus.sending: + return 0; + case MessageSendingStatus.sent: + return 1; + case MessageSendingStatus.failed: + return 2; + case MessageSendingStatus.updating: + return 3; + case MessageSendingStatus.failed_update: + return 4; + case MessageSendingStatus.deleting: + return 5; + case MessageSendingStatus.failed_delete: + return 6; + default: + return null; + } + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/channel_dao.dart b/packages/stream_chat_persistence/lib/src/dao/channel_dao.dart new file mode 100644 index 00000000..fa902f52 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/channel_dao.dart @@ -0,0 +1,57 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/channels.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; +import '../mapper/mapper.dart'; + +part 'channel_dao.g.dart'; + +/// +@UseDao(tables: [Channels, Users]) +class ChannelDao extends DatabaseAccessor + with _$ChannelDaoMixin { + /// + ChannelDao(MoorChatDatabase db) : super(db); + + /// Get channel by cid + Future getChannelByCid(String cid) async { + return (select(channels)..where((c) => c.cid.equals(cid))).join([ + leftOuterJoin(users, channels.createdById.equalsExp(users.id)), + ]).map((rows) { + final channel = rows.readTable(channels); + final createdBy = rows.readTable(users); + return channel.toChannelModel(createdBy: createdBy?.toUser()); + }).getSingle(); + } + + /// Delete all channels by matching cid in [cids] + /// + /// This will automatically delete the following linked records + /// 1. Channel Reads + /// 2. Channel Members + /// 3. Channel Messages -> Messages Reactions + Future deleteChannelByCids(List cids) async { + return (delete(channels)..where((tbl) => tbl.cid.isIn(cids))).go(); + } + + /// Get the channel cids saved in the storage + Future> get cids { + return (select(channels) + ..orderBy([(c) => OrderingTerm.desc(c.lastMessageAt)]) + ..limit(250)) + .map((c) => c.cid) + .get(); + } + + /// + Future updateChannels(List channelList) { + return batch( + (it) => it.insertAll( + channels, + channelList.map((c) => c.toEntity()).toList(), + mode: InsertMode.insertOrReplace, + ), + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart b/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart new file mode 100644 index 00000000..a42dd01e --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart @@ -0,0 +1,126 @@ +import 'dart:convert'; + +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/channel_queries.dart'; +import 'package:stream_chat_persistence/src/entity/channels.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; +import '../mapper/mapper.dart'; + +part 'channel_query_dao.g.dart'; + +/// +@UseDao(tables: [ChannelQueries, Channels, Users]) +class ChannelQueryDao extends DatabaseAccessor + with _$ChannelQueryDaoMixin { + /// + ChannelQueryDao(this._db) : super(_db); + + final MoorChatDatabase _db; + + String _computeHash(Map filter) { + if (filter == null) { + return 'allchannels'; + } + final hash = base64Encode(utf8.encode('filter: ${jsonEncode(filter)}')); + return hash; + } + + /// Update list of channel queries + /// If [clearQueryCache] is true before the insert + /// the list of matching rows will be deleted + Future updateChannelQueries( + Map filter, + List cids, + bool clearQueryCache, + ) async { + final hash = _computeHash(filter); + if (clearQueryCache) { + await (delete(channelQueries) + ..where((query) => query.queryHash.equals(hash))) + .go(); + } + + return batch((batch) { + batch.insertAll( + channelQueries, + cids.map((cid) { + return ChannelQueryEntity( + queryHash: hash, + channelCid: cid, + ); + }).toList(), + mode: InsertMode.insertOrReplace, + ); + }); + } + + /// Get list of channels by filter, sort and paginationParams + Future> getChannelStates({ + Map filter, + List sort = const [], + PaginationParams paginationParams, + }) async { + final hash = _computeHash(filter); + final cachedChannels = await Future.wait(await (select(channelQueries) + ..where((c) => c.queryHash.equals(hash))) + .get() + .then((channelQueries) { + final cids = channelQueries.map((c) => c.channelCid).toList(); + final query = select(channels)..where((c) => c.cid.isIn(cids)); + + sort = sort + ?.where((s) => ChannelModel.topLevelFields.contains(s.field)) + ?.toList(); + + if (sort != null && sort.isNotEmpty) { + query.orderBy(sort.map((s) { + final orderExpression = CustomExpression('channels.${s.field}'); + return (c) => OrderingTerm( + expression: orderExpression, + mode: s.direction == 1 ? OrderingMode.asc : OrderingMode.desc, + ); + }).toList()); + } + + if (paginationParams != null) { + query.limit( + paginationParams.limit ?? 10, + offset: paginationParams.offset, + ); + } + + return query.join([ + leftOuterJoin(users, channels.createdById.equalsExp(users.id)), + ]).map((row) async { + final userEntity = row.readTable(users); + final channelEntity = row.readTable(channels); + + final cid = channelEntity.cid; + final members = await _db.memberDao.getMembersByCid(cid); + final reads = await _db.readDao.getReadsByCid(cid); + final messages = await _db.messageDao.getMessagesByCid(cid); + + return channelEntity.toChannelState( + createdBy: userEntity?.toUser(), + members: members, + reads: reads, + messages: messages, + ); + }).get(); + })); + + if (sort?.isEmpty != false && cachedChannels?.isNotEmpty == true) { + cachedChannels + .sort((a, b) => b.channel.updatedAt.compareTo(a.channel.updatedAt)); + cachedChannels.sort((a, b) { + final dateA = a.channel.lastMessageAt ?? a.channel.createdAt; + final dateB = b.channel.lastMessageAt ?? b.channel.createdAt; + return dateB.compareTo(dateA); + }); + } + + return cachedChannels; + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart new file mode 100644 index 00000000..59d22010 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart @@ -0,0 +1,58 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/connection_events.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; +import '../mapper/mapper.dart'; + +part 'connection_event_dao.g.dart'; + +/// +@UseDao(tables: [ConnectionEvents, Users]) +class ConnectionEventDao extends DatabaseAccessor + with _$ConnectionEventDaoMixin { + /// + ConnectionEventDao(MoorChatDatabase db) : super(db); + + /// Get the latest stored connection event + Future get connectionEvent { + return select(connectionEvents).join([ + leftOuterJoin(users, connectionEvents.ownUserId.equalsExp(users.id)), + ]).map((rows) { + final event = rows.readTable(connectionEvents); + final user = rows.readTable(users); + return event.toEvent(user: user?.toUser()); + }).getSingle(); + } + + /// Get the latest stored lastSyncAt + Future get lastSyncAt { + return select(connectionEvents).getSingle().then((r) => r?.lastSyncAt); + } + + /// Update stored connection event with latest data + Future updateConnectionEvent(Event event) async { + final connectionInfo = await select(connectionEvents).getSingle(); + return into(connectionEvents).insert( + ConnectionEventEntity( + id: 1, + lastSyncAt: connectionInfo?.lastSyncAt, + lastEventAt: event.createdAt ?? connectionInfo?.lastEventAt, + totalUnreadCount: + event.totalUnreadCount ?? connectionInfo?.totalUnreadCount, + ownUserId: event.me?.id ?? connectionInfo?.ownUserId, + unreadChannels: event.unreadChannels ?? connectionInfo?.unreadChannels, + ), + mode: InsertMode.insertOrReplace, + ); + } + + /// Update stored lastSyncAt with latest data + Future updateLastSyncAt(DateTime lastSyncAt) async { + return (update(connectionEvents)..where((tbl) => tbl.id.equals(1))).write( + ConnectionEventsCompanion( + lastSyncAt: Value(lastSyncAt), + ), + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/dao.dart b/packages/stream_chat_persistence/lib/src/dao/dao.dart new file mode 100644 index 00000000..6f1e8221 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/dao.dart @@ -0,0 +1,8 @@ +export 'user_dao.dart'; +export 'channel_dao.dart'; +export 'message_dao.dart'; +export 'member_dao.dart'; +export 'connection_event_dao.dart'; +export 'reaction_dao.dart'; +export 'read_dao.dart'; +export 'channel_query_dao.dart'; diff --git a/packages/stream_chat_persistence/lib/src/dao/member_dao.dart b/packages/stream_chat_persistence/lib/src/dao/member_dao.dart new file mode 100644 index 00000000..f21ab334 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/member_dao.dart @@ -0,0 +1,43 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; + +import 'package:stream_chat_persistence/src/entity/members.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; + +import '../mapper/mapper.dart'; + +part 'member_dao.g.dart'; + +/// +@UseDao(tables: [Members, Users]) +class MemberDao extends DatabaseAccessor + with _$MemberDaoMixin { + /// + MemberDao(MoorChatDatabase db) : super(db); + + /// Get all members where [members.channelCid] matches [cid] + Future> getMembersByCid(String cid) async { + return (select(members).join([ + leftOuterJoin(users, members.userId.equalsExp(users.id)), + ]) + ..where(members.channelCid.equals(cid)) + ..orderBy([OrderingTerm.asc(members.createdAt)])) + .map((row) { + final userEntity = row.readTable(users); + final memberEntity = row.readTable(members); + return memberEntity.toMember(user: userEntity?.toUser()); + }).get(); + } + + /// + Future updateMembers(String cid, List memberList) async { + return batch( + (it) => it.insertAll( + members, + memberList.map((m) => m.toEntity(cid: cid)).toList(), + mode: InsertMode.insertOrReplace, + ), + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart new file mode 100644 index 00000000..700f8bed --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -0,0 +1,143 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/messages.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; +import '../mapper/mapper.dart'; + +part 'message_dao.g.dart'; + +/// +@UseDao(tables: [Messages, Users]) +class MessageDao extends DatabaseAccessor + with _$MessageDaoMixin { + /// + MessageDao(this._db) : super(_db); + + final MoorChatDatabase _db; + + /// Removes all the messages by matching [messages.id] in [messageIds] + /// + /// This will automatically delete the following linked records + /// 1. Message Reactions + Future deleteMessageByIds(List messageIds) { + return (delete(messages)..where((tbl) => tbl.id.isIn(messageIds))).go(); + } + + /// Removes all the messages by matching [messages.channelCid] in [cids] + /// + /// This will automatically delete the following linked records + /// 1. Message Reactions + Future deleteMessageByCids(List cids) async { + return (delete(messages)..where((tbl) => tbl.channelCid.isIn(cids))).go(); + } + + Future _messageFromJoinRow(TypedResult rows) async { + final userEntity = rows.readTable(users); + final msgEntity = rows.readTable(messages); + final latestReactions = await _db.reactionDao.getReactions(msgEntity.id); + final ownReactions = await _db.reactionDao.getOwnReactions( + msgEntity.id, + userEntity.id, + ); + Message quotedMessage; + if (msgEntity.quotedMessageId != null) { + quotedMessage = await getMessageById(msgEntity.quotedMessageId); + } + return msgEntity.toMessage( + user: userEntity?.toUser(), + latestReactions: latestReactions, + ownReactions: ownReactions, + quotedMessage: quotedMessage, + ); + } + + /// + Future getMessageById(String id) async { + return await (select(messages).join([ + leftOuterJoin(users, messages.userId.equalsExp(users.id)), + ]) + ..where(messages.id.equals(id))) + .map(_messageFromJoinRow) + .getSingle(); + } + + /// + Future> getThreadMessages(String cid) async { + return Future.wait(await (select(messages).join([ + leftOuterJoin(users, messages.userId.equalsExp(users.id)), + ]) + ..where(messages.channelCid.equals(cid)) + ..where(isNotNull(messages.parentId)) + ..orderBy([OrderingTerm.asc(messages.createdAt)])) + .map(_messageFromJoinRow) + .get()); + } + + /// + Future> getThreadMessagesByParentId( + String parentId, { + String lessThan, + }) async { + final msgList = await Future.wait(await (select(messages).join([ + innerJoin(users, messages.userId.equalsExp(users.id)), + ]) + ..where(messages.parentId.equals(parentId)) + ..orderBy([OrderingTerm.asc(messages.createdAt)])) + .map(_messageFromJoinRow) + .get()); + + if (lessThan != null) { + final lessThanIndex = msgList.indexWhere((m) => m.id == lessThan); + msgList.removeRange(lessThanIndex, msgList.length); + } + return msgList; + } + + /// + Future> getMessagesByCid( + String cid, { + int limit = 20, + String messageLessThan, + String messageGreaterThan, + }) async { + final msgList = await Future.wait(await (select(messages).join([ + leftOuterJoin(users, messages.userId.equalsExp(users.id)), + ]) + ..where(messages.channelCid.equals(cid)) + ..where( + isNull(messages.parentId) | messages.showInChannel.equals(true)) + ..orderBy([OrderingTerm.asc(messages.createdAt)])) + .map(_messageFromJoinRow) + .get()); + + if (messageLessThan != null) { + final lessThanIndex = msgList.indexWhere((m) => m.id == messageLessThan); + if (lessThanIndex != -1) { + msgList.removeRange(lessThanIndex, msgList.length); + } + } + if (messageGreaterThan != null) { + final greaterThanIndex = + msgList.indexWhere((m) => m.id == messageGreaterThan); + if (greaterThanIndex != -1) { + msgList.removeRange(0, greaterThanIndex); + } + } + if (limit != null) { + return msgList.take(limit).toList(); + } + return msgList; + } + + /// + Future updateMessages(String cid, List messageList) { + return batch((batch) { + batch.insertAll( + messages, + messageList.map((it) => it.toEntity(cid: cid)).toList(), + mode: InsertMode.insertOrReplace, + ); + }); + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart new file mode 100644 index 00000000..8df23d44 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart @@ -0,0 +1,50 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/reactions.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; +import '../mapper/mapper.dart'; + +part 'reaction_dao.g.dart'; + +/// +@UseDao(tables: [Reactions, Users]) +class ReactionDao extends DatabaseAccessor + with _$ReactionDaoMixin { + /// + ReactionDao(MoorChatDatabase db) : super(db); + + /// + Future> getReactions(String messageId) { + return (select(reactions).join([ + leftOuterJoin(users, reactions.userId.equalsExp(users.id)), + ]) + ..where(reactions.messageId.equals(messageId)) + ..orderBy([OrderingTerm.asc(reactions.createdAt)])) + .map((rows) { + final userEntity = rows.readTable(users); + final reactionEntity = rows.readTable(reactions); + return reactionEntity.toReaction(user: userEntity?.toUser()); + }).get(); + } + + /// + Future> getOwnReactions( + String messageId, + String userId, + ) async { + final reactions = await getReactions(messageId); + return reactions.where((it) => it.userId == userId).toList(); + } + + /// + Future updateReactions(List reactionList) { + return batch((it) { + it.insertAll( + reactions, + reactionList.map((r) => r.toEntity()).toList(), + mode: InsertMode.insertOrReplace, + ); + }); + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/read_dao.dart b/packages/stream_chat_persistence/lib/src/dao/read_dao.dart new file mode 100644 index 00000000..cd4da0f6 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/read_dao.dart @@ -0,0 +1,42 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/reads.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; +import '../mapper/mapper.dart'; + +part 'read_dao.g.dart'; + +/// +@UseDao(tables: [Reads, Users]) +class ReadDao extends DatabaseAccessor with _$ReadDaoMixin { + /// + ReadDao(MoorChatDatabase db) : super(db); + + /// Get all reads where [reads.channelCid] matches [cid] + Future> getReadsByCid(String cid) async { + return (select(reads).join([ + leftOuterJoin(users, reads.userId.equalsExp(users.id)), + ]) + ..where(reads.channelCid.equals(cid)) + ..orderBy([ + OrderingTerm.asc(reads.lastRead), + ])) + .map((row) { + final userEntity = row.readTable(users); + final readEntity = row.readTable(reads); + return readEntity.toRead(user: userEntity?.toUser()); + }).get(); + } + + /// + Future updateReads(String cid, List readList) { + return batch( + (it) => it.insertAll( + reads, + readList.map((r) => r.toEntity(cid: cid)).toList(), + mode: InsertMode.insertOrReplace, + ), + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/dao/user_dao.dart b/packages/stream_chat_persistence/lib/src/dao/user_dao.dart new file mode 100644 index 00000000..630a8252 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/user_dao.dart @@ -0,0 +1,25 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/users.dart'; +import '../mapper/user_mapper.dart'; + +part 'user_dao.g.dart'; + +/// +@UseDao(tables: [Users]) +class UserDao extends DatabaseAccessor with _$UserDaoMixin { + /// + UserDao(MoorChatDatabase db) : super(db); + + /// + Future updateUsers(List userList) { + return batch( + (it) => it.insertAll( + users, + userList.map((u) => u.toEntity()).toList(), + mode: InsertMode.insertOrReplace, + ), + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart new file mode 100644 index 00000000..21447981 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart @@ -0,0 +1,83 @@ +import 'package:moor/isolate.dart'; +import 'package:moor/moor.dart'; +import 'package:stream_chat/stream_chat.dart'; + +import '../entity/entity.dart'; +import '../dao/dao.dart'; +import 'shared/shared_db.dart'; + +part 'moor_chat_database.g.dart'; + +LazyDatabase _openConnection( + String dbName, { + logStatements = false, +}) { + return LazyDatabase(() async { + return await SharedDB.constructDatabase( + dbName, + logStatements: logStatements, + ); + }); +} + +/// +@UseMoor(tables: [ + Channels, + Messages, + Reactions, + Users, + Members, + Reads, + ChannelQueries, + ConnectionEvents, +], daos: [ + UserDao, + ChannelDao, + MessageDao, + MemberDao, + ReactionDao, + ReadDao, + ChannelQueryDao, + ConnectionEventDao, +]) +class MoorChatDatabase extends _$MoorChatDatabase { + /// Instantiate a new database instance + MoorChatDatabase( + String dbName, { + logStatements = false, + }) : super(_openConnection( + dbName, + logStatements: logStatements, + )); + + /// Instantiate a new database instance + MoorChatDatabase.connect( + this._isolate, + DatabaseConnection connection, + ) : super.connect(connection); + + MoorIsolate _isolate; + + // you should bump this number whenever you change or add a table definition. + @override + int get schemaVersion => 1; + + @override + MigrationStrategy get migration => MigrationStrategy( + onUpgrade: (openingDetails, before, after) async { + if (before != after) { + final m = createMigrator(); + for (final table in allTables) { + await m.deleteTable(table.actualTableName); + await m.createTable(table); + } + } + }, + ); + + /// Closes the database instance + Future disconnect() async { + await _isolate?.shutdownAll(); + await close(); + } +} diff --git a/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart new file mode 100644 index 00000000..198b9010 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart @@ -0,0 +1,87 @@ +//ignore_for_file: public_member_api_docs + +import 'dart:io'; +import 'dart:isolate'; +import 'package:moor/ffi.dart'; +import 'package:moor/isolate.dart'; +import 'package:moor/moor.dart'; +import 'package:path/path.dart'; +import 'package:path_provider/path_provider.dart'; + +import '../moor_chat_database.dart'; + +class SharedDB { + static Future constructDatabase( + String dbName, { + bool logStatements = false, + }) async { + if (Platform.isIOS || Platform.isAndroid) { + final dir = await getApplicationDocumentsDirectory(); + final path = join(dir.path, '$dbName.sqlite'); + final file = File(path); + return VmDatabase(file, logStatements: logStatements); + } + if (Platform.isMacOS || Platform.isLinux) { + final file = File('$dbName.sqlite'); + return VmDatabase(file, logStatements: logStatements); + } + return VmDatabase.memory(logStatements: logStatements); + } + + static void _startBackground(_IsolateStartRequest request) { + final executor = LazyDatabase(() async { + return VmDatabase( + File(request.targetPath), + logStatements: request.logStatements, + ); + }); + final moorIsolate = MoorIsolate.inCurrent( + () => DatabaseConnection.fromExecutor(executor), + ); + request.sendMoorIsolate.send(moorIsolate); + } + + static Future _createMoorIsolate( + String dbName, { + bool logStatements = false, + }) async { + final dir = await getApplicationDocumentsDirectory(); + final path = join(dir.path, '$dbName.sqlite'); + + final receivePort = ReceivePort(); + await Isolate.spawn( + _startBackground, + _IsolateStartRequest( + receivePort.sendPort, + path, + logStatements: logStatements, + ), + ); + + return (await receivePort.first as MoorIsolate); + } + + static Future constructOfflineStorage( + String dbName, { + bool logStatements = false, + }) async { + final isolate = await _createMoorIsolate( + dbName, + logStatements: logStatements, + ); + final connection = await isolate.connect(); + return MoorChatDatabase.connect(isolate, connection); + } +} + +class _IsolateStartRequest { + final SendPort sendMoorIsolate; + final String targetPath; + final bool logStatements; + + const _IsolateStartRequest( + this.sendMoorIsolate, + this.targetPath, { + this.logStatements = false, + }); +} diff --git a/packages/stream_chat_persistence/lib/src/db/shared/shared_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/shared_db.dart new file mode 100644 index 00000000..25120fcf --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/db/shared/shared_db.dart @@ -0,0 +1,3 @@ +export 'unsupported_db.dart' + if (dart.library.io) 'native_db.dart' // implementation using dart:io + if (dart.library.html) 'web_db.dart'; diff --git a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart new file mode 100644 index 00000000..7415fdba --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart @@ -0,0 +1,18 @@ +//ignore_for_file: public_member_api_docs +//ignore_for_file: always_declare_return_types + +class SharedDB { + static constructDatabase( + String dbName, { + bool logStatements = false, + }) { + throw 'Unsupported Platform'; + } + + static constructOfflineStorage( + String dbName, { + logStatements = false, + }) { + throw 'Unsupported Platform'; + } +} diff --git a/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart new file mode 100644 index 00000000..31b4f4b6 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart @@ -0,0 +1,21 @@ +//ignore_for_file: public_member_api_docs +//ignore_for_file: always_declare_return_types +import 'package:moor/moor_web.dart'; + +import '../moor_chat_database.dart'; + +class SharedDB { + static constructDatabase( + String dbName, { + bool logStatements = false, + }) async { + return WebDatabase(dbName, logStatements: logStatements); + } + + static Future constructOfflineStorage( + String dbName, { + bool logStatements = false, + }) async { + return MoorChatDatabase(dbName, logStatements: logStatements); + } +} diff --git a/packages/stream_chat_persistence/lib/src/db/stream_chat_database_impl.dart b/packages/stream_chat_persistence/lib/src/db/stream_chat_database_impl.dart new file mode 100644 index 00000000..de9bbe45 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/db/stream_chat_database_impl.dart @@ -0,0 +1,222 @@ +import 'package:stream_chat/stream_chat.dart'; + +import 'moor_chat_database.dart'; +import 'shared/shared_db.dart'; + +/// +class StreamChatDatabaseImpl implements StreamChatDatabase { + /// + StreamChatDatabaseImpl( + this._userId, { + Logger logger, + }) : _logger = logger, + assert(_userId != null); + + final String _userId; + final Logger _logger; + MoorChatDatabase _db; + + bool get _debugAssertConnected { + assert(() { + if (_db == null) { + throw Exception( + 'A $runtimeType was used after being disconnected.\n' + 'Once you have called disconnect() on a $runtimeType, it can no longer be used.', + ); + } + return true; + }()); + return true; + } + + @override + Future connect({ + bool connectBackground = false, + bool logStatements = false, + }) async { + if (_db != null) { + throw Exception( + 'An instance of StreamChatDatabase is already connected.\n' + 'disconnect the previous instance before connecting again.', + ); + } + + final dbName = 'db_$_userId'; + if (connectBackground) { + _logger?.info('Connecting on background isolate'); + _db = await SharedDB.constructOfflineStorage( + dbName, + logStatements: logStatements, + ); + } else { + _logger?.info('Connecting on a regular isolate'); + _db = MoorChatDatabase(dbName, logStatements: logStatements); + } + } + + @override + Future getConnectionInfo() { + return _db.connectionEventDao.connectionEvent; + } + + @override + Future updateConnectionInfo(Event event) { + return _db.connectionEventDao.updateConnectionEvent(event); + } + + @override + Future updateLastSyncAt(DateTime lastSyncAt) { + return _db.connectionEventDao.updateLastSyncAt(lastSyncAt); + } + + @override + Future getLastSyncAt() { + return _db.connectionEventDao.lastSyncAt; + } + + @override + Future deleteChannelByCids(List cids) { + return _db.channelDao.deleteChannelByCids(cids); + } + + @override + Future> getChannelCids() => _db.channelDao.cids; + + @override + Future deleteMessageByIds(List messageIds) { + return _db.messageDao.deleteMessageByIds(messageIds); + } + + @override + Future deleteMessageByCids(List cids) { + return _db.messageDao.deleteMessageByCids(cids); + } + + @override + Future> getMembersByCid(String cid) { + return _db.memberDao.getMembersByCid(cid); + } + + @override + Future getChannelByCid(String cid) { + return _db.channelDao.getChannelByCid(cid); + } + + @override + Future> getMessagesByCid( + String cid, { + int limit = 20, + String messageLessThan, + String messageGreaterThan, + }) { + return _db.messageDao.getMessagesByCid( + cid, + limit: limit, + messageLessThan: messageLessThan, + messageGreaterThan: messageGreaterThan, + ); + } + + @override + Future> getReadsByCid(String cid) { + return _db.readDao.getReadsByCid(cid); + } + + @override + Future>> getChannelThreads(String cid) async { + final messages = await _db.messageDao.getThreadMessages(cid); + final messageByParentIdDictionary = >{}; + for (final message in messages) { + final parentId = message.parentId; + messageByParentIdDictionary[parentId] = [ + ...messageByParentIdDictionary[parentId] ?? [], + message + ]; + } + return messageByParentIdDictionary; + } + + @override + Future> getReplies( + String parentId, { + String lessThan, + }) { + return _db.messageDao.getThreadMessagesByParentId( + parentId, + lessThan: lessThan, + ); + } + + @override + Future> getChannelStates({ + Map filter, + List sort = const [], + PaginationParams paginationParams, + }) { + return _db.channelQueryDao.getChannelStates( + filter: filter, + sort: sort, + paginationParams: paginationParams, + ); + } + + @override + Future updateChannelQueries( + Map filter, + List cids, + bool clearQueryCache, + ) { + return _db.channelQueryDao.updateChannelQueries( + filter, + cids, + clearQueryCache, + ); + } + + @override + Future updateChannels(List channels) { + return _db.channelDao.updateChannels(channels); + } + + @override + Future updateMembers(String cid, List members) { + return _db.memberDao.updateMembers(cid, members); + } + + @override + Future updateMessages(String cid, List messages) { + return _db.messageDao.updateMessages(cid, messages); + } + + @override + Future updateReactions(List reactions) { + return _db.reactionDao.updateReactions(reactions); + } + + @override + Future updateReads(String cid, List reads) { + return _db.readDao.updateReads(cid, reads); + } + + @override + Future updateUsers(List users) { + return _db.userDao.updateUsers(users); + } + + @override + Future disconnect({bool flush = false}) async { + if (_db != null) { + _logger?.info('Disconnecting'); + if (flush) { + _logger?.info('Flushing'); + await _db.batch((batch) { + _db.allTables.forEach((table) { + _db.delete(table).go(); + }); + }); + } + await _db.disconnect(); + _db = null; + } + } +} diff --git a/packages/stream_chat_persistence/lib/src/entity/channel_queries.dart b/packages/stream_chat_persistence/lib/src/entity/channel_queries.dart new file mode 100644 index 00000000..fefdc925 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/channel_queries.dart @@ -0,0 +1,14 @@ +import 'package:moor/moor.dart'; + +@DataClassName('ChannelQueryEntity') +class ChannelQueries extends Table { + TextColumn get queryHash => text()(); + + TextColumn get channelCid => text()(); + + @override + Set get primaryKey => { + queryHash, + channelCid, + }; +} diff --git a/packages/stream_chat_persistence/lib/src/entity/channels.dart b/packages/stream_chat_persistence/lib/src/entity/channels.dart new file mode 100644 index 00000000..9f652ed1 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/channels.dart @@ -0,0 +1,32 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat_persistence/src/converter/map_converter.dart'; + +@DataClassName('ChannelEntity') +class Channels extends Table { + TextColumn get id => text()(); + + TextColumn get type => text()(); + + TextColumn get cid => text()(); + + TextColumn get config => text().map(MapConverter())(); + + BoolColumn get frozen => boolean().withDefault(Constant(false))(); + + DateTimeColumn get lastMessageAt => dateTime().nullable()(); + + DateTimeColumn get createdAt => dateTime().nullable()(); + + DateTimeColumn get updatedAt => dateTime().nullable()(); + + DateTimeColumn get deletedAt => dateTime().nullable()(); + + IntColumn get memberCount => integer().nullable()(); + + TextColumn get createdById => text().nullable()(); + + TextColumn get extraData => text().nullable().map(MapConverter())(); + + @override + Set get primaryKey => {cid}; +} diff --git a/packages/stream_chat_persistence/lib/src/entity/connection_events.dart b/packages/stream_chat_persistence/lib/src/entity/connection_events.dart new file mode 100644 index 00000000..311f2da0 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/connection_events.dart @@ -0,0 +1,19 @@ +import 'package:moor/moor.dart'; + +@DataClassName('ConnectionEventEntity') +class ConnectionEvents extends Table { + IntColumn get id => integer()(); + + TextColumn get ownUserId => text().nullable()(); + + IntColumn get totalUnreadCount => integer().nullable()(); + + IntColumn get unreadChannels => integer().nullable()(); + + DateTimeColumn get lastEventAt => dateTime().nullable()(); + + DateTimeColumn get lastSyncAt => dateTime().nullable()(); + + @override + Set get primaryKey => {id}; +} diff --git a/packages/stream_chat_persistence/lib/src/entity/entity.dart b/packages/stream_chat_persistence/lib/src/entity/entity.dart new file mode 100644 index 00000000..8751f538 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/entity.dart @@ -0,0 +1,8 @@ +export 'channels.dart'; +export 'messages.dart'; +export 'reactions.dart'; +export 'users.dart'; +export 'members.dart'; +export 'reads.dart'; +export 'channel_queries.dart'; +export 'connection_events.dart'; diff --git a/packages/stream_chat_persistence/lib/src/entity/members.dart b/packages/stream_chat_persistence/lib/src/entity/members.dart new file mode 100644 index 00000000..39e224e0 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/members.dart @@ -0,0 +1,33 @@ +import 'package:moor/moor.dart'; + +@DataClassName('MemberEntity') +class Members extends Table { + TextColumn get userId => text()(); + + TextColumn get channelCid => + text().customConstraint('REFERENCES channels(cid) ON DELETE CASCADE')(); + + TextColumn get role => text().nullable()(); + + DateTimeColumn get inviteAcceptedAt => dateTime().nullable()(); + + DateTimeColumn get inviteRejectedAt => dateTime().nullable()(); + + BoolColumn get invited => boolean().nullable()(); + + BoolColumn get banned => boolean().nullable()(); + + BoolColumn get shadowBanned => boolean().nullable()(); + + BoolColumn get isModerator => boolean().nullable()(); + + DateTimeColumn get createdAt => dateTime()(); + + DateTimeColumn get updatedAt => dateTime().nullable()(); + + @override + Set get primaryKey => { + userId, + channelCid, + }; +} diff --git a/packages/stream_chat_persistence/lib/src/entity/messages.dart b/packages/stream_chat_persistence/lib/src/entity/messages.dart new file mode 100644 index 00000000..10c98315 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/messages.dart @@ -0,0 +1,54 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat_persistence/src/converter/list_converter.dart'; +import 'package:stream_chat_persistence/src/converter/map_converter.dart'; +import 'package:stream_chat_persistence/src/converter/message_sending_status_converter.dart'; + +@DataClassName('MessageEntity') +class Messages extends Table { + TextColumn get id => text()(); + + TextColumn get messageText => text().nullable()(); + + TextColumn get attachments => + text().nullable().map(ListConverter())(); + + IntColumn get status => + integer().nullable().map(MessageSendingStatusConverter())(); + + TextColumn get type => text().nullable()(); + + TextColumn get mentionedUsers => + text().nullable().map(ListConverter())(); + + TextColumn get reactionCounts => text().nullable().map(MapConverter())(); + + TextColumn get reactionScores => text().nullable().map(MapConverter())(); + + TextColumn get parentId => text().nullable()(); + + TextColumn get quotedMessageId => text().nullable()(); + + IntColumn get replyCount => integer().nullable()(); + + BoolColumn get showInChannel => boolean().nullable()(); + + BoolColumn get shadowed => boolean().nullable()(); + + TextColumn get command => text().nullable()(); + + DateTimeColumn get createdAt => dateTime()(); + + DateTimeColumn get updatedAt => dateTime().nullable()(); + + DateTimeColumn get deletedAt => dateTime().nullable()(); + + TextColumn get userId => text().nullable()(); + + TextColumn get channelCid => text().nullable().customConstraint( + 'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE')(); + + TextColumn get extraData => text().nullable().map(MapConverter())(); + + @override + Set get primaryKey => {id}; +} diff --git a/packages/stream_chat_persistence/lib/src/entity/reactions.dart b/packages/stream_chat_persistence/lib/src/entity/reactions.dart new file mode 100644 index 00000000..a20ffbeb --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/reactions.dart @@ -0,0 +1,25 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat_persistence/src/converter/map_converter.dart'; + +@DataClassName('ReactionEntity') +class Reactions extends Table { + TextColumn get userId => text()(); + + TextColumn get messageId => + text().customConstraint('REFERENCES messages(id) ON DELETE CASCADE')(); + + TextColumn get type => text()(); + + DateTimeColumn get createdAt => dateTime()(); + + IntColumn get score => integer().nullable()(); + + TextColumn get extraData => text().nullable().map(MapConverter())(); + + @override + Set get primaryKey => { + messageId, + type, + userId, + }; +} diff --git a/packages/stream_chat_persistence/lib/src/entity/reads.dart b/packages/stream_chat_persistence/lib/src/entity/reads.dart new file mode 100644 index 00000000..c36dceef --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/reads.dart @@ -0,0 +1,19 @@ +import 'package:moor/moor.dart'; + +@DataClassName('ReadEntity') +class Reads extends Table { + DateTimeColumn get lastRead => dateTime()(); + + TextColumn get userId => text()(); + + TextColumn get channelCid => + text().customConstraint('REFERENCES channels(cid) ON DELETE CASCADE')(); + + IntColumn get unreadMessages => integer().nullable()(); + + @override + Set get primaryKey => { + userId, + channelCid, + }; +} diff --git a/packages/stream_chat_persistence/lib/src/entity/users.dart b/packages/stream_chat_persistence/lib/src/entity/users.dart new file mode 100644 index 00000000..4beee396 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/users.dart @@ -0,0 +1,24 @@ +import 'package:moor/moor.dart'; +import 'package:stream_chat_persistence/src/converter/map_converter.dart'; + +@DataClassName('UserEntity') +class Users extends Table { + TextColumn get id => text()(); + + TextColumn get role => text().nullable()(); + + DateTimeColumn get createdAt => dateTime().nullable()(); + + DateTimeColumn get updatedAt => dateTime().nullable()(); + + DateTimeColumn get lastActive => dateTime().nullable()(); + + BoolColumn get online => boolean().nullable()(); + + BoolColumn get banned => boolean().nullable()(); + + TextColumn get extraData => text().nullable().map(MapConverter())(); + + @override + Set get primaryKey => {id}; +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart new file mode 100644 index 00000000..cdabf17f --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart @@ -0,0 +1,61 @@ +import 'package:stream_chat/stream_chat.dart'; +import 'user_mapper.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; + +/// +extension ChannelEntityX on ChannelEntity { + /// + ChannelModel toChannelModel({User createdBy}) { + final config = ChannelConfig.fromJson(this.config ?? {}); + return ChannelModel( + id: id, + config: config, + type: type, + frozen: frozen, + createdAt: createdAt, + updatedAt: updatedAt, + memberCount: memberCount, + cid: cid, + lastMessageAt: lastMessageAt, + deletedAt: deletedAt, + extraData: extraData, + createdBy: createdBy, + ); + } + + /// + ChannelState toChannelState({ + User createdBy, + List members, + List reads, + List messages, + }) { + return ChannelState( + members: members, + read: reads, + messages: messages, + channel: toChannelModel(createdBy: createdBy), + ); + } +} + +/// +extension ChannelModelX on ChannelModel { + /// + ChannelEntity toEntity() { + return ChannelEntity( + id: id, + type: type, + cid: cid, + config: config.toJson(), + frozen: frozen, + lastMessageAt: lastMessageAt, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + memberCount: memberCount, + createdById: createdBy.id, + extraData: extraData, + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart new file mode 100644 index 00000000..41e90205 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart @@ -0,0 +1,15 @@ +import 'package:stream_chat/stream_chat.dart'; +import 'user_mapper.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; + +/// +extension ConnectionEventX on ConnectionEventEntity { + /// + Event toEvent({User user}) { + return Event( + me: user, + totalUnreadCount: totalUnreadCount, + unreadChannels: unreadChannels, + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/mapper.dart new file mode 100644 index 00000000..efedde22 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/mapper.dart @@ -0,0 +1,7 @@ +export 'user_mapper.dart'; +export 'reaction_mapper.dart'; +export 'channel_mapper.dart'; +export 'event_mapper.dart'; +export 'member_mapper.dart'; +export 'read_mapper.dart'; +export 'message_mapper.dart'; \ No newline at end of file diff --git a/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart new file mode 100644 index 00000000..42f463ba --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart @@ -0,0 +1,43 @@ +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'user_mapper.dart'; + +/// +extension MemberEntityX on MemberEntity { + /// + Member toMember({User user}) { + return Member( + user: user, + userId: userId, + banned: banned, + shadowBanned: shadowBanned, + updatedAt: updatedAt, + createdAt: createdAt, + role: role, + inviteAcceptedAt: inviteAcceptedAt, + invited: invited, + inviteRejectedAt: inviteRejectedAt, + isModerator: isModerator, + ); + } +} + +/// +extension MemberX on Member { + /// + MemberEntity toEntity({String cid}) { + return MemberEntity( + userId: user?.id, + banned: banned, + shadowBanned: shadowBanned, + channelCid: cid, + createdAt: createdAt, + isModerator: isModerator, + inviteRejectedAt: inviteRejectedAt, + invited: invited, + inviteAcceptedAt: inviteAcceptedAt, + role: role, + updatedAt: updatedAt, + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart new file mode 100644 index 00000000..4ea001a1 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart @@ -0,0 +1,70 @@ +import 'dart:convert'; + +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; + +/// +extension MessageEntityX on MessageEntity { + /// + Message toMessage({ + User user, + List latestReactions, + List ownReactions, + Message quotedMessage, + }) { + return Message( + shadowed: shadowed, + latestReactions: latestReactions, + ownReactions: ownReactions, + attachments: attachments?.map((it) { + final json = jsonDecode(it); + return Attachment.fromJson(json); + })?.toList(), + createdAt: createdAt, + extraData: extraData, + updatedAt: updatedAt, + id: id, + type: type, + status: status, + command: command, + parentId: parentId, + quotedMessageId: quotedMessageId, + quotedMessage: quotedMessage, + reactionCounts: reactionCounts, + reactionScores: reactionScores, + replyCount: replyCount, + showInChannel: showInChannel, + text: messageText, + user: user, + deletedAt: deletedAt, + ); + } +} + +/// +extension MessageX on Message { + /// + MessageEntity toEntity({String cid}) { + return MessageEntity( + id: id, + attachments: attachments.map((it) => jsonEncode(it)).toList(), + channelCid: cid, + type: type, + parentId: parentId, + quotedMessageId: quotedMessageId, + command: command, + createdAt: createdAt, + shadowed: shadowed, + showInChannel: showInChannel, + replyCount: replyCount, + reactionScores: reactionScores, + reactionCounts: reactionCounts, + status: status, + updatedAt: updatedAt, + extraData: extraData, + userId: user?.id, + deletedAt: deletedAt, + messageText: text, + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart new file mode 100644 index 00000000..d468d11c --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart @@ -0,0 +1,33 @@ +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; + +/// +extension ReactionEntityX on ReactionEntity { + /// + Reaction toReaction({User user}) { + return Reaction( + extraData: extraData, + type: type, + createdAt: createdAt, + userId: userId, + user: user, + messageId: messageId, + score: score, + ); + } +} + +/// +extension ReactionX on Reaction { + /// + ReactionEntity toEntity() { + return ReactionEntity( + extraData: extraData, + type: type, + createdAt: createdAt, + userId: userId, + messageId: messageId, + score: score, + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart new file mode 100644 index 00000000..0f9ea560 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart @@ -0,0 +1,28 @@ +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; +import 'user_mapper.dart'; + +/// +extension ReadEntityX on ReadEntity { + /// + Read toRead({User user}) { + return Read( + user: user, + lastRead: lastRead, + unreadMessages: unreadMessages, + ); + } +} + +/// +extension ReadX on Read { + /// + ReadEntity toEntity({String cid}) { + return ReadEntity( + lastRead: lastRead, + userId: user?.id, + channelCid: cid, + unreadMessages: unreadMessages, + ); + } +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart new file mode 100644 index 00000000..cb775ab7 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart @@ -0,0 +1,36 @@ +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; + +/// +extension UserEntityX on UserEntity { + /// + User toUser() { + return User( + id: id, + updatedAt: updatedAt, + role: role, + online: online, + lastActive: lastActive, + extraData: extraData, + banned: banned, + createdAt: createdAt, + ); + } +} + +/// +extension UserX on User { + /// + UserEntity toEntity() { + return UserEntity( + id: id, + role: role, + createdAt: createdAt, + updatedAt: updatedAt, + lastActive: lastActive, + online: online, + banned: banned, + extraData: extraData, + ); + } +} diff --git a/packages/stream_chat_persistence/lib/stream_chat_persistence.dart b/packages/stream_chat_persistence/lib/stream_chat_persistence.dart new file mode 100644 index 00000000..3388d36e --- /dev/null +++ b/packages/stream_chat_persistence/lib/stream_chat_persistence.dart @@ -0,0 +1,3 @@ +library stream_chat_persistence; + +export 'src/db/stream_chat_database_impl.dart'; diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml new file mode 100644 index 00000000..9ba42d1a --- /dev/null +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -0,0 +1,18 @@ +name: stream_chat_persistence +description: A new Flutter package. +version: 0.0.1 +author: +homepage: + +environment: + sdk: ">=2.7.0 <3.0.0" + +dependencies: + moor: ^3.4.0 + stream_chat: + path: ../dart_client + +dev_dependencies: + test: ^1.15.7 + build_runner: ^1.10.13 + moor_generator: ^3.4.1 From 82fee14f68ba537958d7d80f987b72589f46a69d Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 25 Jan 2021 19:23:38 +0530 Subject: [PATCH 03/46] [StreamChatPersistence] Ran formatter Signed-off-by: Sahil Kumar --- packages/stream_chat_persistence/lib/src/mapper/mapper.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat_persistence/lib/src/mapper/mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/mapper.dart index efedde22..8d19729d 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/mapper.dart @@ -4,4 +4,4 @@ export 'channel_mapper.dart'; export 'event_mapper.dart'; export 'member_mapper.dart'; export 'read_mapper.dart'; -export 'message_mapper.dart'; \ No newline at end of file +export 'message_mapper.dart'; From a168d3695d9e164a5ca5fcfad40a39b49917a394 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 26 Jan 2021 15:58:11 +0530 Subject: [PATCH 04/46] [StreamChatPersistence] Fix connectionEventEntity, MessageDao Signed-off-by: Sahil Kumar --- .../lib/src/converter/converter.dart | 3 +++ .../lib/src/dao/connection_event_dao.dart | 10 +++----- .../lib/src/dao/message_dao.dart | 23 ++++++++++--------- .../lib/src/db/moor_chat_database.dart | 1 + .../lib/src/entity/connection_events.dart | 3 ++- .../lib/src/mapper/event_mapper.dart | 4 ++-- ...dart => stream_chat_persistence_impl.dart} | 18 ++++++--------- .../lib/stream_chat_persistence.dart | 2 +- packages/stream_chat_persistence/pubspec.yaml | 5 +++- 9 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 packages/stream_chat_persistence/lib/src/converter/converter.dart rename packages/stream_chat_persistence/lib/src/{db/stream_chat_database_impl.dart => stream_chat_persistence_impl.dart} (92%) diff --git a/packages/stream_chat_persistence/lib/src/converter/converter.dart b/packages/stream_chat_persistence/lib/src/converter/converter.dart new file mode 100644 index 00000000..f32f4b54 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/converter/converter.dart @@ -0,0 +1,3 @@ +export 'list_converter.dart'; +export 'map_converter.dart'; +export 'message_sending_status_converter.dart'; \ No newline at end of file diff --git a/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart index 59d22010..baf91095 100644 --- a/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart @@ -16,12 +16,8 @@ class ConnectionEventDao extends DatabaseAccessor /// Get the latest stored connection event Future get connectionEvent { - return select(connectionEvents).join([ - leftOuterJoin(users, connectionEvents.ownUserId.equalsExp(users.id)), - ]).map((rows) { - final event = rows.readTable(connectionEvents); - final user = rows.readTable(users); - return event.toEvent(user: user?.toUser()); + return select(connectionEvents).map((eventEntity) { + return eventEntity.toEvent(); }).getSingle(); } @@ -40,7 +36,7 @@ class ConnectionEventDao extends DatabaseAccessor lastEventAt: event.createdAt ?? connectionInfo?.lastEventAt, totalUnreadCount: event.totalUnreadCount ?? connectionInfo?.totalUnreadCount, - ownUserId: event.me?.id ?? connectionInfo?.ownUserId, + ownUser: event.me?.toJson() ?? connectionInfo?.ownUser, unreadChannels: event.unreadChannels ?? connectionInfo?.unreadChannels, ), mode: InsertMode.insertOrReplace, diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart index 700f8bed..320cb022 100644 --- a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -97,9 +97,7 @@ class MessageDao extends DatabaseAccessor /// Future> getMessagesByCid( String cid, { - int limit = 20, - String messageLessThan, - String messageGreaterThan, + PaginationParams messagePagination, }) async { final msgList = await Future.wait(await (select(messages).join([ leftOuterJoin(users, messages.userId.equalsExp(users.id)), @@ -111,27 +109,30 @@ class MessageDao extends DatabaseAccessor .map(_messageFromJoinRow) .get()); - if (messageLessThan != null) { - final lessThanIndex = msgList.indexWhere((m) => m.id == messageLessThan); + if (messagePagination.lessThan != null) { + final lessThanIndex = msgList.indexWhere( + (m) => m.id == messagePagination.lessThan, + ); if (lessThanIndex != -1) { msgList.removeRange(lessThanIndex, msgList.length); } } - if (messageGreaterThan != null) { - final greaterThanIndex = - msgList.indexWhere((m) => m.id == messageGreaterThan); + if (messagePagination.greaterThanOrEqual != null) { + final greaterThanIndex = msgList.indexWhere( + (m) => m.id == messagePagination.greaterThanOrEqual, + ); if (greaterThanIndex != -1) { msgList.removeRange(0, greaterThanIndex); } } - if (limit != null) { - return msgList.take(limit).toList(); + if (messagePagination.limit != null) { + return msgList.take(messagePagination.limit).toList(); } return msgList; } /// - Future updateMessages(String cid, List messageList) { + Future updateMessages(String cid, List messageList) { return batch((batch) { batch.insertAll( messages, diff --git a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart index 21447981..e32c3e3c 100644 --- a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart @@ -4,6 +4,7 @@ import 'package:stream_chat/stream_chat.dart'; import '../entity/entity.dart'; import '../dao/dao.dart'; +import '../converter/converter.dart'; import 'shared/shared_db.dart'; part 'moor_chat_database.g.dart'; diff --git a/packages/stream_chat_persistence/lib/src/entity/connection_events.dart b/packages/stream_chat_persistence/lib/src/entity/connection_events.dart index 311f2da0..3ca4592e 100644 --- a/packages/stream_chat_persistence/lib/src/entity/connection_events.dart +++ b/packages/stream_chat_persistence/lib/src/entity/connection_events.dart @@ -1,10 +1,11 @@ import 'package:moor/moor.dart'; +import 'package:stream_chat_persistence/src/converter/map_converter.dart'; @DataClassName('ConnectionEventEntity') class ConnectionEvents extends Table { IntColumn get id => integer()(); - TextColumn get ownUserId => text().nullable()(); + TextColumn get ownUser => text().nullable().map(MapConverter())(); IntColumn get totalUnreadCount => integer().nullable()(); diff --git a/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart index 41e90205..9746dc20 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart @@ -5,9 +5,9 @@ import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; /// extension ConnectionEventX on ConnectionEventEntity { /// - Event toEvent({User user}) { + Event toEvent() { return Event( - me: user, + me: ownUser != null ? OwnUser.fromJson(ownUser) : null, totalUnreadCount: totalUnreadCount, unreadChannels: unreadChannels, ); diff --git a/packages/stream_chat_persistence/lib/src/db/stream_chat_database_impl.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_impl.dart similarity index 92% rename from packages/stream_chat_persistence/lib/src/db/stream_chat_database_impl.dart rename to packages/stream_chat_persistence/lib/src/stream_chat_persistence_impl.dart index de9bbe45..2d4caae8 100644 --- a/packages/stream_chat_persistence/lib/src/db/stream_chat_database_impl.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_impl.dart @@ -1,12 +1,12 @@ import 'package:stream_chat/stream_chat.dart'; -import 'moor_chat_database.dart'; -import 'shared/shared_db.dart'; +import 'db/moor_chat_database.dart'; +import 'db/shared/shared_db.dart'; /// -class StreamChatDatabaseImpl implements StreamChatDatabase { +class StreamChatPersistenceImpl extends StreamChatPersistence { /// - StreamChatDatabaseImpl( + StreamChatPersistenceImpl( this._userId, { Logger logger, }) : _logger = logger, @@ -75,7 +75,7 @@ class StreamChatDatabaseImpl implements StreamChatDatabase { } @override - Future deleteChannelByCids(List cids) { + Future deleteChannels(List cids) { return _db.channelDao.deleteChannelByCids(cids); } @@ -105,15 +105,11 @@ class StreamChatDatabaseImpl implements StreamChatDatabase { @override Future> getMessagesByCid( String cid, { - int limit = 20, - String messageLessThan, - String messageGreaterThan, + PaginationParams messagePagination, }) { return _db.messageDao.getMessagesByCid( cid, - limit: limit, - messageLessThan: messageLessThan, - messageGreaterThan: messageGreaterThan, + messagePagination: messagePagination, ); } diff --git a/packages/stream_chat_persistence/lib/stream_chat_persistence.dart b/packages/stream_chat_persistence/lib/stream_chat_persistence.dart index 3388d36e..3d58cb17 100644 --- a/packages/stream_chat_persistence/lib/stream_chat_persistence.dart +++ b/packages/stream_chat_persistence/lib/stream_chat_persistence.dart @@ -1,3 +1,3 @@ library stream_chat_persistence; -export 'src/db/stream_chat_database_impl.dart'; +export 'src/stream_chat_persistence_impl.dart'; diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index 9ba42d1a..a0c97c89 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -9,10 +9,13 @@ environment: dependencies: moor: ^3.4.0 + path: ^1.7.0 + path_provider: ^1.6.27 + sqlite3_flutter_libs: ^0.3.0 stream_chat: path: ../dart_client dev_dependencies: test: ^1.15.7 - build_runner: ^1.10.13 + build_runner: ^1.11.0 moor_generator: ^3.4.1 From b08506062e383512c28730a7f5b36eded3c9085f Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 26 Jan 2021 15:59:05 +0530 Subject: [PATCH 05/46] [StreamChat] Migrate to use `streamChatPersistence` instead of `OfflineStorage` Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/api/channel.dart | 23 +- packages/dart_client/lib/src/client.dart | 54 +- .../dart_client/lib/src/db/models.part.dart | 258 - .../lib/src/db/offline_storage.dart | 841 ---- .../lib/src/db/offline_storage.g.dart | 4160 ----------------- .../lib/src/db/shared/native_db.dart | 65 - .../lib/src/db/shared/shared_db.dart | 3 - .../lib/src/db/shared/unsupported_db.dart | 14 - .../dart_client/lib/src/db/shared/web_db.dart | 20 - .../lib/src/db/stream_chat_database.dart | 97 - .../lib/src/db/stream_chat_persistence.dart | 196 + .../dart_client/lib/src/notifications.dart | 22 +- packages/dart_client/lib/stream_chat.dart | 4 +- packages/dart_client/pubspec.yaml | 5 - packages/flutter_widgets/pubspec.yaml | 3 +- 15 files changed, 253 insertions(+), 5512 deletions(-) delete mode 100644 packages/dart_client/lib/src/db/models.part.dart delete mode 100644 packages/dart_client/lib/src/db/offline_storage.dart delete mode 100644 packages/dart_client/lib/src/db/offline_storage.g.dart delete mode 100644 packages/dart_client/lib/src/db/shared/native_db.dart delete mode 100644 packages/dart_client/lib/src/db/shared/shared_db.dart delete mode 100644 packages/dart_client/lib/src/db/shared/unsupported_db.dart delete mode 100644 packages/dart_client/lib/src/db/shared/web_db.dart delete mode 100644 packages/dart_client/lib/src/db/stream_chat_database.dart create mode 100644 packages/dart_client/lib/src/db/stream_chat_persistence.dart diff --git a/packages/dart_client/lib/src/api/channel.dart b/packages/dart_client/lib/src/api/channel.dart index 01911b83..a8952e34 100644 --- a/packages/dart_client/lib/src/api/channel.dart +++ b/packages/dart_client/lib/src/api/channel.dart @@ -419,7 +419,7 @@ class Channel { } } - await _client.offlineStorage?.deleteMessages([messageId]); + await _client.chatPersistence?.deleteMessageById(messageId); } return res; @@ -487,7 +487,7 @@ class Channel { PaginationParams options, { bool preferOffline = false, }) async { - final cachedReplies = await _client.offlineStorage?.getReplies( + final cachedReplies = await _client.chatPersistence?.getReplies( parentId, lessThan: options?.lessThan, ); @@ -603,11 +603,9 @@ class Channel { } if (preferOffline && cid != null) { - final updatedState = await _client.offlineStorage?.getChannel( + final updatedState = await _client.chatPersistence?.getChannelStateByCid( cid, - limit: messagesPagination?.limit, - messageLessThan: messagesPagination?.lessThan, - messageGreaterThan: messagesPagination?.greaterThan, + messagePagination: messagesPagination, ); if (updatedState != null && updatedState.messages.isNotEmpty) { if (state == null) { @@ -732,7 +730,7 @@ class Channel { if (clearHistory == true) { state.truncate(); - await _client.offlineStorage?.deleteChannelsMessages([_cid]); + await _client.chatPersistence?.deleteMessageByCid(_cid); } return _client.decode(response.data, EmptyResponse.fromJson); @@ -871,7 +869,7 @@ class ChannelClientState { _computeInitialUnread(); - _channel._client.offlineStorage + _channel._client.chatPersistence ?.getChannelThreads(_channel.cid) ?.then((threads) { _threads = threads; @@ -949,8 +947,7 @@ class ChannelClientState { .on(EventType.channelTruncated, EventType.notificationChannelTruncated) .listen((event) async { final channel = event.channel; - await _channel._client.offlineStorage - ?.deleteChannelsMessages([channel.cid]); + await _channel._client.chatPersistence?.deleteMessageByCid(channel.cid); truncate(); })); } @@ -1404,7 +1401,7 @@ class ChannelClientState { set _channelState(ChannelState v) { _channelStateController.add(v); - _channel._client.offlineStorage?.updateChannelState(v); + _channel._client.chatPersistence?.updateChannelState(v); } /// The channel threads related to this channel @@ -1417,9 +1414,9 @@ class ChannelClientState { BehaviorSubject.seeded({}); set _threads(Map> v) { - _channel._client.offlineStorage?.updateMessages( - v.values.expand((v) => v).toList(), + _channel._client.chatPersistence?.updateMessages( _channel.cid, + v.values.expand((v) => v).toList(), ); _threadsController.add(v); } diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index bb026ee7..99350636 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -6,6 +6,7 @@ import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; import 'package:logging/logging.dart'; import 'package:rxdart/rxdart.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stream_chat/src/api/retry_policy.dart'; import 'package:stream_chat/src/event_type.dart'; @@ -20,7 +21,7 @@ import 'api/connection_status.dart'; import 'api/requests.dart'; import 'api/responses.dart'; import 'api/websocket.dart'; -import 'db/offline_storage.dart'; +import 'db/stream_chat_persistence.dart'; import 'exceptions.dart'; import 'models/event.dart'; import 'models/message.dart'; @@ -110,7 +111,7 @@ class Client { logger.info('instantiating new client'); } - OfflineStorage _offlineStorage; + StreamChatPersistence _chatPersistence; /// If true chat data will persist on disk final bool persistenceEnabled; @@ -131,7 +132,7 @@ class Client { final Duration backgroundKeepAlive; /// Client offline database - OfflineStorage get offlineStorage => _offlineStorage; + StreamChatPersistence get chatPersistence => _chatPersistence; /// This client state ClientState state; @@ -344,7 +345,7 @@ class Client { /// Call this function to dispose the client void dispose() async { - await _offlineStorage?.disconnect(); + await _chatPersistence?.disconnect(); await _disconnect(); httpClient.close(); await _controller.close(); @@ -426,8 +427,8 @@ class Client { if (!event.isLocal) { if (_synced && event.createdAt != null) { - await _offlineStorage?.updateConnectionInfo(event); - await _offlineStorage?.updateLastSyncAt(event.createdAt); + await _chatPersistence?.updateConnectionInfo(event); + await _chatPersistence?.updateLastSyncAt(event.createdAt); } } @@ -458,9 +459,12 @@ class Client { wsConnectionStatus.value = ConnectionStatus.connecting; - if (persistenceEnabled && _offlineStorage == null) { - _offlineStorage = - await connectDatabase(state.user, _detachedLogger('💽')); + if (persistenceEnabled && _chatPersistence == null) { + _chatPersistence = StreamChatPersistenceImpl( + state.user.id, + logger: _detachedLogger('💽'), + ); + await _chatPersistence.connect(); } _ws = WebSocket( @@ -510,10 +514,10 @@ class Client { _ws.connectionStatus.addListener(_connectionStatusListener); - var event = await _offlineStorage?.getConnectionInfo(); + var event = await _chatPersistence?.getConnectionInfo(); await _ws.connect().then((e) async { - await _offlineStorage?.updateConnectionInfo(e); + await _chatPersistence?.updateConnectionInfo(e); event = e; await resync(); }).catchError((err, stacktrace) { @@ -528,14 +532,14 @@ class Client { /// Get the events missed while offline to sync the offline storage Future resync([List cids]) async { - final lastSyncAt = await offlineStorage?.getLastSyncAt(); + final lastSyncAt = await chatPersistence?.getLastSyncAt(); if (lastSyncAt == null) { _synced = true; return; } - cids ??= await offlineStorage?.getChannelCids(); + cids ??= await chatPersistence?.getChannelCids(); if (cids?.isEmpty == true) { return; @@ -564,7 +568,7 @@ class Client { handleEvent(event); }); - await _offlineStorage?.updateLastSyncAt(DateTime.now()); + await _chatPersistence?.updateLastSyncAt(DateTime.now()); _synced = true; } catch (error) { logger.severe('Error during resync $error'); @@ -710,7 +714,7 @@ class Client { channels.add(channel); } else { final newChannel = Channel.fromState(this, channelState); - await _offlineStorage + await _chatPersistence ?.updateChannelState(newChannel.state.channelState); newChannel.state?.updateChannelState(channelState); newChannels[newChannel.cid] = newChannel; @@ -721,7 +725,7 @@ class Client { state.channels = newChannels; - await _offlineStorage?.updateChannelQueries( + await _chatPersistence?.updateChannelQueries( filter, res.channels.map((c) => c.channel.cid).toList(), paginationParams?.offset == null || paginationParams.offset == 0, @@ -756,7 +760,7 @@ class Client { @required List sort, PaginationParams paginationParams = const PaginationParams(limit: 10), }) async { - final offlineChannels = await _offlineStorage?.getChannelStates( + final offlineChannels = await _chatPersistence?.getChannelStates( filter: filter, sort: sort, paginationParams: paginationParams, @@ -771,7 +775,7 @@ class Client { return channel; } else { final newChannel = Channel.fromState(this, channelState); - _offlineStorage?.updateChannelState(newChannel.state.channelState); + _chatPersistence?.updateChannelState(newChannel.state.channelState); newChannels[newChannel.cid] = newChannel; return newChannel; } @@ -925,17 +929,17 @@ class Client { } /// Closes the websocket connection and resets the client - /// If [flushOfflineStorage] is true the client deletes all offline user's data + /// If [flushChatPersistence] is true the client deletes all offline user's data /// If [clearUser] is true the client unsets the current user Future disconnect({ - bool flushOfflineStorage = false, + bool flushChatPersistence = false, bool clearUser = false, }) async { logger.info( - 'Disconnecting flushOfflineStorage: $flushOfflineStorage; clearUser: $clearUser'); + 'Disconnecting flushOfflineStorage: $flushChatPersistence; clearUser: $clearUser'); - await _offlineStorage?.disconnect(flush: flushOfflineStorage); - _offlineStorage = null; + await _chatPersistence?.disconnect(flush: flushChatPersistence); + _chatPersistence = null; if (clearUser == true) { state.dispose(); @@ -1324,7 +1328,7 @@ class ClientState { void _listenChannelHidden() { _subscriptions.add(_client.on(EventType.channelHidden).listen((event) { - _client._offlineStorage?.deleteChannels([event.cid]); + _client._chatPersistence?.deleteChannels([event.cid]); if (channels != null) { channels = channels..removeWhere((cid, ch) => cid == event.cid); } @@ -1349,7 +1353,7 @@ class ClientState { ) .listen((Event event) async { final eventChannel = event.channel; - await _client._offlineStorage?.deleteChannels([eventChannel.cid]); + await _client._chatPersistence?.deleteChannels([eventChannel.cid]); if (channels != null) { channels = channels..remove(eventChannel.cid); } diff --git a/packages/dart_client/lib/src/db/models.part.dart b/packages/dart_client/lib/src/db/models.part.dart deleted file mode 100644 index 9a8c5e8e..00000000 --- a/packages/dart_client/lib/src/db/models.part.dart +++ /dev/null @@ -1,258 +0,0 @@ -part of 'offline_storage.dart'; - -@DataClassName('ChannelQuery') -class _ChannelQueries extends Table { - TextColumn get queryHash => text()(); - - TextColumn get channelCid => text()(); - - @override - Set get primaryKey => { - queryHash, - channelCid, - }; -} - -class _Channels extends Table { - TextColumn get id => text()(); - - TextColumn get type => text()(); - - TextColumn get cid => text()(); - - TextColumn get config => text()(); - - BoolColumn get frozen => boolean().withDefault(Constant(false))(); - - DateTimeColumn get lastMessageAt => dateTime().nullable()(); - - DateTimeColumn get createdAt => dateTime().nullable()(); - - DateTimeColumn get updatedAt => dateTime().nullable()(); - - DateTimeColumn get deletedAt => dateTime().nullable()(); - - IntColumn get memberCount => integer().nullable()(); - - TextColumn get extraData => text().nullable().map(_ExtraDataConverter())(); - - TextColumn get createdBy => text().nullable()(); - - @override - Set get primaryKey => {cid}; -} - -class _ConnectionEvent extends Table { - IntColumn get id => integer()(); - - TextColumn get ownUser => text().nullable().map(_ExtraDataConverter())(); - - IntColumn get totalUnreadCount => integer().nullable()(); - - IntColumn get unreadChannels => integer().nullable()(); - - DateTimeColumn get lastEventAt => dateTime().nullable()(); - - DateTimeColumn get lastSyncAt => dateTime().nullable()(); - - @override - Set get primaryKey => {id}; -} - -class _Users extends Table { - TextColumn get id => text()(); - - TextColumn get role => text().nullable()(); - - DateTimeColumn get createdAt => dateTime().nullable()(); - - DateTimeColumn get updatedAt => dateTime().nullable()(); - - DateTimeColumn get lastActive => dateTime().nullable()(); - - BoolColumn get online => boolean().nullable()(); - - BoolColumn get banned => boolean().nullable()(); - - TextColumn get extraData => text().nullable().map(_ExtraDataConverter())(); - - @override - Set get primaryKey => {id}; -} - -class _Reads extends Table { - DateTimeColumn get lastRead => dateTime()(); - - TextColumn get userId => text()(); - - TextColumn get channelCid => text()(); - - IntColumn get unreadMessages => integer().nullable()(); - - @override - Set get primaryKey => { - userId, - channelCid, - }; -} - -class _Reactions extends Table { - TextColumn get messageId => text()(); - - TextColumn get type => text()(); - - DateTimeColumn get createdAt => dateTime()(); - - IntColumn get score => integer().nullable()(); - - TextColumn get userId => text()(); - - TextColumn get extraData => text().nullable().map(_ExtraDataConverter())(); - - @override - Set get primaryKey => { - messageId, - type, - userId, - }; -} - -class _Messages extends Table { - TextColumn get id => text()(); - - TextColumn get messageText => text().nullable()(); - - TextColumn get attachmentJson => text().nullable()(); - - IntColumn get status => - integer().map(_MessageSendingStatusConverter()).nullable()(); - - TextColumn get type => text().nullable()(); - - List mentionedUsers; - - TextColumn get reactionCounts => - text().nullable().map(_ExtraDataConverter())(); - - TextColumn get reactionScores => - text().nullable().map(_ExtraDataConverter())(); - - TextColumn get parentId => text().nullable()(); - - TextColumn get quotedMessageId => text().nullable()(); - - IntColumn get replyCount => integer().nullable()(); - - BoolColumn get showInChannel => boolean().nullable()(); - - BoolColumn get shadowed => boolean().nullable()(); - - TextColumn get command => text().nullable()(); - - DateTimeColumn get createdAt => dateTime()(); - - DateTimeColumn get updatedAt => dateTime().nullable()(); - - DateTimeColumn get deletedAt => dateTime().nullable()(); - - TextColumn get userId => text().nullable()(); - - TextColumn get channelCid => text().nullable()(); - - TextColumn get extraData => text().nullable().map(_ExtraDataConverter())(); - - @override - Set get primaryKey => {id}; -} - -class _Members extends Table { - TextColumn get userId => text()(); - - TextColumn get channelCid => text()(); - - TextColumn get role => text().nullable()(); - - DateTimeColumn get inviteAcceptedAt => dateTime().nullable()(); - - DateTimeColumn get inviteRejectedAt => dateTime().nullable()(); - - BoolColumn get invited => boolean().nullable()(); - - BoolColumn get banned => boolean().nullable()(); - - BoolColumn get shadowBanned => boolean().nullable()(); - - BoolColumn get isModerator => boolean().nullable()(); - - DateTimeColumn get createdAt => dateTime()(); - - DateTimeColumn get updatedAt => dateTime().nullable()(); - - @override - Set get primaryKey => { - userId, - channelCid, - }; -} - -class _ExtraDataConverter extends TypeConverter, String> { - @override - Map mapToDart(fromDb) { - if (fromDb == null) { - return null; - } - return Map.from(jsonDecode(fromDb) ?? {}); - } - - @override - String mapToSql(value) { - return jsonEncode(value); - } -} - -class _MessageSendingStatusConverter - extends TypeConverter { - @override - MessageSendingStatus mapToDart(int fromDb) { - switch (fromDb) { - case 0: - return MessageSendingStatus.sending; - case 1: - return MessageSendingStatus.sent; - case 2: - return MessageSendingStatus.failed; - case 3: - return MessageSendingStatus.updating; - case 4: - return MessageSendingStatus.failed_update; - case 5: - return MessageSendingStatus.deleting; - case 6: - return MessageSendingStatus.failed_delete; - default: - return null; - } - } - - @override - int mapToSql(MessageSendingStatus value) { - switch (value) { - case MessageSendingStatus.sending: - return 0; - case MessageSendingStatus.sent: - return 1; - case MessageSendingStatus.failed: - return 2; - case MessageSendingStatus.updating: - return 3; - case MessageSendingStatus.failed_update: - return 4; - case MessageSendingStatus.deleting: - return 5; - case MessageSendingStatus.failed_delete: - return 6; - default: - return null; - } - } -} diff --git a/packages/dart_client/lib/src/db/offline_storage.dart b/packages/dart_client/lib/src/db/offline_storage.dart deleted file mode 100644 index b132ae02..00000000 --- a/packages/dart_client/lib/src/db/offline_storage.dart +++ /dev/null @@ -1,841 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart' show WidgetsFlutterBinding; -import 'package:logging/logging.dart'; -import 'package:moor/isolate.dart'; -import 'package:moor/moor.dart'; -import 'package:stream_chat/src/db/shared/shared_db.dart'; -import 'package:stream_chat/src/models/event.dart'; -import 'package:stream_chat/src/models/own_user.dart'; - -import '../api/requests.dart'; -import '../models/attachment.dart'; -import '../models/channel_config.dart'; -import '../models/channel_model.dart'; -import '../models/channel_state.dart'; -import '../models/member.dart'; -import '../models/message.dart'; -import '../models/reaction.dart'; -import '../models/read.dart'; -import '../models/user.dart'; - -part 'models.part.dart'; - -part 'offline_storage.g.dart'; - -/// Gets a new instance of the database running on a background isolate -Future connectDatabase(User user, Logger logger) async { - logger.info('Connecting on background isolate'); - WidgetsFlutterBinding.ensureInitialized(); - return SharedDB.constructOfflineStorage( - userId: user.id, - logger: logger, - ); -} - -LazyDatabase _openConnection(String userId) { - moorRuntimeOptions.dontWarnAboutMultipleDatabases = true; - return LazyDatabase(() async { - return await SharedDB.constructDatabase('db_$userId.sqlite'); - }); -} - -/// Offline database used for caching channel queries and state -@UseMoor(tables: [ - _ConnectionEvent, - _Channels, - _Users, - _Messages, - _Reads, - _Members, - _ChannelQueries, - _Reactions, -]) -class OfflineStorage extends _$OfflineStorage { - /// Creates a new database instance - OfflineStorage.connect( - DatabaseConnection connection, - this._userId, - this._isolate, - this._logger, - ) : super.connect(connection); - - /// Instantiate a new OfflineStorage - OfflineStorage( - this._userId, - this._logger, - ) : _isolate = null, - super(_openConnection(_userId)) { - _logger.info('Connecting on standard isolate'); - } - - final String _userId; - final MoorIsolate _isolate; - final Logger _logger; - - // you should bump this number whenever you change or add a table definition. Migrations - // are covered later in this readme. - @override - int get schemaVersion => 8; - - @override - MigrationStrategy get migration => MigrationStrategy( - onUpgrade: (openingDetails, before, after) async { - if (before != after) { - final m = createMigrator(); - for (final table in allTables) { - await m.deleteTable(table.actualTableName); - await m.createTable(table); - } - } - }, - ); - - /// Closes the database instance - /// If [flush] is true, the database data will be deleted - Future disconnect({bool flush = false}) async { - _logger.info('Disconnecting'); - if (flush) { - _logger.info('Flushing'); - await batch((batch) { - allTables.forEach((table) { - delete(table).go(); - }); - }); - } - - await _isolate?.shutdownAll(); - - await close(); - } - - /// Get stored replies by messageId - Future> getReplies( - String parentId, { - String lessThan, - }) async { - final offlineList = await Future.wait(await (select(messages).join([ - innerJoin(users, messages.userId.equalsExp(users.id)), - ]) - ..where(messages.parentId.equals(parentId)) - ..orderBy([ - OrderingTerm.asc(messages.createdAt), - ])) - .map(_messageFromJoinRow) - .get()); - if (lessThan != null) { - final lessThanIndex = offlineList.indexWhere((m) => m.id == lessThan); - offlineList.removeRange(lessThanIndex, offlineList.length); - } - - return offlineList; - } - - /// Get stored connection event - Future getConnectionInfo() async { - return select(connectionEvent).map((row) { - return Event( - me: row.ownUser != null ? OwnUser.fromJson(row.ownUser) : null, - totalUnreadCount: row.totalUnreadCount, - unreadChannels: row.unreadChannels, - ); - }).getSingle(); - } - - /// Get stored lastSyncAt - Future getLastSyncAt() async { - return select(connectionEvent).getSingle().then((r) => r?.lastSyncAt); - } - - /// Update stored connection event - Future updateConnectionInfo(Event event) async { - final connectionInfo = await select(connectionEvent).getSingle(); - - return into(connectionEvent).insert( - _ConnectionEventData( - id: 1, - lastSyncAt: connectionInfo?.lastSyncAt, - lastEventAt: event.createdAt ?? connectionInfo?.lastEventAt, - totalUnreadCount: - event.totalUnreadCount ?? connectionInfo?.totalUnreadCount, - ownUser: event.me?.toJson() ?? connectionInfo?.ownUser, - unreadChannels: event.unreadChannels ?? connectionInfo?.unreadChannels, - ), - mode: InsertMode.insertOrReplace, - ); - } - - /// Update stored lastSyncAt - Future updateLastSyncAt(DateTime lastSyncAt) async { - return await (update(connectionEvent)..where((r) => r.id.equals(1))).write( - _ConnectionEventCompanion( - id: Value(1), - lastSyncAt: Value(lastSyncAt), - ), - ); - } - - /// Get the channel cids saved in the offline storage - Future> getChannelCids() async { - return (select(channels) - ..orderBy([(c) => OrderingTerm.desc(c.lastMessageAt)]) - ..limit(250)) - .map((c) => c.cid) - .get(); - } - - /// Get channel data by cid - Future getChannel( - String cid, { - int limit, - String messageLessThan, - String messageGreaterThan, - }) async { - return await (select(channels)..where((c) => c.cid.equals(cid))).join([ - leftOuterJoin(users, channels.createdBy.equalsExp(users.id)), - ]).map((row) { - return _channelFromRow( - row.readTable(channels), - row.readTable(users), - limit: limit, - messageLessThan: messageLessThan, - messageGreaterThan: messageGreaterThan, - ); - }).getSingle(); - } - - /// Get list of channels by filter, sort and paginationParams - Future> getChannelStates({ - Map filter, - List sort = const [], - PaginationParams paginationParams, - }) async { - _logger.info('Get channel states'); - final hash = _computeHash(filter); - final cachedChannels = await Future.wait(await (select(channelQueries) - ..where((c) => c.queryHash.equals(hash))) - .get() - .then((channelQueries) { - final cids = channelQueries.map((c) => c.channelCid).toList(); - final query = select(channels)..where((c) => c.cid.isIn(cids)); - - sort = sort - ?.where((s) => ChannelModel.topLevelFields.contains(s.field)) - ?.toList(); - - if (sort != null && sort.isNotEmpty) { - query.orderBy(sort.map((s) { - final orderExpression = CustomExpression('channels.${s.field}'); - return (c) => OrderingTerm( - expression: orderExpression, - mode: s.direction == 1 ? OrderingMode.asc : OrderingMode.desc, - ); - }).toList()); - } - - if (paginationParams != null) { - query.limit( - paginationParams.limit ?? 10, - offset: paginationParams.offset, - ); - } - - return query.join([ - leftOuterJoin(users, channels.createdBy.equalsExp(users.id)), - ]).map((row) async { - final userRow = row.readTable(users); - final channelRow = row.readTable(channels); - - return _channelFromRow(channelRow, userRow); - }).get(); - })); - - _logger.info('Got ${cachedChannels.length} channels'); - - if (sort?.isEmpty != false && cachedChannels?.isNotEmpty == true) { - cachedChannels - .sort((a, b) => b.channel.updatedAt.compareTo(a.channel.updatedAt)); - cachedChannels.sort((a, b) { - final dateA = a.channel.lastMessageAt ?? a.channel.createdAt; - final dateB = b.channel.lastMessageAt ?? b.channel.createdAt; - return dateB.compareTo(dateA); - }); - } - - return cachedChannels; - } - - /// Update list of channel queries - /// If [clearQueryCache] is true before the insert - /// the list of matching rows will be deleted - Future updateChannelQueries( - Map filter, - List cids, - bool clearQueryCache, - ) async { - final hash = _computeHash(filter); - if (clearQueryCache) { - await (delete(channelQueries) - ..where( - (_ChannelQueries query) => query.queryHash.equals(hash), - )) - .go(); - } - - return batch((batch) { - batch.insertAll( - channelQueries, - cids.map((cid) { - return ChannelQuery( - queryHash: hash, - channelCid: cid, - ); - }).toList(), - mode: InsertMode.insertOrReplace, - ); - }); - } - - /// Remove a message by message id - Future deleteMessages(List messageIds) { - return batch((batch) { - batch.deleteWhere<_Reactions, _Reaction>( - reactions, - (r) => r.messageId.isIn(messageIds), - ); - batch.deleteWhere<_Messages, _Message>( - messages, - (m) => m.id.isIn(messageIds), - ); - }); - } - - /// Remove a message by message id - Future deleteChannelsMessages(List cids) async { - final messageIds = await (select(messages) - ..where((m) => m.channelCid.isIn(cids))) - .map((m) => m.id) - .get(); - return batch((batch) { - batch.deleteWhere<_Reactions, _Reaction>( - reactions, - (r) => r.messageId.isIn(messageIds), - ); - batch.deleteWhere<_Messages, _Message>( - messages, - (m) => m.id.isIn(messageIds), - ); - }); - } - - /// Remove a channel by cid - Future deleteChannels(List cids) async { - await deleteChannelsMessages(cids); - return batch((batch) { - batch.deleteWhere<_Members, _Member>( - members, - (m) => m.channelCid.isIn(cids), - ); - batch.deleteWhere<_Reads, _Read>( - reads, - (r) => r.channelCid.isIn(cids), - ); - batch.deleteWhere<_Channels, _Channel>( - channels, - (c) => c.cid.isIn(cids), - ); - }); - } - - /// Update messages data from a list - Future updateMessages( - List newMessages, - String cid, - ) { - return batch((batch) { - batch.insertAll( - messages, - newMessages.map( - (m) { - return _Message( - id: m.id, - attachmentJson: m.attachments != null - ? jsonEncode(m.attachments.map((a) => a.toJson()).toList()) - : null, - channelCid: cid, - type: m.type, - parentId: m.parentId, - quotedMessageId: m.quotedMessageId, - command: m.command, - createdAt: m.createdAt, - shadowed: m.shadowed, - showInChannel: m.showInChannel, - replyCount: m.replyCount, - reactionScores: m.reactionScores, - reactionCounts: m.reactionCounts, - status: m.status, - updatedAt: m.updatedAt, - extraData: m.extraData, - userId: m.user.id, - deletedAt: m.deletedAt, - messageText: m.text, - ); - }, - ).toList(), - mode: InsertMode.insertOrReplace, - ); - }); - } - - /// Update single channel state - Future updateChannelState(ChannelState channelState) async { - await updateChannelStates([channelState]); - } - - /// Update list of channel states - Future updateChannelStates(List channelStates) async { - channelStates.forEach((cs) { - updateMessages( - cs.messages, - cs.channel.cid, - ); - }); - - await batch((batch) { - _updateReactions(batch, channelStates); - - _updateUsers(batch, channelStates); - - _updateReads(channelStates, batch); - - _updateMembers(channelStates, batch); - - _updateChannels(batch, channelStates); - }); - } - - /// Get the info about channel threads - Future>> getChannelThreads(String cid) async { - final rowMessages = await Future.wait(await (select(messages).join([ - leftOuterJoin(users, messages.userId.equalsExp(users.id)), - ]) - ..where(messages.channelCid.equals(cid)) - ..where(isNotNull(messages.parentId)) - ..orderBy([ - OrderingTerm.asc(messages.createdAt), - ])) - .map(_messageFromJoinRow) - .get()); - - final threads = >{}; - rowMessages.forEach((message) { - if (threads.containsKey(message.parentId)) { - threads[message.parentId].add(message); - } else { - threads[message.parentId] = [message]; - } - }); - - return threads; - } - - Future _channelFromRow( - _Channel channelRow, - _User userRow, { - int limit, - String messageLessThan, - String messageGreaterThan, - }) async { - final rowMessages = await _getChannelMessages( - channelRow, - limit: limit, - lessThan: messageLessThan, - greaterThan: messageGreaterThan, - ); - final rowReads = await _getChannelReads(channelRow); - final rowMembers = await _getChannelMembers(channelRow); - - return ChannelState( - members: rowMembers, - read: rowReads, - messages: rowMessages, - channel: ChannelModel( - id: channelRow.id, - type: channelRow.type, - frozen: channelRow.frozen, - createdAt: channelRow.createdAt, - updatedAt: channelRow.updatedAt, - memberCount: channelRow.memberCount, - cid: channelRow.cid, - lastMessageAt: channelRow.lastMessageAt, - deletedAt: channelRow.deletedAt, - extraData: channelRow.extraData, - config: ChannelConfig.fromJson(jsonDecode(channelRow.config)), - createdBy: userRow != null ? _userFromUserRow(userRow) : null, - ), - ); - } - - String _computeHash(Map filter) { - if (filter == null) { - return 'allchannels'; - } - final hash = base64Encode(utf8.encode('filter: ${jsonEncode(filter)}')); - return hash; - } - - Future _getMessageById(String id) async { - if (id == null || id.isEmpty) return null; - final message = await Future.wait(await (select(messages).join([ - leftOuterJoin(users, messages.userId.equalsExp(users.id)), - ]) - ..where(messages.id.equals(id))) - .map(_messageFromJoinRow) - .get()); - return message.first; - } - - Future> _getChannelMessages( - _Channel channelRow, { - int limit, - String lessThan, - String greaterThan, - }) async { - final rowMessages = await Future.wait(await (select(messages).join([ - leftOuterJoin(users, messages.userId.equalsExp(users.id)), - ]) - ..where(messages.channelCid.equals(channelRow.cid)) - ..where( - isNull(messages.parentId) | messages.showInChannel.equals(true)) - ..orderBy([ - OrderingTerm.asc(messages.createdAt), - ])) - .map(_messageFromJoinRow) - .get()); - - if (lessThan != null) { - final lessThanIndex = rowMessages.indexWhere((m) => m.id == lessThan); - if (lessThanIndex != -1) { - rowMessages.removeRange(lessThanIndex, rowMessages.length); - } - } - if (greaterThan != null) { - final greaterThanIndex = - rowMessages.indexWhere((m) => m.id == greaterThan); - if (greaterThanIndex != -1) { - rowMessages.removeRange(0, greaterThanIndex); - } - } - if (limit != null) { - return rowMessages.take(limit).toList(); - } - return rowMessages; - } - - Future _messageFromJoinRow(row) async { - final messageRow = row.readTable(messages); - final userRow = row.readTable(users); - - final latestReactions = await _getLatestReactions(messageRow); - final ownReactions = await _getOwnReactions(messageRow); - final quotedMessage = await _getMessageById(messageRow.quotedMessageId); - - return Message( - shadowed: messageRow.shadowed, - latestReactions: latestReactions, - ownReactions: ownReactions, - attachments: messageRow.attachmentJson != null - ? List>.from( - jsonDecode(messageRow.attachmentJson)) - .map((j) => Attachment.fromJson(j)) - .toList() - : null, - createdAt: messageRow.createdAt, - extraData: messageRow.extraData, - updatedAt: messageRow.updatedAt, - id: messageRow.id, - type: messageRow.type, - status: messageRow.status, - command: messageRow.command, - parentId: messageRow.parentId, - quotedMessageId: messageRow.quotedMessageId, - quotedMessage: quotedMessage, - reactionCounts: messageRow.reactionCounts, - reactionScores: messageRow.reactionScores, - replyCount: messageRow.replyCount, - showInChannel: messageRow.showInChannel, - text: messageRow.messageText, - user: _userFromUserRow(userRow), - deletedAt: messageRow.deletedAt, - ); - } - - Future> _getLatestReactions(_Message messageRow) async { - return await (select(reactions).join([ - leftOuterJoin(users, reactions.userId.equalsExp(users.id)), - ]) - ..where(reactions.messageId.equals(messageRow.id)) - ..orderBy([OrderingTerm.asc(reactions.createdAt)])) - .map((row) { - final r = row.readTable(reactions); - final u = row.readTable(users); - return _reactionFromRow(r, u); - }).get(); - } - - Reaction _reactionFromRow(_Reaction r, _User u) { - return Reaction( - extraData: r.extraData, - type: r.type, - createdAt: r.createdAt, - userId: r.userId, - user: _userFromUserRow(u), - messageId: r.messageId, - score: r.score, - ); - } - - Future> _getOwnReactions(_Message messageRow) async { - return await (select(reactions).join([ - leftOuterJoin(users, reactions.userId.equalsExp(users.id)), - ]) - ..where(reactions.userId.equals(_userId)) - ..where(reactions.messageId.equals(messageRow.id)) - ..orderBy([OrderingTerm.asc(reactions.createdAt)])) - .map((row) { - final r = row.readTable(reactions); - final u = row.readTable(users); - return _reactionFromRow(r, u); - }).get(); - } - - Future> _getChannelReads(_Channel channelRow) async { - final rowReads = await (select(reads).join([ - leftOuterJoin(users, reads.userId.equalsExp(users.id)), - ]) - ..where(reads.channelCid.equals(channelRow.cid)) - ..orderBy([ - OrderingTerm.asc(reads.lastRead), - ])) - .map((row) { - final userRow = row.readTable(users); - final readRow = row.readTable(reads); - return Read( - user: _userFromUserRow(userRow), - lastRead: readRow.lastRead, - unreadMessages: readRow.unreadMessages, - ); - }).get(); - return rowReads; - } - - Future> _getChannelMembers(_Channel channelRow) async { - final rowMembers = await (select(members).join([ - leftOuterJoin(users, members.userId.equalsExp(users.id)), - ]) - ..where(members.channelCid.equals(channelRow.cid)) - ..orderBy([ - OrderingTerm.asc(members.createdAt), - ])) - .map((row) { - final userRow = row.readTable(users); - final memberRow = row.readTable(members); - return Member( - user: _userFromUserRow(userRow), - userId: userRow.id, - banned: memberRow.banned, - shadowBanned: memberRow.shadowBanned, - updatedAt: memberRow.updatedAt, - createdAt: memberRow.createdAt, - role: memberRow.role, - inviteAcceptedAt: memberRow.inviteAcceptedAt, - invited: memberRow.invited, - inviteRejectedAt: memberRow.inviteRejectedAt, - isModerator: memberRow.isModerator, - ); - }).get(); - return rowMembers; - } - - User _userFromUserRow(_User userRow) { - return User( - updatedAt: userRow.updatedAt, - role: userRow.role, - online: userRow.online, - lastActive: userRow.lastActive, - extraData: userRow.extraData, - banned: userRow.banned, - createdAt: userRow.createdAt, - id: userRow.id, - ); - } - - void _updateChannels(Batch batch, List channelStates) { - batch.insertAll( - channels, - channelStates.map((cs) { - final channel = cs.channel; - return _channelDataFromChannelModel(channel); - }).toList(), - mode: InsertMode.insertOrReplace, - ); - } - - void _updateMembers(List channelStates, Batch batch) async { - await (delete(members) - ..where((tbl) => - tbl.channelCid.isIn(channelStates.map((e) => e.channel.cid)))) - .go(); - final newMembers = channelStates - .map((cs) => cs.members.map((m) => _Member( - userId: m.user.id, - banned: m.banned, - shadowBanned: m.shadowBanned, - channelCid: cs.channel.cid, - createdAt: m.createdAt, - isModerator: m.isModerator, - inviteRejectedAt: m.inviteRejectedAt, - invited: m.invited, - inviteAcceptedAt: m.inviteAcceptedAt, - role: m.role, - updatedAt: m.updatedAt, - ))) - .where((v) => v != null) - .expand((v) => v); - if (newMembers != null && newMembers.isNotEmpty) { - batch.insertAll( - members, - newMembers.toList(), - mode: InsertMode.insertOrReplace, - ); - } - } - - void _updateReads(List channelStates, Batch batch) { - final newReads = channelStates - .map((cs) => cs.read?.map((r) => _Read( - lastRead: r.lastRead, - userId: r.user.id, - channelCid: cs.channel.cid, - unreadMessages: r.unreadMessages, - ))) - .where((v) => v != null) - .expand((v) => v); - - if (newReads != null && newReads.isNotEmpty) { - batch.insertAll( - reads, - newReads.toList(), - mode: InsertMode.insertOrReplace, - ); - } - } - - void _updateUsers(Batch batch, List channelStates) { - batch.insertAll( - users, - channelStates - .map((cs) => [ - if (cs.channel.createdBy != null) - _userDataFromUser(cs.channel.createdBy), - if (cs.messages != null) - ...cs.messages - .map((m) => [ - _userDataFromUser(m.user), - if (m.latestReactions != null) - ...m.latestReactions - .where((r) => r.user != null) - .map((r) => _userDataFromUser(r.user)), - if (m.ownReactions != null) - ...m.ownReactions - .where((r) => r.user != null) - .map((r) => _userDataFromUser(r.user)), - ]) - .expand((v) => v), - if (cs.read != null) - ...cs.read.map((r) => _userDataFromUser(r.user)), - if (cs.members != null) - ...cs.members.map((m) => _userDataFromUser(m.user)), - ]) - .expand((v) => v) - .toList(), - mode: InsertMode.insertOrReplace, - ); - } - - void _updateReactions(Batch batch, List channelStates) { - batch.deleteWhere<_Reactions, _Reaction>( - reactions, - (r) => r.messageId.isIn(channelStates - .map((cs) => cs.messages.map((m) => m.id)) - .expand((v) => v)), - ); - final newReactions = channelStates - .map((cs) => cs.messages.map((m) { - final ownReactions = - m.ownReactions?.where((e) => e.userId != null)?.map( - (r) => _reactionDataFromReaction(m, r), - ) ?? - []; - final latestReactions = - m.latestReactions?.where((e) => e.userId != null)?.map( - (r) => _reactionDataFromReaction(m, r), - ) ?? - []; - return [ - ...ownReactions, - ...latestReactions, - ]; - }).expand((v) => v)) - .expand((v) => v); - - if (newReactions.isNotEmpty) { - batch.insertAll( - reactions, - newReactions.toList(), - mode: InsertMode.insertOrReplace, - ); - } - } - - _Reaction _reactionDataFromReaction(Message m, Reaction r) { - return _Reaction( - messageId: m.id, - type: r.type, - extraData: r.extraData, - score: r.score, - createdAt: r.createdAt, - userId: r.userId, - ); - } - - _User _userDataFromUser(User user) { - return _User( - id: user.id, - createdAt: user.createdAt, - banned: user.banned, - extraData: user.extraData, - lastActive: user.lastActive, - online: user.online, - role: user.role, - updatedAt: user.updatedAt, - ); - } - - _Channel _channelDataFromChannelModel(ChannelModel channel) { - return _Channel( - id: channel.id, - config: jsonEncode(channel.config?.toJson() ?? {}), - type: channel.type, - frozen: channel.frozen, - createdAt: channel.createdAt, - updatedAt: channel.updatedAt, - memberCount: channel.memberCount, - cid: channel.cid, - lastMessageAt: channel.lastMessageAt, - deletedAt: channel.deletedAt, - extraData: channel.extraData, - createdBy: channel.createdBy?.id, - ); - } -} diff --git a/packages/dart_client/lib/src/db/offline_storage.g.dart b/packages/dart_client/lib/src/db/offline_storage.g.dart deleted file mode 100644 index a87ecb92..00000000 --- a/packages/dart_client/lib/src/db/offline_storage.g.dart +++ /dev/null @@ -1,4160 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'offline_storage.dart'; - -// ************************************************************************** -// MoorGenerator -// ************************************************************************** - -// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this -class _ConnectionEventData extends DataClass - implements Insertable<_ConnectionEventData> { - final int id; - final Map ownUser; - final int totalUnreadCount; - final int unreadChannels; - final DateTime lastEventAt; - final DateTime lastSyncAt; - _ConnectionEventData( - {@required this.id, - this.ownUser, - this.totalUnreadCount, - this.unreadChannels, - this.lastEventAt, - this.lastSyncAt}); - factory _ConnectionEventData.fromData( - Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final intType = db.typeSystem.forDartType(); - final stringType = db.typeSystem.forDartType(); - final dateTimeType = db.typeSystem.forDartType(); - return _ConnectionEventData( - id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']), - ownUser: $_ConnectionEventTable.$converter0.mapToDart(stringType - .mapFromDatabaseResponse(data['${effectivePrefix}own_user'])), - totalUnreadCount: intType.mapFromDatabaseResponse( - data['${effectivePrefix}total_unread_count']), - unreadChannels: intType - .mapFromDatabaseResponse(data['${effectivePrefix}unread_channels']), - lastEventAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}last_event_at']), - lastSyncAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}last_sync_at']), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || id != null) { - map['id'] = Variable(id); - } - if (!nullToAbsent || ownUser != null) { - final converter = $_ConnectionEventTable.$converter0; - map['own_user'] = Variable(converter.mapToSql(ownUser)); - } - if (!nullToAbsent || totalUnreadCount != null) { - map['total_unread_count'] = Variable(totalUnreadCount); - } - if (!nullToAbsent || unreadChannels != null) { - map['unread_channels'] = Variable(unreadChannels); - } - if (!nullToAbsent || lastEventAt != null) { - map['last_event_at'] = Variable(lastEventAt); - } - if (!nullToAbsent || lastSyncAt != null) { - map['last_sync_at'] = Variable(lastSyncAt); - } - return map; - } - - _ConnectionEventCompanion toCompanion(bool nullToAbsent) { - return _ConnectionEventCompanion( - id: id == null && nullToAbsent ? const Value.absent() : Value(id), - ownUser: ownUser == null && nullToAbsent - ? const Value.absent() - : Value(ownUser), - totalUnreadCount: totalUnreadCount == null && nullToAbsent - ? const Value.absent() - : Value(totalUnreadCount), - unreadChannels: unreadChannels == null && nullToAbsent - ? const Value.absent() - : Value(unreadChannels), - lastEventAt: lastEventAt == null && nullToAbsent - ? const Value.absent() - : Value(lastEventAt), - lastSyncAt: lastSyncAt == null && nullToAbsent - ? const Value.absent() - : Value(lastSyncAt), - ); - } - - factory _ConnectionEventData.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return _ConnectionEventData( - id: serializer.fromJson(json['id']), - ownUser: serializer.fromJson>(json['ownUser']), - totalUnreadCount: serializer.fromJson(json['totalUnreadCount']), - unreadChannels: serializer.fromJson(json['unreadChannels']), - lastEventAt: serializer.fromJson(json['lastEventAt']), - lastSyncAt: serializer.fromJson(json['lastSyncAt']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'id': serializer.toJson(id), - 'ownUser': serializer.toJson>(ownUser), - 'totalUnreadCount': serializer.toJson(totalUnreadCount), - 'unreadChannels': serializer.toJson(unreadChannels), - 'lastEventAt': serializer.toJson(lastEventAt), - 'lastSyncAt': serializer.toJson(lastSyncAt), - }; - } - - _ConnectionEventData copyWith( - {int id, - Map ownUser, - int totalUnreadCount, - int unreadChannels, - DateTime lastEventAt, - DateTime lastSyncAt}) => - _ConnectionEventData( - id: id ?? this.id, - ownUser: ownUser ?? this.ownUser, - totalUnreadCount: totalUnreadCount ?? this.totalUnreadCount, - unreadChannels: unreadChannels ?? this.unreadChannels, - lastEventAt: lastEventAt ?? this.lastEventAt, - lastSyncAt: lastSyncAt ?? this.lastSyncAt, - ); - @override - String toString() { - return (StringBuffer('_ConnectionEventData(') - ..write('id: $id, ') - ..write('ownUser: $ownUser, ') - ..write('totalUnreadCount: $totalUnreadCount, ') - ..write('unreadChannels: $unreadChannels, ') - ..write('lastEventAt: $lastEventAt, ') - ..write('lastSyncAt: $lastSyncAt') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc( - id.hashCode, - $mrjc( - ownUser.hashCode, - $mrjc( - totalUnreadCount.hashCode, - $mrjc(unreadChannels.hashCode, - $mrjc(lastEventAt.hashCode, lastSyncAt.hashCode)))))); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is _ConnectionEventData && - other.id == this.id && - other.ownUser == this.ownUser && - other.totalUnreadCount == this.totalUnreadCount && - other.unreadChannels == this.unreadChannels && - other.lastEventAt == this.lastEventAt && - other.lastSyncAt == this.lastSyncAt); -} - -class _ConnectionEventCompanion extends UpdateCompanion<_ConnectionEventData> { - final Value id; - final Value> ownUser; - final Value totalUnreadCount; - final Value unreadChannels; - final Value lastEventAt; - final Value lastSyncAt; - const _ConnectionEventCompanion({ - this.id = const Value.absent(), - this.ownUser = const Value.absent(), - this.totalUnreadCount = const Value.absent(), - this.unreadChannels = const Value.absent(), - this.lastEventAt = const Value.absent(), - this.lastSyncAt = const Value.absent(), - }); - _ConnectionEventCompanion.insert({ - this.id = const Value.absent(), - this.ownUser = const Value.absent(), - this.totalUnreadCount = const Value.absent(), - this.unreadChannels = const Value.absent(), - this.lastEventAt = const Value.absent(), - this.lastSyncAt = const Value.absent(), - }); - static Insertable<_ConnectionEventData> custom({ - Expression id, - Expression ownUser, - Expression totalUnreadCount, - Expression unreadChannels, - Expression lastEventAt, - Expression lastSyncAt, - }) { - return RawValuesInsertable({ - if (id != null) 'id': id, - if (ownUser != null) 'own_user': ownUser, - if (totalUnreadCount != null) 'total_unread_count': totalUnreadCount, - if (unreadChannels != null) 'unread_channels': unreadChannels, - if (lastEventAt != null) 'last_event_at': lastEventAt, - if (lastSyncAt != null) 'last_sync_at': lastSyncAt, - }); - } - - _ConnectionEventCompanion copyWith( - {Value id, - Value> ownUser, - Value totalUnreadCount, - Value unreadChannels, - Value lastEventAt, - Value lastSyncAt}) { - return _ConnectionEventCompanion( - id: id ?? this.id, - ownUser: ownUser ?? this.ownUser, - totalUnreadCount: totalUnreadCount ?? this.totalUnreadCount, - unreadChannels: unreadChannels ?? this.unreadChannels, - lastEventAt: lastEventAt ?? this.lastEventAt, - lastSyncAt: lastSyncAt ?? this.lastSyncAt, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (id.present) { - map['id'] = Variable(id.value); - } - if (ownUser.present) { - final converter = $_ConnectionEventTable.$converter0; - map['own_user'] = Variable(converter.mapToSql(ownUser.value)); - } - if (totalUnreadCount.present) { - map['total_unread_count'] = Variable(totalUnreadCount.value); - } - if (unreadChannels.present) { - map['unread_channels'] = Variable(unreadChannels.value); - } - if (lastEventAt.present) { - map['last_event_at'] = Variable(lastEventAt.value); - } - if (lastSyncAt.present) { - map['last_sync_at'] = Variable(lastSyncAt.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_ConnectionEventCompanion(') - ..write('id: $id, ') - ..write('ownUser: $ownUser, ') - ..write('totalUnreadCount: $totalUnreadCount, ') - ..write('unreadChannels: $unreadChannels, ') - ..write('lastEventAt: $lastEventAt, ') - ..write('lastSyncAt: $lastSyncAt') - ..write(')')) - .toString(); - } -} - -class $_ConnectionEventTable extends _ConnectionEvent - with TableInfo<$_ConnectionEventTable, _ConnectionEventData> { - final GeneratedDatabase _db; - final String _alias; - $_ConnectionEventTable(this._db, [this._alias]); - final VerificationMeta _idMeta = const VerificationMeta('id'); - GeneratedIntColumn _id; - @override - GeneratedIntColumn get id => _id ??= _constructId(); - GeneratedIntColumn _constructId() { - return GeneratedIntColumn( - 'id', - $tableName, - false, - ); - } - - final VerificationMeta _ownUserMeta = const VerificationMeta('ownUser'); - GeneratedTextColumn _ownUser; - @override - GeneratedTextColumn get ownUser => _ownUser ??= _constructOwnUser(); - GeneratedTextColumn _constructOwnUser() { - return GeneratedTextColumn( - 'own_user', - $tableName, - true, - ); - } - - final VerificationMeta _totalUnreadCountMeta = - const VerificationMeta('totalUnreadCount'); - GeneratedIntColumn _totalUnreadCount; - @override - GeneratedIntColumn get totalUnreadCount => - _totalUnreadCount ??= _constructTotalUnreadCount(); - GeneratedIntColumn _constructTotalUnreadCount() { - return GeneratedIntColumn( - 'total_unread_count', - $tableName, - true, - ); - } - - final VerificationMeta _unreadChannelsMeta = - const VerificationMeta('unreadChannels'); - GeneratedIntColumn _unreadChannels; - @override - GeneratedIntColumn get unreadChannels => - _unreadChannels ??= _constructUnreadChannels(); - GeneratedIntColumn _constructUnreadChannels() { - return GeneratedIntColumn( - 'unread_channels', - $tableName, - true, - ); - } - - final VerificationMeta _lastEventAtMeta = - const VerificationMeta('lastEventAt'); - GeneratedDateTimeColumn _lastEventAt; - @override - GeneratedDateTimeColumn get lastEventAt => - _lastEventAt ??= _constructLastEventAt(); - GeneratedDateTimeColumn _constructLastEventAt() { - return GeneratedDateTimeColumn( - 'last_event_at', - $tableName, - true, - ); - } - - final VerificationMeta _lastSyncAtMeta = const VerificationMeta('lastSyncAt'); - GeneratedDateTimeColumn _lastSyncAt; - @override - GeneratedDateTimeColumn get lastSyncAt => - _lastSyncAt ??= _constructLastSyncAt(); - GeneratedDateTimeColumn _constructLastSyncAt() { - return GeneratedDateTimeColumn( - 'last_sync_at', - $tableName, - true, - ); - } - - @override - List get $columns => - [id, ownUser, totalUnreadCount, unreadChannels, lastEventAt, lastSyncAt]; - @override - $_ConnectionEventTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'connection_event'; - @override - final String actualTableName = 'connection_event'; - @override - VerificationContext validateIntegrity( - Insertable<_ConnectionEventData> instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('id')) { - context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); - } - context.handle(_ownUserMeta, const VerificationResult.success()); - if (data.containsKey('total_unread_count')) { - context.handle( - _totalUnreadCountMeta, - totalUnreadCount.isAcceptableOrUnknown( - data['total_unread_count'], _totalUnreadCountMeta)); - } - if (data.containsKey('unread_channels')) { - context.handle( - _unreadChannelsMeta, - unreadChannels.isAcceptableOrUnknown( - data['unread_channels'], _unreadChannelsMeta)); - } - if (data.containsKey('last_event_at')) { - context.handle( - _lastEventAtMeta, - lastEventAt.isAcceptableOrUnknown( - data['last_event_at'], _lastEventAtMeta)); - } - if (data.containsKey('last_sync_at')) { - context.handle( - _lastSyncAtMeta, - lastSyncAt.isAcceptableOrUnknown( - data['last_sync_at'], _lastSyncAtMeta)); - } - return context; - } - - @override - Set get $primaryKey => {id}; - @override - _ConnectionEventData map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return _ConnectionEventData.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_ConnectionEventTable createAlias(String alias) { - return $_ConnectionEventTable(_db, alias); - } - - static TypeConverter, String> $converter0 = - _ExtraDataConverter(); -} - -class _Channel extends DataClass implements Insertable<_Channel> { - final String id; - final String type; - final String cid; - final String config; - final bool frozen; - final DateTime lastMessageAt; - final DateTime createdAt; - final DateTime updatedAt; - final DateTime deletedAt; - final int memberCount; - final Map extraData; - final String createdBy; - _Channel( - {@required this.id, - @required this.type, - @required this.cid, - @required this.config, - @required this.frozen, - this.lastMessageAt, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.memberCount, - this.extraData, - this.createdBy}); - factory _Channel.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final stringType = db.typeSystem.forDartType(); - final boolType = db.typeSystem.forDartType(); - final dateTimeType = db.typeSystem.forDartType(); - final intType = db.typeSystem.forDartType(); - return _Channel( - id: stringType.mapFromDatabaseResponse(data['${effectivePrefix}id']), - type: stringType.mapFromDatabaseResponse(data['${effectivePrefix}type']), - cid: stringType.mapFromDatabaseResponse(data['${effectivePrefix}cid']), - config: - stringType.mapFromDatabaseResponse(data['${effectivePrefix}config']), - frozen: - boolType.mapFromDatabaseResponse(data['${effectivePrefix}frozen']), - lastMessageAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}last_message_at']), - createdAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), - updatedAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), - deletedAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}deleted_at']), - memberCount: intType - .mapFromDatabaseResponse(data['${effectivePrefix}member_count']), - extraData: $_ChannelsTable.$converter0.mapToDart(stringType - .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), - createdBy: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}created_by']), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || id != null) { - map['id'] = Variable(id); - } - if (!nullToAbsent || type != null) { - map['type'] = Variable(type); - } - if (!nullToAbsent || cid != null) { - map['cid'] = Variable(cid); - } - if (!nullToAbsent || config != null) { - map['config'] = Variable(config); - } - if (!nullToAbsent || frozen != null) { - map['frozen'] = Variable(frozen); - } - if (!nullToAbsent || lastMessageAt != null) { - map['last_message_at'] = Variable(lastMessageAt); - } - if (!nullToAbsent || createdAt != null) { - map['created_at'] = Variable(createdAt); - } - if (!nullToAbsent || updatedAt != null) { - map['updated_at'] = Variable(updatedAt); - } - if (!nullToAbsent || deletedAt != null) { - map['deleted_at'] = Variable(deletedAt); - } - if (!nullToAbsent || memberCount != null) { - map['member_count'] = Variable(memberCount); - } - if (!nullToAbsent || extraData != null) { - final converter = $_ChannelsTable.$converter0; - map['extra_data'] = Variable(converter.mapToSql(extraData)); - } - if (!nullToAbsent || createdBy != null) { - map['created_by'] = Variable(createdBy); - } - return map; - } - - _ChannelsCompanion toCompanion(bool nullToAbsent) { - return _ChannelsCompanion( - id: id == null && nullToAbsent ? const Value.absent() : Value(id), - type: type == null && nullToAbsent ? const Value.absent() : Value(type), - cid: cid == null && nullToAbsent ? const Value.absent() : Value(cid), - config: - config == null && nullToAbsent ? const Value.absent() : Value(config), - frozen: - frozen == null && nullToAbsent ? const Value.absent() : Value(frozen), - lastMessageAt: lastMessageAt == null && nullToAbsent - ? const Value.absent() - : Value(lastMessageAt), - createdAt: createdAt == null && nullToAbsent - ? const Value.absent() - : Value(createdAt), - updatedAt: updatedAt == null && nullToAbsent - ? const Value.absent() - : Value(updatedAt), - deletedAt: deletedAt == null && nullToAbsent - ? const Value.absent() - : Value(deletedAt), - memberCount: memberCount == null && nullToAbsent - ? const Value.absent() - : Value(memberCount), - extraData: extraData == null && nullToAbsent - ? const Value.absent() - : Value(extraData), - createdBy: createdBy == null && nullToAbsent - ? const Value.absent() - : Value(createdBy), - ); - } - - factory _Channel.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return _Channel( - id: serializer.fromJson(json['id']), - type: serializer.fromJson(json['type']), - cid: serializer.fromJson(json['cid']), - config: serializer.fromJson(json['config']), - frozen: serializer.fromJson(json['frozen']), - lastMessageAt: serializer.fromJson(json['lastMessageAt']), - createdAt: serializer.fromJson(json['createdAt']), - updatedAt: serializer.fromJson(json['updatedAt']), - deletedAt: serializer.fromJson(json['deletedAt']), - memberCount: serializer.fromJson(json['memberCount']), - extraData: serializer.fromJson>(json['extraData']), - createdBy: serializer.fromJson(json['createdBy']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'id': serializer.toJson(id), - 'type': serializer.toJson(type), - 'cid': serializer.toJson(cid), - 'config': serializer.toJson(config), - 'frozen': serializer.toJson(frozen), - 'lastMessageAt': serializer.toJson(lastMessageAt), - 'createdAt': serializer.toJson(createdAt), - 'updatedAt': serializer.toJson(updatedAt), - 'deletedAt': serializer.toJson(deletedAt), - 'memberCount': serializer.toJson(memberCount), - 'extraData': serializer.toJson>(extraData), - 'createdBy': serializer.toJson(createdBy), - }; - } - - _Channel copyWith( - {String id, - String type, - String cid, - String config, - bool frozen, - DateTime lastMessageAt, - DateTime createdAt, - DateTime updatedAt, - DateTime deletedAt, - int memberCount, - Map extraData, - String createdBy}) => - _Channel( - id: id ?? this.id, - type: type ?? this.type, - cid: cid ?? this.cid, - config: config ?? this.config, - frozen: frozen ?? this.frozen, - lastMessageAt: lastMessageAt ?? this.lastMessageAt, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - memberCount: memberCount ?? this.memberCount, - extraData: extraData ?? this.extraData, - createdBy: createdBy ?? this.createdBy, - ); - @override - String toString() { - return (StringBuffer('_Channel(') - ..write('id: $id, ') - ..write('type: $type, ') - ..write('cid: $cid, ') - ..write('config: $config, ') - ..write('frozen: $frozen, ') - ..write('lastMessageAt: $lastMessageAt, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('deletedAt: $deletedAt, ') - ..write('memberCount: $memberCount, ') - ..write('extraData: $extraData, ') - ..write('createdBy: $createdBy') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc( - id.hashCode, - $mrjc( - type.hashCode, - $mrjc( - cid.hashCode, - $mrjc( - config.hashCode, - $mrjc( - frozen.hashCode, - $mrjc( - lastMessageAt.hashCode, - $mrjc( - createdAt.hashCode, - $mrjc( - updatedAt.hashCode, - $mrjc( - deletedAt.hashCode, - $mrjc( - memberCount.hashCode, - $mrjc(extraData.hashCode, - createdBy.hashCode)))))))))))); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is _Channel && - other.id == this.id && - other.type == this.type && - other.cid == this.cid && - other.config == this.config && - other.frozen == this.frozen && - other.lastMessageAt == this.lastMessageAt && - other.createdAt == this.createdAt && - other.updatedAt == this.updatedAt && - other.deletedAt == this.deletedAt && - other.memberCount == this.memberCount && - other.extraData == this.extraData && - other.createdBy == this.createdBy); -} - -class _ChannelsCompanion extends UpdateCompanion<_Channel> { - final Value id; - final Value type; - final Value cid; - final Value config; - final Value frozen; - final Value lastMessageAt; - final Value createdAt; - final Value updatedAt; - final Value deletedAt; - final Value memberCount; - final Value> extraData; - final Value createdBy; - const _ChannelsCompanion({ - this.id = const Value.absent(), - this.type = const Value.absent(), - this.cid = const Value.absent(), - this.config = const Value.absent(), - this.frozen = const Value.absent(), - this.lastMessageAt = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), - this.deletedAt = const Value.absent(), - this.memberCount = const Value.absent(), - this.extraData = const Value.absent(), - this.createdBy = const Value.absent(), - }); - _ChannelsCompanion.insert({ - @required String id, - @required String type, - @required String cid, - @required String config, - this.frozen = const Value.absent(), - this.lastMessageAt = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), - this.deletedAt = const Value.absent(), - this.memberCount = const Value.absent(), - this.extraData = const Value.absent(), - this.createdBy = const Value.absent(), - }) : id = Value(id), - type = Value(type), - cid = Value(cid), - config = Value(config); - static Insertable<_Channel> custom({ - Expression id, - Expression type, - Expression cid, - Expression config, - Expression frozen, - Expression lastMessageAt, - Expression createdAt, - Expression updatedAt, - Expression deletedAt, - Expression memberCount, - Expression extraData, - Expression createdBy, - }) { - return RawValuesInsertable({ - if (id != null) 'id': id, - if (type != null) 'type': type, - if (cid != null) 'cid': cid, - if (config != null) 'config': config, - if (frozen != null) 'frozen': frozen, - if (lastMessageAt != null) 'last_message_at': lastMessageAt, - if (createdAt != null) 'created_at': createdAt, - if (updatedAt != null) 'updated_at': updatedAt, - if (deletedAt != null) 'deleted_at': deletedAt, - if (memberCount != null) 'member_count': memberCount, - if (extraData != null) 'extra_data': extraData, - if (createdBy != null) 'created_by': createdBy, - }); - } - - _ChannelsCompanion copyWith( - {Value id, - Value type, - Value cid, - Value config, - Value frozen, - Value lastMessageAt, - Value createdAt, - Value updatedAt, - Value deletedAt, - Value memberCount, - Value> extraData, - Value createdBy}) { - return _ChannelsCompanion( - id: id ?? this.id, - type: type ?? this.type, - cid: cid ?? this.cid, - config: config ?? this.config, - frozen: frozen ?? this.frozen, - lastMessageAt: lastMessageAt ?? this.lastMessageAt, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - memberCount: memberCount ?? this.memberCount, - extraData: extraData ?? this.extraData, - createdBy: createdBy ?? this.createdBy, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (id.present) { - map['id'] = Variable(id.value); - } - if (type.present) { - map['type'] = Variable(type.value); - } - if (cid.present) { - map['cid'] = Variable(cid.value); - } - if (config.present) { - map['config'] = Variable(config.value); - } - if (frozen.present) { - map['frozen'] = Variable(frozen.value); - } - if (lastMessageAt.present) { - map['last_message_at'] = Variable(lastMessageAt.value); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (updatedAt.present) { - map['updated_at'] = Variable(updatedAt.value); - } - if (deletedAt.present) { - map['deleted_at'] = Variable(deletedAt.value); - } - if (memberCount.present) { - map['member_count'] = Variable(memberCount.value); - } - if (extraData.present) { - final converter = $_ChannelsTable.$converter0; - map['extra_data'] = Variable(converter.mapToSql(extraData.value)); - } - if (createdBy.present) { - map['created_by'] = Variable(createdBy.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_ChannelsCompanion(') - ..write('id: $id, ') - ..write('type: $type, ') - ..write('cid: $cid, ') - ..write('config: $config, ') - ..write('frozen: $frozen, ') - ..write('lastMessageAt: $lastMessageAt, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('deletedAt: $deletedAt, ') - ..write('memberCount: $memberCount, ') - ..write('extraData: $extraData, ') - ..write('createdBy: $createdBy') - ..write(')')) - .toString(); - } -} - -class $_ChannelsTable extends _Channels - with TableInfo<$_ChannelsTable, _Channel> { - final GeneratedDatabase _db; - final String _alias; - $_ChannelsTable(this._db, [this._alias]); - final VerificationMeta _idMeta = const VerificationMeta('id'); - GeneratedTextColumn _id; - @override - GeneratedTextColumn get id => _id ??= _constructId(); - GeneratedTextColumn _constructId() { - return GeneratedTextColumn( - 'id', - $tableName, - false, - ); - } - - final VerificationMeta _typeMeta = const VerificationMeta('type'); - GeneratedTextColumn _type; - @override - GeneratedTextColumn get type => _type ??= _constructType(); - GeneratedTextColumn _constructType() { - return GeneratedTextColumn( - 'type', - $tableName, - false, - ); - } - - final VerificationMeta _cidMeta = const VerificationMeta('cid'); - GeneratedTextColumn _cid; - @override - GeneratedTextColumn get cid => _cid ??= _constructCid(); - GeneratedTextColumn _constructCid() { - return GeneratedTextColumn( - 'cid', - $tableName, - false, - ); - } - - final VerificationMeta _configMeta = const VerificationMeta('config'); - GeneratedTextColumn _config; - @override - GeneratedTextColumn get config => _config ??= _constructConfig(); - GeneratedTextColumn _constructConfig() { - return GeneratedTextColumn( - 'config', - $tableName, - false, - ); - } - - final VerificationMeta _frozenMeta = const VerificationMeta('frozen'); - GeneratedBoolColumn _frozen; - @override - GeneratedBoolColumn get frozen => _frozen ??= _constructFrozen(); - GeneratedBoolColumn _constructFrozen() { - return GeneratedBoolColumn('frozen', $tableName, false, - defaultValue: Constant(false)); - } - - final VerificationMeta _lastMessageAtMeta = - const VerificationMeta('lastMessageAt'); - GeneratedDateTimeColumn _lastMessageAt; - @override - GeneratedDateTimeColumn get lastMessageAt => - _lastMessageAt ??= _constructLastMessageAt(); - GeneratedDateTimeColumn _constructLastMessageAt() { - return GeneratedDateTimeColumn( - 'last_message_at', - $tableName, - true, - ); - } - - final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); - GeneratedDateTimeColumn _createdAt; - @override - GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); - GeneratedDateTimeColumn _constructCreatedAt() { - return GeneratedDateTimeColumn( - 'created_at', - $tableName, - true, - ); - } - - final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); - GeneratedDateTimeColumn _updatedAt; - @override - GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); - GeneratedDateTimeColumn _constructUpdatedAt() { - return GeneratedDateTimeColumn( - 'updated_at', - $tableName, - true, - ); - } - - final VerificationMeta _deletedAtMeta = const VerificationMeta('deletedAt'); - GeneratedDateTimeColumn _deletedAt; - @override - GeneratedDateTimeColumn get deletedAt => _deletedAt ??= _constructDeletedAt(); - GeneratedDateTimeColumn _constructDeletedAt() { - return GeneratedDateTimeColumn( - 'deleted_at', - $tableName, - true, - ); - } - - final VerificationMeta _memberCountMeta = - const VerificationMeta('memberCount'); - GeneratedIntColumn _memberCount; - @override - GeneratedIntColumn get memberCount => - _memberCount ??= _constructMemberCount(); - GeneratedIntColumn _constructMemberCount() { - return GeneratedIntColumn( - 'member_count', - $tableName, - true, - ); - } - - final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); - GeneratedTextColumn _extraData; - @override - GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); - GeneratedTextColumn _constructExtraData() { - return GeneratedTextColumn( - 'extra_data', - $tableName, - true, - ); - } - - final VerificationMeta _createdByMeta = const VerificationMeta('createdBy'); - GeneratedTextColumn _createdBy; - @override - GeneratedTextColumn get createdBy => _createdBy ??= _constructCreatedBy(); - GeneratedTextColumn _constructCreatedBy() { - return GeneratedTextColumn( - 'created_by', - $tableName, - true, - ); - } - - @override - List get $columns => [ - id, - type, - cid, - config, - frozen, - lastMessageAt, - createdAt, - updatedAt, - deletedAt, - memberCount, - extraData, - createdBy - ]; - @override - $_ChannelsTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'channels'; - @override - final String actualTableName = 'channels'; - @override - VerificationContext validateIntegrity(Insertable<_Channel> instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('id')) { - context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); - } else if (isInserting) { - context.missing(_idMeta); - } - if (data.containsKey('type')) { - context.handle( - _typeMeta, type.isAcceptableOrUnknown(data['type'], _typeMeta)); - } else if (isInserting) { - context.missing(_typeMeta); - } - if (data.containsKey('cid')) { - context.handle( - _cidMeta, cid.isAcceptableOrUnknown(data['cid'], _cidMeta)); - } else if (isInserting) { - context.missing(_cidMeta); - } - if (data.containsKey('config')) { - context.handle(_configMeta, - config.isAcceptableOrUnknown(data['config'], _configMeta)); - } else if (isInserting) { - context.missing(_configMeta); - } - if (data.containsKey('frozen')) { - context.handle(_frozenMeta, - frozen.isAcceptableOrUnknown(data['frozen'], _frozenMeta)); - } - if (data.containsKey('last_message_at')) { - context.handle( - _lastMessageAtMeta, - lastMessageAt.isAcceptableOrUnknown( - data['last_message_at'], _lastMessageAtMeta)); - } - if (data.containsKey('created_at')) { - context.handle(_createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); - } - if (data.containsKey('updated_at')) { - context.handle(_updatedAtMeta, - updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); - } - if (data.containsKey('deleted_at')) { - context.handle(_deletedAtMeta, - deletedAt.isAcceptableOrUnknown(data['deleted_at'], _deletedAtMeta)); - } - if (data.containsKey('member_count')) { - context.handle( - _memberCountMeta, - memberCount.isAcceptableOrUnknown( - data['member_count'], _memberCountMeta)); - } - context.handle(_extraDataMeta, const VerificationResult.success()); - if (data.containsKey('created_by')) { - context.handle(_createdByMeta, - createdBy.isAcceptableOrUnknown(data['created_by'], _createdByMeta)); - } - return context; - } - - @override - Set get $primaryKey => {cid}; - @override - _Channel map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return _Channel.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_ChannelsTable createAlias(String alias) { - return $_ChannelsTable(_db, alias); - } - - static TypeConverter, String> $converter0 = - _ExtraDataConverter(); -} - -class _User extends DataClass implements Insertable<_User> { - final String id; - final String role; - final DateTime createdAt; - final DateTime updatedAt; - final DateTime lastActive; - final bool online; - final bool banned; - final Map extraData; - _User( - {@required this.id, - this.role, - this.createdAt, - this.updatedAt, - this.lastActive, - this.online, - this.banned, - this.extraData}); - factory _User.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final stringType = db.typeSystem.forDartType(); - final dateTimeType = db.typeSystem.forDartType(); - final boolType = db.typeSystem.forDartType(); - return _User( - id: stringType.mapFromDatabaseResponse(data['${effectivePrefix}id']), - role: stringType.mapFromDatabaseResponse(data['${effectivePrefix}role']), - createdAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), - updatedAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), - lastActive: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}last_active']), - online: - boolType.mapFromDatabaseResponse(data['${effectivePrefix}online']), - banned: - boolType.mapFromDatabaseResponse(data['${effectivePrefix}banned']), - extraData: $_UsersTable.$converter0.mapToDart(stringType - .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || id != null) { - map['id'] = Variable(id); - } - if (!nullToAbsent || role != null) { - map['role'] = Variable(role); - } - if (!nullToAbsent || createdAt != null) { - map['created_at'] = Variable(createdAt); - } - if (!nullToAbsent || updatedAt != null) { - map['updated_at'] = Variable(updatedAt); - } - if (!nullToAbsent || lastActive != null) { - map['last_active'] = Variable(lastActive); - } - if (!nullToAbsent || online != null) { - map['online'] = Variable(online); - } - if (!nullToAbsent || banned != null) { - map['banned'] = Variable(banned); - } - if (!nullToAbsent || extraData != null) { - final converter = $_UsersTable.$converter0; - map['extra_data'] = Variable(converter.mapToSql(extraData)); - } - return map; - } - - _UsersCompanion toCompanion(bool nullToAbsent) { - return _UsersCompanion( - id: id == null && nullToAbsent ? const Value.absent() : Value(id), - role: role == null && nullToAbsent ? const Value.absent() : Value(role), - createdAt: createdAt == null && nullToAbsent - ? const Value.absent() - : Value(createdAt), - updatedAt: updatedAt == null && nullToAbsent - ? const Value.absent() - : Value(updatedAt), - lastActive: lastActive == null && nullToAbsent - ? const Value.absent() - : Value(lastActive), - online: - online == null && nullToAbsent ? const Value.absent() : Value(online), - banned: - banned == null && nullToAbsent ? const Value.absent() : Value(banned), - extraData: extraData == null && nullToAbsent - ? const Value.absent() - : Value(extraData), - ); - } - - factory _User.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return _User( - id: serializer.fromJson(json['id']), - role: serializer.fromJson(json['role']), - createdAt: serializer.fromJson(json['createdAt']), - updatedAt: serializer.fromJson(json['updatedAt']), - lastActive: serializer.fromJson(json['lastActive']), - online: serializer.fromJson(json['online']), - banned: serializer.fromJson(json['banned']), - extraData: serializer.fromJson>(json['extraData']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'id': serializer.toJson(id), - 'role': serializer.toJson(role), - 'createdAt': serializer.toJson(createdAt), - 'updatedAt': serializer.toJson(updatedAt), - 'lastActive': serializer.toJson(lastActive), - 'online': serializer.toJson(online), - 'banned': serializer.toJson(banned), - 'extraData': serializer.toJson>(extraData), - }; - } - - _User copyWith( - {String id, - String role, - DateTime createdAt, - DateTime updatedAt, - DateTime lastActive, - bool online, - bool banned, - Map extraData}) => - _User( - id: id ?? this.id, - role: role ?? this.role, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - lastActive: lastActive ?? this.lastActive, - online: online ?? this.online, - banned: banned ?? this.banned, - extraData: extraData ?? this.extraData, - ); - @override - String toString() { - return (StringBuffer('_User(') - ..write('id: $id, ') - ..write('role: $role, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('lastActive: $lastActive, ') - ..write('online: $online, ') - ..write('banned: $banned, ') - ..write('extraData: $extraData') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc( - id.hashCode, - $mrjc( - role.hashCode, - $mrjc( - createdAt.hashCode, - $mrjc( - updatedAt.hashCode, - $mrjc( - lastActive.hashCode, - $mrjc(online.hashCode, - $mrjc(banned.hashCode, extraData.hashCode)))))))); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is _User && - other.id == this.id && - other.role == this.role && - other.createdAt == this.createdAt && - other.updatedAt == this.updatedAt && - other.lastActive == this.lastActive && - other.online == this.online && - other.banned == this.banned && - other.extraData == this.extraData); -} - -class _UsersCompanion extends UpdateCompanion<_User> { - final Value id; - final Value role; - final Value createdAt; - final Value updatedAt; - final Value lastActive; - final Value online; - final Value banned; - final Value> extraData; - const _UsersCompanion({ - this.id = const Value.absent(), - this.role = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), - this.lastActive = const Value.absent(), - this.online = const Value.absent(), - this.banned = const Value.absent(), - this.extraData = const Value.absent(), - }); - _UsersCompanion.insert({ - @required String id, - this.role = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), - this.lastActive = const Value.absent(), - this.online = const Value.absent(), - this.banned = const Value.absent(), - this.extraData = const Value.absent(), - }) : id = Value(id); - static Insertable<_User> custom({ - Expression id, - Expression role, - Expression createdAt, - Expression updatedAt, - Expression lastActive, - Expression online, - Expression banned, - Expression extraData, - }) { - return RawValuesInsertable({ - if (id != null) 'id': id, - if (role != null) 'role': role, - if (createdAt != null) 'created_at': createdAt, - if (updatedAt != null) 'updated_at': updatedAt, - if (lastActive != null) 'last_active': lastActive, - if (online != null) 'online': online, - if (banned != null) 'banned': banned, - if (extraData != null) 'extra_data': extraData, - }); - } - - _UsersCompanion copyWith( - {Value id, - Value role, - Value createdAt, - Value updatedAt, - Value lastActive, - Value online, - Value banned, - Value> extraData}) { - return _UsersCompanion( - id: id ?? this.id, - role: role ?? this.role, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - lastActive: lastActive ?? this.lastActive, - online: online ?? this.online, - banned: banned ?? this.banned, - extraData: extraData ?? this.extraData, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (id.present) { - map['id'] = Variable(id.value); - } - if (role.present) { - map['role'] = Variable(role.value); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (updatedAt.present) { - map['updated_at'] = Variable(updatedAt.value); - } - if (lastActive.present) { - map['last_active'] = Variable(lastActive.value); - } - if (online.present) { - map['online'] = Variable(online.value); - } - if (banned.present) { - map['banned'] = Variable(banned.value); - } - if (extraData.present) { - final converter = $_UsersTable.$converter0; - map['extra_data'] = Variable(converter.mapToSql(extraData.value)); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_UsersCompanion(') - ..write('id: $id, ') - ..write('role: $role, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('lastActive: $lastActive, ') - ..write('online: $online, ') - ..write('banned: $banned, ') - ..write('extraData: $extraData') - ..write(')')) - .toString(); - } -} - -class $_UsersTable extends _Users with TableInfo<$_UsersTable, _User> { - final GeneratedDatabase _db; - final String _alias; - $_UsersTable(this._db, [this._alias]); - final VerificationMeta _idMeta = const VerificationMeta('id'); - GeneratedTextColumn _id; - @override - GeneratedTextColumn get id => _id ??= _constructId(); - GeneratedTextColumn _constructId() { - return GeneratedTextColumn( - 'id', - $tableName, - false, - ); - } - - final VerificationMeta _roleMeta = const VerificationMeta('role'); - GeneratedTextColumn _role; - @override - GeneratedTextColumn get role => _role ??= _constructRole(); - GeneratedTextColumn _constructRole() { - return GeneratedTextColumn( - 'role', - $tableName, - true, - ); - } - - final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); - GeneratedDateTimeColumn _createdAt; - @override - GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); - GeneratedDateTimeColumn _constructCreatedAt() { - return GeneratedDateTimeColumn( - 'created_at', - $tableName, - true, - ); - } - - final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); - GeneratedDateTimeColumn _updatedAt; - @override - GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); - GeneratedDateTimeColumn _constructUpdatedAt() { - return GeneratedDateTimeColumn( - 'updated_at', - $tableName, - true, - ); - } - - final VerificationMeta _lastActiveMeta = const VerificationMeta('lastActive'); - GeneratedDateTimeColumn _lastActive; - @override - GeneratedDateTimeColumn get lastActive => - _lastActive ??= _constructLastActive(); - GeneratedDateTimeColumn _constructLastActive() { - return GeneratedDateTimeColumn( - 'last_active', - $tableName, - true, - ); - } - - final VerificationMeta _onlineMeta = const VerificationMeta('online'); - GeneratedBoolColumn _online; - @override - GeneratedBoolColumn get online => _online ??= _constructOnline(); - GeneratedBoolColumn _constructOnline() { - return GeneratedBoolColumn( - 'online', - $tableName, - true, - ); - } - - final VerificationMeta _bannedMeta = const VerificationMeta('banned'); - GeneratedBoolColumn _banned; - @override - GeneratedBoolColumn get banned => _banned ??= _constructBanned(); - GeneratedBoolColumn _constructBanned() { - return GeneratedBoolColumn( - 'banned', - $tableName, - true, - ); - } - - final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); - GeneratedTextColumn _extraData; - @override - GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); - GeneratedTextColumn _constructExtraData() { - return GeneratedTextColumn( - 'extra_data', - $tableName, - true, - ); - } - - @override - List get $columns => - [id, role, createdAt, updatedAt, lastActive, online, banned, extraData]; - @override - $_UsersTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'users'; - @override - final String actualTableName = 'users'; - @override - VerificationContext validateIntegrity(Insertable<_User> instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('id')) { - context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); - } else if (isInserting) { - context.missing(_idMeta); - } - if (data.containsKey('role')) { - context.handle( - _roleMeta, role.isAcceptableOrUnknown(data['role'], _roleMeta)); - } - if (data.containsKey('created_at')) { - context.handle(_createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); - } - if (data.containsKey('updated_at')) { - context.handle(_updatedAtMeta, - updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); - } - if (data.containsKey('last_active')) { - context.handle( - _lastActiveMeta, - lastActive.isAcceptableOrUnknown( - data['last_active'], _lastActiveMeta)); - } - if (data.containsKey('online')) { - context.handle(_onlineMeta, - online.isAcceptableOrUnknown(data['online'], _onlineMeta)); - } - if (data.containsKey('banned')) { - context.handle(_bannedMeta, - banned.isAcceptableOrUnknown(data['banned'], _bannedMeta)); - } - context.handle(_extraDataMeta, const VerificationResult.success()); - return context; - } - - @override - Set get $primaryKey => {id}; - @override - _User map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return _User.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_UsersTable createAlias(String alias) { - return $_UsersTable(_db, alias); - } - - static TypeConverter, String> $converter0 = - _ExtraDataConverter(); -} - -class _Message extends DataClass implements Insertable<_Message> { - final String id; - final String messageText; - final String attachmentJson; - final MessageSendingStatus status; - final String type; - final Map reactionCounts; - final Map reactionScores; - final String parentId; - final String quotedMessageId; - final int replyCount; - final bool showInChannel; - final bool shadowed; - final String command; - final DateTime createdAt; - final DateTime updatedAt; - final DateTime deletedAt; - final String userId; - final String channelCid; - final Map extraData; - _Message( - {@required this.id, - this.messageText, - this.attachmentJson, - this.status, - this.type, - this.reactionCounts, - this.reactionScores, - this.parentId, - this.quotedMessageId, - this.replyCount, - this.showInChannel, - this.shadowed, - this.command, - @required this.createdAt, - this.updatedAt, - this.deletedAt, - this.userId, - this.channelCid, - this.extraData}); - factory _Message.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final stringType = db.typeSystem.forDartType(); - final intType = db.typeSystem.forDartType(); - final boolType = db.typeSystem.forDartType(); - final dateTimeType = db.typeSystem.forDartType(); - return _Message( - id: stringType.mapFromDatabaseResponse(data['${effectivePrefix}id']), - messageText: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}message_text']), - attachmentJson: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}attachment_json']), - status: $_MessagesTable.$converter0.mapToDart( - intType.mapFromDatabaseResponse(data['${effectivePrefix}status'])), - type: stringType.mapFromDatabaseResponse(data['${effectivePrefix}type']), - reactionCounts: $_MessagesTable.$converter1.mapToDart(stringType - .mapFromDatabaseResponse(data['${effectivePrefix}reaction_counts'])), - reactionScores: $_MessagesTable.$converter2.mapToDart(stringType - .mapFromDatabaseResponse(data['${effectivePrefix}reaction_scores'])), - parentId: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}parent_id']), - quotedMessageId: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}quoted_message_id']), - replyCount: intType - .mapFromDatabaseResponse(data['${effectivePrefix}reply_count']), - showInChannel: boolType - .mapFromDatabaseResponse(data['${effectivePrefix}show_in_channel']), - shadowed: - boolType.mapFromDatabaseResponse(data['${effectivePrefix}shadowed']), - command: - stringType.mapFromDatabaseResponse(data['${effectivePrefix}command']), - createdAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), - updatedAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), - deletedAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}deleted_at']), - userId: - stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), - channelCid: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), - extraData: $_MessagesTable.$converter3.mapToDart(stringType - .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || id != null) { - map['id'] = Variable(id); - } - if (!nullToAbsent || messageText != null) { - map['message_text'] = Variable(messageText); - } - if (!nullToAbsent || attachmentJson != null) { - map['attachment_json'] = Variable(attachmentJson); - } - if (!nullToAbsent || status != null) { - final converter = $_MessagesTable.$converter0; - map['status'] = Variable(converter.mapToSql(status)); - } - if (!nullToAbsent || type != null) { - map['type'] = Variable(type); - } - if (!nullToAbsent || reactionCounts != null) { - final converter = $_MessagesTable.$converter1; - map['reaction_counts'] = - Variable(converter.mapToSql(reactionCounts)); - } - if (!nullToAbsent || reactionScores != null) { - final converter = $_MessagesTable.$converter2; - map['reaction_scores'] = - Variable(converter.mapToSql(reactionScores)); - } - if (!nullToAbsent || parentId != null) { - map['parent_id'] = Variable(parentId); - } - if (!nullToAbsent || quotedMessageId != null) { - map['quoted_message_id'] = Variable(quotedMessageId); - } - if (!nullToAbsent || replyCount != null) { - map['reply_count'] = Variable(replyCount); - } - if (!nullToAbsent || showInChannel != null) { - map['show_in_channel'] = Variable(showInChannel); - } - if (!nullToAbsent || shadowed != null) { - map['shadowed'] = Variable(shadowed); - } - if (!nullToAbsent || command != null) { - map['command'] = Variable(command); - } - if (!nullToAbsent || createdAt != null) { - map['created_at'] = Variable(createdAt); - } - if (!nullToAbsent || updatedAt != null) { - map['updated_at'] = Variable(updatedAt); - } - if (!nullToAbsent || deletedAt != null) { - map['deleted_at'] = Variable(deletedAt); - } - if (!nullToAbsent || userId != null) { - map['user_id'] = Variable(userId); - } - if (!nullToAbsent || channelCid != null) { - map['channel_cid'] = Variable(channelCid); - } - if (!nullToAbsent || extraData != null) { - final converter = $_MessagesTable.$converter3; - map['extra_data'] = Variable(converter.mapToSql(extraData)); - } - return map; - } - - _MessagesCompanion toCompanion(bool nullToAbsent) { - return _MessagesCompanion( - id: id == null && nullToAbsent ? const Value.absent() : Value(id), - messageText: messageText == null && nullToAbsent - ? const Value.absent() - : Value(messageText), - attachmentJson: attachmentJson == null && nullToAbsent - ? const Value.absent() - : Value(attachmentJson), - status: - status == null && nullToAbsent ? const Value.absent() : Value(status), - type: type == null && nullToAbsent ? const Value.absent() : Value(type), - reactionCounts: reactionCounts == null && nullToAbsent - ? const Value.absent() - : Value(reactionCounts), - reactionScores: reactionScores == null && nullToAbsent - ? const Value.absent() - : Value(reactionScores), - parentId: parentId == null && nullToAbsent - ? const Value.absent() - : Value(parentId), - quotedMessageId: quotedMessageId == null && nullToAbsent - ? const Value.absent() - : Value(quotedMessageId), - replyCount: replyCount == null && nullToAbsent - ? const Value.absent() - : Value(replyCount), - showInChannel: showInChannel == null && nullToAbsent - ? const Value.absent() - : Value(showInChannel), - shadowed: shadowed == null && nullToAbsent - ? const Value.absent() - : Value(shadowed), - command: command == null && nullToAbsent - ? const Value.absent() - : Value(command), - createdAt: createdAt == null && nullToAbsent - ? const Value.absent() - : Value(createdAt), - updatedAt: updatedAt == null && nullToAbsent - ? const Value.absent() - : Value(updatedAt), - deletedAt: deletedAt == null && nullToAbsent - ? const Value.absent() - : Value(deletedAt), - userId: - userId == null && nullToAbsent ? const Value.absent() : Value(userId), - channelCid: channelCid == null && nullToAbsent - ? const Value.absent() - : Value(channelCid), - extraData: extraData == null && nullToAbsent - ? const Value.absent() - : Value(extraData), - ); - } - - factory _Message.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return _Message( - id: serializer.fromJson(json['id']), - messageText: serializer.fromJson(json['messageText']), - attachmentJson: serializer.fromJson(json['attachmentJson']), - status: serializer.fromJson(json['status']), - type: serializer.fromJson(json['type']), - reactionCounts: - serializer.fromJson>(json['reactionCounts']), - reactionScores: - serializer.fromJson>(json['reactionScores']), - parentId: serializer.fromJson(json['parentId']), - quotedMessageId: serializer.fromJson(json['quotedMessageId']), - replyCount: serializer.fromJson(json['replyCount']), - showInChannel: serializer.fromJson(json['showInChannel']), - shadowed: serializer.fromJson(json['shadowed']), - command: serializer.fromJson(json['command']), - createdAt: serializer.fromJson(json['createdAt']), - updatedAt: serializer.fromJson(json['updatedAt']), - deletedAt: serializer.fromJson(json['deletedAt']), - userId: serializer.fromJson(json['userId']), - channelCid: serializer.fromJson(json['channelCid']), - extraData: serializer.fromJson>(json['extraData']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'id': serializer.toJson(id), - 'messageText': serializer.toJson(messageText), - 'attachmentJson': serializer.toJson(attachmentJson), - 'status': serializer.toJson(status), - 'type': serializer.toJson(type), - 'reactionCounts': serializer.toJson>(reactionCounts), - 'reactionScores': serializer.toJson>(reactionScores), - 'parentId': serializer.toJson(parentId), - 'quotedMessageId': serializer.toJson(quotedMessageId), - 'replyCount': serializer.toJson(replyCount), - 'showInChannel': serializer.toJson(showInChannel), - 'shadowed': serializer.toJson(shadowed), - 'command': serializer.toJson(command), - 'createdAt': serializer.toJson(createdAt), - 'updatedAt': serializer.toJson(updatedAt), - 'deletedAt': serializer.toJson(deletedAt), - 'userId': serializer.toJson(userId), - 'channelCid': serializer.toJson(channelCid), - 'extraData': serializer.toJson>(extraData), - }; - } - - _Message copyWith( - {String id, - String messageText, - String attachmentJson, - MessageSendingStatus status, - String type, - Map reactionCounts, - Map reactionScores, - String parentId, - String quotedMessageId, - int replyCount, - bool showInChannel, - bool shadowed, - String command, - DateTime createdAt, - DateTime updatedAt, - DateTime deletedAt, - String userId, - String channelCid, - Map extraData}) => - _Message( - id: id ?? this.id, - messageText: messageText ?? this.messageText, - attachmentJson: attachmentJson ?? this.attachmentJson, - status: status ?? this.status, - type: type ?? this.type, - reactionCounts: reactionCounts ?? this.reactionCounts, - reactionScores: reactionScores ?? this.reactionScores, - parentId: parentId ?? this.parentId, - quotedMessageId: quotedMessageId ?? this.quotedMessageId, - replyCount: replyCount ?? this.replyCount, - showInChannel: showInChannel ?? this.showInChannel, - shadowed: shadowed ?? this.shadowed, - command: command ?? this.command, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - extraData: extraData ?? this.extraData, - ); - @override - String toString() { - return (StringBuffer('_Message(') - ..write('id: $id, ') - ..write('messageText: $messageText, ') - ..write('attachmentJson: $attachmentJson, ') - ..write('status: $status, ') - ..write('type: $type, ') - ..write('reactionCounts: $reactionCounts, ') - ..write('reactionScores: $reactionScores, ') - ..write('parentId: $parentId, ') - ..write('quotedMessageId: $quotedMessageId, ') - ..write('replyCount: $replyCount, ') - ..write('showInChannel: $showInChannel, ') - ..write('shadowed: $shadowed, ') - ..write('command: $command, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('deletedAt: $deletedAt, ') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('extraData: $extraData') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc( - id.hashCode, - $mrjc( - messageText.hashCode, - $mrjc( - attachmentJson.hashCode, - $mrjc( - status.hashCode, - $mrjc( - type.hashCode, - $mrjc( - reactionCounts.hashCode, - $mrjc( - reactionScores.hashCode, - $mrjc( - parentId.hashCode, - $mrjc( - quotedMessageId.hashCode, - $mrjc( - replyCount.hashCode, - $mrjc( - showInChannel.hashCode, - $mrjc( - shadowed.hashCode, - $mrjc( - command.hashCode, - $mrjc( - createdAt.hashCode, - $mrjc( - updatedAt - .hashCode, - $mrjc( - deletedAt - .hashCode, - $mrjc( - userId - .hashCode, - $mrjc( - channelCid - .hashCode, - extraData - .hashCode))))))))))))))))))); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is _Message && - other.id == this.id && - other.messageText == this.messageText && - other.attachmentJson == this.attachmentJson && - other.status == this.status && - other.type == this.type && - other.reactionCounts == this.reactionCounts && - other.reactionScores == this.reactionScores && - other.parentId == this.parentId && - other.quotedMessageId == this.quotedMessageId && - other.replyCount == this.replyCount && - other.showInChannel == this.showInChannel && - other.shadowed == this.shadowed && - other.command == this.command && - other.createdAt == this.createdAt && - other.updatedAt == this.updatedAt && - other.deletedAt == this.deletedAt && - other.userId == this.userId && - other.channelCid == this.channelCid && - other.extraData == this.extraData); -} - -class _MessagesCompanion extends UpdateCompanion<_Message> { - final Value id; - final Value messageText; - final Value attachmentJson; - final Value status; - final Value type; - final Value> reactionCounts; - final Value> reactionScores; - final Value parentId; - final Value quotedMessageId; - final Value replyCount; - final Value showInChannel; - final Value shadowed; - final Value command; - final Value createdAt; - final Value updatedAt; - final Value deletedAt; - final Value userId; - final Value channelCid; - final Value> extraData; - const _MessagesCompanion({ - this.id = const Value.absent(), - this.messageText = const Value.absent(), - this.attachmentJson = const Value.absent(), - this.status = const Value.absent(), - this.type = const Value.absent(), - this.reactionCounts = const Value.absent(), - this.reactionScores = const Value.absent(), - this.parentId = const Value.absent(), - this.quotedMessageId = const Value.absent(), - this.replyCount = const Value.absent(), - this.showInChannel = const Value.absent(), - this.shadowed = const Value.absent(), - this.command = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), - this.deletedAt = const Value.absent(), - this.userId = const Value.absent(), - this.channelCid = const Value.absent(), - this.extraData = const Value.absent(), - }); - _MessagesCompanion.insert({ - @required String id, - this.messageText = const Value.absent(), - this.attachmentJson = const Value.absent(), - this.status = const Value.absent(), - this.type = const Value.absent(), - this.reactionCounts = const Value.absent(), - this.reactionScores = const Value.absent(), - this.parentId = const Value.absent(), - this.quotedMessageId = const Value.absent(), - this.replyCount = const Value.absent(), - this.showInChannel = const Value.absent(), - this.shadowed = const Value.absent(), - this.command = const Value.absent(), - @required DateTime createdAt, - this.updatedAt = const Value.absent(), - this.deletedAt = const Value.absent(), - this.userId = const Value.absent(), - this.channelCid = const Value.absent(), - this.extraData = const Value.absent(), - }) : id = Value(id), - createdAt = Value(createdAt); - static Insertable<_Message> custom({ - Expression id, - Expression messageText, - Expression attachmentJson, - Expression status, - Expression type, - Expression reactionCounts, - Expression reactionScores, - Expression parentId, - Expression quotedMessageId, - Expression replyCount, - Expression showInChannel, - Expression shadowed, - Expression command, - Expression createdAt, - Expression updatedAt, - Expression deletedAt, - Expression userId, - Expression channelCid, - Expression extraData, - }) { - return RawValuesInsertable({ - if (id != null) 'id': id, - if (messageText != null) 'message_text': messageText, - if (attachmentJson != null) 'attachment_json': attachmentJson, - if (status != null) 'status': status, - if (type != null) 'type': type, - if (reactionCounts != null) 'reaction_counts': reactionCounts, - if (reactionScores != null) 'reaction_scores': reactionScores, - if (parentId != null) 'parent_id': parentId, - if (quotedMessageId != null) 'quoted_message_id': quotedMessageId, - if (replyCount != null) 'reply_count': replyCount, - if (showInChannel != null) 'show_in_channel': showInChannel, - if (shadowed != null) 'shadowed': shadowed, - if (command != null) 'command': command, - if (createdAt != null) 'created_at': createdAt, - if (updatedAt != null) 'updated_at': updatedAt, - if (deletedAt != null) 'deleted_at': deletedAt, - if (userId != null) 'user_id': userId, - if (channelCid != null) 'channel_cid': channelCid, - if (extraData != null) 'extra_data': extraData, - }); - } - - _MessagesCompanion copyWith( - {Value id, - Value messageText, - Value attachmentJson, - Value status, - Value type, - Value> reactionCounts, - Value> reactionScores, - Value parentId, - Value quotedMessageId, - Value replyCount, - Value showInChannel, - Value shadowed, - Value command, - Value createdAt, - Value updatedAt, - Value deletedAt, - Value userId, - Value channelCid, - Value> extraData}) { - return _MessagesCompanion( - id: id ?? this.id, - messageText: messageText ?? this.messageText, - attachmentJson: attachmentJson ?? this.attachmentJson, - status: status ?? this.status, - type: type ?? this.type, - reactionCounts: reactionCounts ?? this.reactionCounts, - reactionScores: reactionScores ?? this.reactionScores, - parentId: parentId ?? this.parentId, - quotedMessageId: quotedMessageId ?? this.quotedMessageId, - replyCount: replyCount ?? this.replyCount, - showInChannel: showInChannel ?? this.showInChannel, - shadowed: shadowed ?? this.shadowed, - command: command ?? this.command, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - extraData: extraData ?? this.extraData, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (id.present) { - map['id'] = Variable(id.value); - } - if (messageText.present) { - map['message_text'] = Variable(messageText.value); - } - if (attachmentJson.present) { - map['attachment_json'] = Variable(attachmentJson.value); - } - if (status.present) { - final converter = $_MessagesTable.$converter0; - map['status'] = Variable(converter.mapToSql(status.value)); - } - if (type.present) { - map['type'] = Variable(type.value); - } - if (reactionCounts.present) { - final converter = $_MessagesTable.$converter1; - map['reaction_counts'] = - Variable(converter.mapToSql(reactionCounts.value)); - } - if (reactionScores.present) { - final converter = $_MessagesTable.$converter2; - map['reaction_scores'] = - Variable(converter.mapToSql(reactionScores.value)); - } - if (parentId.present) { - map['parent_id'] = Variable(parentId.value); - } - if (quotedMessageId.present) { - map['quoted_message_id'] = Variable(quotedMessageId.value); - } - if (replyCount.present) { - map['reply_count'] = Variable(replyCount.value); - } - if (showInChannel.present) { - map['show_in_channel'] = Variable(showInChannel.value); - } - if (shadowed.present) { - map['shadowed'] = Variable(shadowed.value); - } - if (command.present) { - map['command'] = Variable(command.value); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (updatedAt.present) { - map['updated_at'] = Variable(updatedAt.value); - } - if (deletedAt.present) { - map['deleted_at'] = Variable(deletedAt.value); - } - if (userId.present) { - map['user_id'] = Variable(userId.value); - } - if (channelCid.present) { - map['channel_cid'] = Variable(channelCid.value); - } - if (extraData.present) { - final converter = $_MessagesTable.$converter3; - map['extra_data'] = Variable(converter.mapToSql(extraData.value)); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_MessagesCompanion(') - ..write('id: $id, ') - ..write('messageText: $messageText, ') - ..write('attachmentJson: $attachmentJson, ') - ..write('status: $status, ') - ..write('type: $type, ') - ..write('reactionCounts: $reactionCounts, ') - ..write('reactionScores: $reactionScores, ') - ..write('parentId: $parentId, ') - ..write('quotedMessageId: $quotedMessageId, ') - ..write('replyCount: $replyCount, ') - ..write('showInChannel: $showInChannel, ') - ..write('shadowed: $shadowed, ') - ..write('command: $command, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('deletedAt: $deletedAt, ') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('extraData: $extraData') - ..write(')')) - .toString(); - } -} - -class $_MessagesTable extends _Messages - with TableInfo<$_MessagesTable, _Message> { - final GeneratedDatabase _db; - final String _alias; - $_MessagesTable(this._db, [this._alias]); - final VerificationMeta _idMeta = const VerificationMeta('id'); - GeneratedTextColumn _id; - @override - GeneratedTextColumn get id => _id ??= _constructId(); - GeneratedTextColumn _constructId() { - return GeneratedTextColumn( - 'id', - $tableName, - false, - ); - } - - final VerificationMeta _messageTextMeta = - const VerificationMeta('messageText'); - GeneratedTextColumn _messageText; - @override - GeneratedTextColumn get messageText => - _messageText ??= _constructMessageText(); - GeneratedTextColumn _constructMessageText() { - return GeneratedTextColumn( - 'message_text', - $tableName, - true, - ); - } - - final VerificationMeta _attachmentJsonMeta = - const VerificationMeta('attachmentJson'); - GeneratedTextColumn _attachmentJson; - @override - GeneratedTextColumn get attachmentJson => - _attachmentJson ??= _constructAttachmentJson(); - GeneratedTextColumn _constructAttachmentJson() { - return GeneratedTextColumn( - 'attachment_json', - $tableName, - true, - ); - } - - final VerificationMeta _statusMeta = const VerificationMeta('status'); - GeneratedIntColumn _status; - @override - GeneratedIntColumn get status => _status ??= _constructStatus(); - GeneratedIntColumn _constructStatus() { - return GeneratedIntColumn( - 'status', - $tableName, - true, - ); - } - - final VerificationMeta _typeMeta = const VerificationMeta('type'); - GeneratedTextColumn _type; - @override - GeneratedTextColumn get type => _type ??= _constructType(); - GeneratedTextColumn _constructType() { - return GeneratedTextColumn( - 'type', - $tableName, - true, - ); - } - - final VerificationMeta _reactionCountsMeta = - const VerificationMeta('reactionCounts'); - GeneratedTextColumn _reactionCounts; - @override - GeneratedTextColumn get reactionCounts => - _reactionCounts ??= _constructReactionCounts(); - GeneratedTextColumn _constructReactionCounts() { - return GeneratedTextColumn( - 'reaction_counts', - $tableName, - true, - ); - } - - final VerificationMeta _reactionScoresMeta = - const VerificationMeta('reactionScores'); - GeneratedTextColumn _reactionScores; - @override - GeneratedTextColumn get reactionScores => - _reactionScores ??= _constructReactionScores(); - GeneratedTextColumn _constructReactionScores() { - return GeneratedTextColumn( - 'reaction_scores', - $tableName, - true, - ); - } - - final VerificationMeta _parentIdMeta = const VerificationMeta('parentId'); - GeneratedTextColumn _parentId; - @override - GeneratedTextColumn get parentId => _parentId ??= _constructParentId(); - GeneratedTextColumn _constructParentId() { - return GeneratedTextColumn( - 'parent_id', - $tableName, - true, - ); - } - - final VerificationMeta _quotedMessageIdMeta = - const VerificationMeta('quotedMessageId'); - GeneratedTextColumn _quotedMessageId; - @override - GeneratedTextColumn get quotedMessageId => - _quotedMessageId ??= _constructQuotedMessageId(); - GeneratedTextColumn _constructQuotedMessageId() { - return GeneratedTextColumn( - 'quoted_message_id', - $tableName, - true, - ); - } - - final VerificationMeta _replyCountMeta = const VerificationMeta('replyCount'); - GeneratedIntColumn _replyCount; - @override - GeneratedIntColumn get replyCount => _replyCount ??= _constructReplyCount(); - GeneratedIntColumn _constructReplyCount() { - return GeneratedIntColumn( - 'reply_count', - $tableName, - true, - ); - } - - final VerificationMeta _showInChannelMeta = - const VerificationMeta('showInChannel'); - GeneratedBoolColumn _showInChannel; - @override - GeneratedBoolColumn get showInChannel => - _showInChannel ??= _constructShowInChannel(); - GeneratedBoolColumn _constructShowInChannel() { - return GeneratedBoolColumn( - 'show_in_channel', - $tableName, - true, - ); - } - - final VerificationMeta _shadowedMeta = const VerificationMeta('shadowed'); - GeneratedBoolColumn _shadowed; - @override - GeneratedBoolColumn get shadowed => _shadowed ??= _constructShadowed(); - GeneratedBoolColumn _constructShadowed() { - return GeneratedBoolColumn( - 'shadowed', - $tableName, - true, - ); - } - - final VerificationMeta _commandMeta = const VerificationMeta('command'); - GeneratedTextColumn _command; - @override - GeneratedTextColumn get command => _command ??= _constructCommand(); - GeneratedTextColumn _constructCommand() { - return GeneratedTextColumn( - 'command', - $tableName, - true, - ); - } - - final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); - GeneratedDateTimeColumn _createdAt; - @override - GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); - GeneratedDateTimeColumn _constructCreatedAt() { - return GeneratedDateTimeColumn( - 'created_at', - $tableName, - false, - ); - } - - final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); - GeneratedDateTimeColumn _updatedAt; - @override - GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); - GeneratedDateTimeColumn _constructUpdatedAt() { - return GeneratedDateTimeColumn( - 'updated_at', - $tableName, - true, - ); - } - - final VerificationMeta _deletedAtMeta = const VerificationMeta('deletedAt'); - GeneratedDateTimeColumn _deletedAt; - @override - GeneratedDateTimeColumn get deletedAt => _deletedAt ??= _constructDeletedAt(); - GeneratedDateTimeColumn _constructDeletedAt() { - return GeneratedDateTimeColumn( - 'deleted_at', - $tableName, - true, - ); - } - - final VerificationMeta _userIdMeta = const VerificationMeta('userId'); - GeneratedTextColumn _userId; - @override - GeneratedTextColumn get userId => _userId ??= _constructUserId(); - GeneratedTextColumn _constructUserId() { - return GeneratedTextColumn( - 'user_id', - $tableName, - true, - ); - } - - final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); - GeneratedTextColumn _channelCid; - @override - GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); - GeneratedTextColumn _constructChannelCid() { - return GeneratedTextColumn( - 'channel_cid', - $tableName, - true, - ); - } - - final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); - GeneratedTextColumn _extraData; - @override - GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); - GeneratedTextColumn _constructExtraData() { - return GeneratedTextColumn( - 'extra_data', - $tableName, - true, - ); - } - - @override - List get $columns => [ - id, - messageText, - attachmentJson, - status, - type, - reactionCounts, - reactionScores, - parentId, - quotedMessageId, - replyCount, - showInChannel, - shadowed, - command, - createdAt, - updatedAt, - deletedAt, - userId, - channelCid, - extraData - ]; - @override - $_MessagesTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'messages'; - @override - final String actualTableName = 'messages'; - @override - VerificationContext validateIntegrity(Insertable<_Message> instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('id')) { - context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); - } else if (isInserting) { - context.missing(_idMeta); - } - if (data.containsKey('message_text')) { - context.handle( - _messageTextMeta, - messageText.isAcceptableOrUnknown( - data['message_text'], _messageTextMeta)); - } - if (data.containsKey('attachment_json')) { - context.handle( - _attachmentJsonMeta, - attachmentJson.isAcceptableOrUnknown( - data['attachment_json'], _attachmentJsonMeta)); - } - context.handle(_statusMeta, const VerificationResult.success()); - if (data.containsKey('type')) { - context.handle( - _typeMeta, type.isAcceptableOrUnknown(data['type'], _typeMeta)); - } - context.handle(_reactionCountsMeta, const VerificationResult.success()); - context.handle(_reactionScoresMeta, const VerificationResult.success()); - if (data.containsKey('parent_id')) { - context.handle(_parentIdMeta, - parentId.isAcceptableOrUnknown(data['parent_id'], _parentIdMeta)); - } - if (data.containsKey('quoted_message_id')) { - context.handle( - _quotedMessageIdMeta, - quotedMessageId.isAcceptableOrUnknown( - data['quoted_message_id'], _quotedMessageIdMeta)); - } - if (data.containsKey('reply_count')) { - context.handle( - _replyCountMeta, - replyCount.isAcceptableOrUnknown( - data['reply_count'], _replyCountMeta)); - } - if (data.containsKey('show_in_channel')) { - context.handle( - _showInChannelMeta, - showInChannel.isAcceptableOrUnknown( - data['show_in_channel'], _showInChannelMeta)); - } - if (data.containsKey('shadowed')) { - context.handle(_shadowedMeta, - shadowed.isAcceptableOrUnknown(data['shadowed'], _shadowedMeta)); - } - if (data.containsKey('command')) { - context.handle(_commandMeta, - command.isAcceptableOrUnknown(data['command'], _commandMeta)); - } - if (data.containsKey('created_at')) { - context.handle(_createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); - } else if (isInserting) { - context.missing(_createdAtMeta); - } - if (data.containsKey('updated_at')) { - context.handle(_updatedAtMeta, - updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); - } - if (data.containsKey('deleted_at')) { - context.handle(_deletedAtMeta, - deletedAt.isAcceptableOrUnknown(data['deleted_at'], _deletedAtMeta)); - } - if (data.containsKey('user_id')) { - context.handle(_userIdMeta, - userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); - } - if (data.containsKey('channel_cid')) { - context.handle( - _channelCidMeta, - channelCid.isAcceptableOrUnknown( - data['channel_cid'], _channelCidMeta)); - } - context.handle(_extraDataMeta, const VerificationResult.success()); - return context; - } - - @override - Set get $primaryKey => {id}; - @override - _Message map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return _Message.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_MessagesTable createAlias(String alias) { - return $_MessagesTable(_db, alias); - } - - static TypeConverter $converter0 = - _MessageSendingStatusConverter(); - static TypeConverter, String> $converter1 = - _ExtraDataConverter(); - static TypeConverter, String> $converter2 = - _ExtraDataConverter(); - static TypeConverter, String> $converter3 = - _ExtraDataConverter(); -} - -class _Read extends DataClass implements Insertable<_Read> { - final DateTime lastRead; - final String userId; - final String channelCid; - final int unreadMessages; - _Read( - {@required this.lastRead, - @required this.userId, - @required this.channelCid, - this.unreadMessages}); - factory _Read.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final dateTimeType = db.typeSystem.forDartType(); - final stringType = db.typeSystem.forDartType(); - final intType = db.typeSystem.forDartType(); - return _Read( - lastRead: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}last_read']), - userId: - stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), - channelCid: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), - unreadMessages: intType - .mapFromDatabaseResponse(data['${effectivePrefix}unread_messages']), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || lastRead != null) { - map['last_read'] = Variable(lastRead); - } - if (!nullToAbsent || userId != null) { - map['user_id'] = Variable(userId); - } - if (!nullToAbsent || channelCid != null) { - map['channel_cid'] = Variable(channelCid); - } - if (!nullToAbsent || unreadMessages != null) { - map['unread_messages'] = Variable(unreadMessages); - } - return map; - } - - _ReadsCompanion toCompanion(bool nullToAbsent) { - return _ReadsCompanion( - lastRead: lastRead == null && nullToAbsent - ? const Value.absent() - : Value(lastRead), - userId: - userId == null && nullToAbsent ? const Value.absent() : Value(userId), - channelCid: channelCid == null && nullToAbsent - ? const Value.absent() - : Value(channelCid), - unreadMessages: unreadMessages == null && nullToAbsent - ? const Value.absent() - : Value(unreadMessages), - ); - } - - factory _Read.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return _Read( - lastRead: serializer.fromJson(json['lastRead']), - userId: serializer.fromJson(json['userId']), - channelCid: serializer.fromJson(json['channelCid']), - unreadMessages: serializer.fromJson(json['unreadMessages']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'lastRead': serializer.toJson(lastRead), - 'userId': serializer.toJson(userId), - 'channelCid': serializer.toJson(channelCid), - 'unreadMessages': serializer.toJson(unreadMessages), - }; - } - - _Read copyWith( - {DateTime lastRead, - String userId, - String channelCid, - int unreadMessages}) => - _Read( - lastRead: lastRead ?? this.lastRead, - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - unreadMessages: unreadMessages ?? this.unreadMessages, - ); - @override - String toString() { - return (StringBuffer('_Read(') - ..write('lastRead: $lastRead, ') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('unreadMessages: $unreadMessages') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc( - lastRead.hashCode, - $mrjc(userId.hashCode, - $mrjc(channelCid.hashCode, unreadMessages.hashCode)))); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is _Read && - other.lastRead == this.lastRead && - other.userId == this.userId && - other.channelCid == this.channelCid && - other.unreadMessages == this.unreadMessages); -} - -class _ReadsCompanion extends UpdateCompanion<_Read> { - final Value lastRead; - final Value userId; - final Value channelCid; - final Value unreadMessages; - const _ReadsCompanion({ - this.lastRead = const Value.absent(), - this.userId = const Value.absent(), - this.channelCid = const Value.absent(), - this.unreadMessages = const Value.absent(), - }); - _ReadsCompanion.insert({ - @required DateTime lastRead, - @required String userId, - @required String channelCid, - this.unreadMessages = const Value.absent(), - }) : lastRead = Value(lastRead), - userId = Value(userId), - channelCid = Value(channelCid); - static Insertable<_Read> custom({ - Expression lastRead, - Expression userId, - Expression channelCid, - Expression unreadMessages, - }) { - return RawValuesInsertable({ - if (lastRead != null) 'last_read': lastRead, - if (userId != null) 'user_id': userId, - if (channelCid != null) 'channel_cid': channelCid, - if (unreadMessages != null) 'unread_messages': unreadMessages, - }); - } - - _ReadsCompanion copyWith( - {Value lastRead, - Value userId, - Value channelCid, - Value unreadMessages}) { - return _ReadsCompanion( - lastRead: lastRead ?? this.lastRead, - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - unreadMessages: unreadMessages ?? this.unreadMessages, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (lastRead.present) { - map['last_read'] = Variable(lastRead.value); - } - if (userId.present) { - map['user_id'] = Variable(userId.value); - } - if (channelCid.present) { - map['channel_cid'] = Variable(channelCid.value); - } - if (unreadMessages.present) { - map['unread_messages'] = Variable(unreadMessages.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_ReadsCompanion(') - ..write('lastRead: $lastRead, ') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('unreadMessages: $unreadMessages') - ..write(')')) - .toString(); - } -} - -class $_ReadsTable extends _Reads with TableInfo<$_ReadsTable, _Read> { - final GeneratedDatabase _db; - final String _alias; - $_ReadsTable(this._db, [this._alias]); - final VerificationMeta _lastReadMeta = const VerificationMeta('lastRead'); - GeneratedDateTimeColumn _lastRead; - @override - GeneratedDateTimeColumn get lastRead => _lastRead ??= _constructLastRead(); - GeneratedDateTimeColumn _constructLastRead() { - return GeneratedDateTimeColumn( - 'last_read', - $tableName, - false, - ); - } - - final VerificationMeta _userIdMeta = const VerificationMeta('userId'); - GeneratedTextColumn _userId; - @override - GeneratedTextColumn get userId => _userId ??= _constructUserId(); - GeneratedTextColumn _constructUserId() { - return GeneratedTextColumn( - 'user_id', - $tableName, - false, - ); - } - - final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); - GeneratedTextColumn _channelCid; - @override - GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); - GeneratedTextColumn _constructChannelCid() { - return GeneratedTextColumn( - 'channel_cid', - $tableName, - false, - ); - } - - final VerificationMeta _unreadMessagesMeta = - const VerificationMeta('unreadMessages'); - GeneratedIntColumn _unreadMessages; - @override - GeneratedIntColumn get unreadMessages => - _unreadMessages ??= _constructUnreadMessages(); - GeneratedIntColumn _constructUnreadMessages() { - return GeneratedIntColumn( - 'unread_messages', - $tableName, - true, - ); - } - - @override - List get $columns => - [lastRead, userId, channelCid, unreadMessages]; - @override - $_ReadsTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'reads'; - @override - final String actualTableName = 'reads'; - @override - VerificationContext validateIntegrity(Insertable<_Read> instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('last_read')) { - context.handle(_lastReadMeta, - lastRead.isAcceptableOrUnknown(data['last_read'], _lastReadMeta)); - } else if (isInserting) { - context.missing(_lastReadMeta); - } - if (data.containsKey('user_id')) { - context.handle(_userIdMeta, - userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); - } else if (isInserting) { - context.missing(_userIdMeta); - } - if (data.containsKey('channel_cid')) { - context.handle( - _channelCidMeta, - channelCid.isAcceptableOrUnknown( - data['channel_cid'], _channelCidMeta)); - } else if (isInserting) { - context.missing(_channelCidMeta); - } - if (data.containsKey('unread_messages')) { - context.handle( - _unreadMessagesMeta, - unreadMessages.isAcceptableOrUnknown( - data['unread_messages'], _unreadMessagesMeta)); - } - return context; - } - - @override - Set get $primaryKey => {userId, channelCid}; - @override - _Read map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return _Read.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_ReadsTable createAlias(String alias) { - return $_ReadsTable(_db, alias); - } -} - -class _Member extends DataClass implements Insertable<_Member> { - final String userId; - final String channelCid; - final String role; - final DateTime inviteAcceptedAt; - final DateTime inviteRejectedAt; - final bool invited; - final bool banned; - final bool shadowBanned; - final bool isModerator; - final DateTime createdAt; - final DateTime updatedAt; - _Member( - {@required this.userId, - @required this.channelCid, - this.role, - this.inviteAcceptedAt, - this.inviteRejectedAt, - this.invited, - this.banned, - this.shadowBanned, - this.isModerator, - @required this.createdAt, - this.updatedAt}); - factory _Member.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final stringType = db.typeSystem.forDartType(); - final dateTimeType = db.typeSystem.forDartType(); - final boolType = db.typeSystem.forDartType(); - return _Member( - userId: - stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), - channelCid: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), - role: stringType.mapFromDatabaseResponse(data['${effectivePrefix}role']), - inviteAcceptedAt: dateTimeType.mapFromDatabaseResponse( - data['${effectivePrefix}invite_accepted_at']), - inviteRejectedAt: dateTimeType.mapFromDatabaseResponse( - data['${effectivePrefix}invite_rejected_at']), - invited: - boolType.mapFromDatabaseResponse(data['${effectivePrefix}invited']), - banned: - boolType.mapFromDatabaseResponse(data['${effectivePrefix}banned']), - shadowBanned: boolType - .mapFromDatabaseResponse(data['${effectivePrefix}shadow_banned']), - isModerator: boolType - .mapFromDatabaseResponse(data['${effectivePrefix}is_moderator']), - createdAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), - updatedAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || userId != null) { - map['user_id'] = Variable(userId); - } - if (!nullToAbsent || channelCid != null) { - map['channel_cid'] = Variable(channelCid); - } - if (!nullToAbsent || role != null) { - map['role'] = Variable(role); - } - if (!nullToAbsent || inviteAcceptedAt != null) { - map['invite_accepted_at'] = Variable(inviteAcceptedAt); - } - if (!nullToAbsent || inviteRejectedAt != null) { - map['invite_rejected_at'] = Variable(inviteRejectedAt); - } - if (!nullToAbsent || invited != null) { - map['invited'] = Variable(invited); - } - if (!nullToAbsent || banned != null) { - map['banned'] = Variable(banned); - } - if (!nullToAbsent || shadowBanned != null) { - map['shadow_banned'] = Variable(shadowBanned); - } - if (!nullToAbsent || isModerator != null) { - map['is_moderator'] = Variable(isModerator); - } - if (!nullToAbsent || createdAt != null) { - map['created_at'] = Variable(createdAt); - } - if (!nullToAbsent || updatedAt != null) { - map['updated_at'] = Variable(updatedAt); - } - return map; - } - - _MembersCompanion toCompanion(bool nullToAbsent) { - return _MembersCompanion( - userId: - userId == null && nullToAbsent ? const Value.absent() : Value(userId), - channelCid: channelCid == null && nullToAbsent - ? const Value.absent() - : Value(channelCid), - role: role == null && nullToAbsent ? const Value.absent() : Value(role), - inviteAcceptedAt: inviteAcceptedAt == null && nullToAbsent - ? const Value.absent() - : Value(inviteAcceptedAt), - inviteRejectedAt: inviteRejectedAt == null && nullToAbsent - ? const Value.absent() - : Value(inviteRejectedAt), - invited: invited == null && nullToAbsent - ? const Value.absent() - : Value(invited), - banned: - banned == null && nullToAbsent ? const Value.absent() : Value(banned), - shadowBanned: shadowBanned == null && nullToAbsent - ? const Value.absent() - : Value(shadowBanned), - isModerator: isModerator == null && nullToAbsent - ? const Value.absent() - : Value(isModerator), - createdAt: createdAt == null && nullToAbsent - ? const Value.absent() - : Value(createdAt), - updatedAt: updatedAt == null && nullToAbsent - ? const Value.absent() - : Value(updatedAt), - ); - } - - factory _Member.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return _Member( - userId: serializer.fromJson(json['userId']), - channelCid: serializer.fromJson(json['channelCid']), - role: serializer.fromJson(json['role']), - inviteAcceptedAt: serializer.fromJson(json['inviteAcceptedAt']), - inviteRejectedAt: serializer.fromJson(json['inviteRejectedAt']), - invited: serializer.fromJson(json['invited']), - banned: serializer.fromJson(json['banned']), - shadowBanned: serializer.fromJson(json['shadowBanned']), - isModerator: serializer.fromJson(json['isModerator']), - createdAt: serializer.fromJson(json['createdAt']), - updatedAt: serializer.fromJson(json['updatedAt']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'userId': serializer.toJson(userId), - 'channelCid': serializer.toJson(channelCid), - 'role': serializer.toJson(role), - 'inviteAcceptedAt': serializer.toJson(inviteAcceptedAt), - 'inviteRejectedAt': serializer.toJson(inviteRejectedAt), - 'invited': serializer.toJson(invited), - 'banned': serializer.toJson(banned), - 'shadowBanned': serializer.toJson(shadowBanned), - 'isModerator': serializer.toJson(isModerator), - 'createdAt': serializer.toJson(createdAt), - 'updatedAt': serializer.toJson(updatedAt), - }; - } - - _Member copyWith( - {String userId, - String channelCid, - String role, - DateTime inviteAcceptedAt, - DateTime inviteRejectedAt, - bool invited, - bool banned, - bool shadowBanned, - bool isModerator, - DateTime createdAt, - DateTime updatedAt}) => - _Member( - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - role: role ?? this.role, - inviteAcceptedAt: inviteAcceptedAt ?? this.inviteAcceptedAt, - inviteRejectedAt: inviteRejectedAt ?? this.inviteRejectedAt, - invited: invited ?? this.invited, - banned: banned ?? this.banned, - shadowBanned: shadowBanned ?? this.shadowBanned, - isModerator: isModerator ?? this.isModerator, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - ); - @override - String toString() { - return (StringBuffer('_Member(') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('role: $role, ') - ..write('inviteAcceptedAt: $inviteAcceptedAt, ') - ..write('inviteRejectedAt: $inviteRejectedAt, ') - ..write('invited: $invited, ') - ..write('banned: $banned, ') - ..write('shadowBanned: $shadowBanned, ') - ..write('isModerator: $isModerator, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc( - userId.hashCode, - $mrjc( - channelCid.hashCode, - $mrjc( - role.hashCode, - $mrjc( - inviteAcceptedAt.hashCode, - $mrjc( - inviteRejectedAt.hashCode, - $mrjc( - invited.hashCode, - $mrjc( - banned.hashCode, - $mrjc( - shadowBanned.hashCode, - $mrjc( - isModerator.hashCode, - $mrjc(createdAt.hashCode, - updatedAt.hashCode))))))))))); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is _Member && - other.userId == this.userId && - other.channelCid == this.channelCid && - other.role == this.role && - other.inviteAcceptedAt == this.inviteAcceptedAt && - other.inviteRejectedAt == this.inviteRejectedAt && - other.invited == this.invited && - other.banned == this.banned && - other.shadowBanned == this.shadowBanned && - other.isModerator == this.isModerator && - other.createdAt == this.createdAt && - other.updatedAt == this.updatedAt); -} - -class _MembersCompanion extends UpdateCompanion<_Member> { - final Value userId; - final Value channelCid; - final Value role; - final Value inviteAcceptedAt; - final Value inviteRejectedAt; - final Value invited; - final Value banned; - final Value shadowBanned; - final Value isModerator; - final Value createdAt; - final Value updatedAt; - const _MembersCompanion({ - this.userId = const Value.absent(), - this.channelCid = const Value.absent(), - this.role = const Value.absent(), - this.inviteAcceptedAt = const Value.absent(), - this.inviteRejectedAt = const Value.absent(), - this.invited = const Value.absent(), - this.banned = const Value.absent(), - this.shadowBanned = const Value.absent(), - this.isModerator = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), - }); - _MembersCompanion.insert({ - @required String userId, - @required String channelCid, - this.role = const Value.absent(), - this.inviteAcceptedAt = const Value.absent(), - this.inviteRejectedAt = const Value.absent(), - this.invited = const Value.absent(), - this.banned = const Value.absent(), - this.shadowBanned = const Value.absent(), - this.isModerator = const Value.absent(), - @required DateTime createdAt, - this.updatedAt = const Value.absent(), - }) : userId = Value(userId), - channelCid = Value(channelCid), - createdAt = Value(createdAt); - static Insertable<_Member> custom({ - Expression userId, - Expression channelCid, - Expression role, - Expression inviteAcceptedAt, - Expression inviteRejectedAt, - Expression invited, - Expression banned, - Expression shadowBanned, - Expression isModerator, - Expression createdAt, - Expression updatedAt, - }) { - return RawValuesInsertable({ - if (userId != null) 'user_id': userId, - if (channelCid != null) 'channel_cid': channelCid, - if (role != null) 'role': role, - if (inviteAcceptedAt != null) 'invite_accepted_at': inviteAcceptedAt, - if (inviteRejectedAt != null) 'invite_rejected_at': inviteRejectedAt, - if (invited != null) 'invited': invited, - if (banned != null) 'banned': banned, - if (shadowBanned != null) 'shadow_banned': shadowBanned, - if (isModerator != null) 'is_moderator': isModerator, - if (createdAt != null) 'created_at': createdAt, - if (updatedAt != null) 'updated_at': updatedAt, - }); - } - - _MembersCompanion copyWith( - {Value userId, - Value channelCid, - Value role, - Value inviteAcceptedAt, - Value inviteRejectedAt, - Value invited, - Value banned, - Value shadowBanned, - Value isModerator, - Value createdAt, - Value updatedAt}) { - return _MembersCompanion( - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - role: role ?? this.role, - inviteAcceptedAt: inviteAcceptedAt ?? this.inviteAcceptedAt, - inviteRejectedAt: inviteRejectedAt ?? this.inviteRejectedAt, - invited: invited ?? this.invited, - banned: banned ?? this.banned, - shadowBanned: shadowBanned ?? this.shadowBanned, - isModerator: isModerator ?? this.isModerator, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (userId.present) { - map['user_id'] = Variable(userId.value); - } - if (channelCid.present) { - map['channel_cid'] = Variable(channelCid.value); - } - if (role.present) { - map['role'] = Variable(role.value); - } - if (inviteAcceptedAt.present) { - map['invite_accepted_at'] = Variable(inviteAcceptedAt.value); - } - if (inviteRejectedAt.present) { - map['invite_rejected_at'] = Variable(inviteRejectedAt.value); - } - if (invited.present) { - map['invited'] = Variable(invited.value); - } - if (banned.present) { - map['banned'] = Variable(banned.value); - } - if (shadowBanned.present) { - map['shadow_banned'] = Variable(shadowBanned.value); - } - if (isModerator.present) { - map['is_moderator'] = Variable(isModerator.value); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (updatedAt.present) { - map['updated_at'] = Variable(updatedAt.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_MembersCompanion(') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('role: $role, ') - ..write('inviteAcceptedAt: $inviteAcceptedAt, ') - ..write('inviteRejectedAt: $inviteRejectedAt, ') - ..write('invited: $invited, ') - ..write('banned: $banned, ') - ..write('shadowBanned: $shadowBanned, ') - ..write('isModerator: $isModerator, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt') - ..write(')')) - .toString(); - } -} - -class $_MembersTable extends _Members with TableInfo<$_MembersTable, _Member> { - final GeneratedDatabase _db; - final String _alias; - $_MembersTable(this._db, [this._alias]); - final VerificationMeta _userIdMeta = const VerificationMeta('userId'); - GeneratedTextColumn _userId; - @override - GeneratedTextColumn get userId => _userId ??= _constructUserId(); - GeneratedTextColumn _constructUserId() { - return GeneratedTextColumn( - 'user_id', - $tableName, - false, - ); - } - - final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); - GeneratedTextColumn _channelCid; - @override - GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); - GeneratedTextColumn _constructChannelCid() { - return GeneratedTextColumn( - 'channel_cid', - $tableName, - false, - ); - } - - final VerificationMeta _roleMeta = const VerificationMeta('role'); - GeneratedTextColumn _role; - @override - GeneratedTextColumn get role => _role ??= _constructRole(); - GeneratedTextColumn _constructRole() { - return GeneratedTextColumn( - 'role', - $tableName, - true, - ); - } - - final VerificationMeta _inviteAcceptedAtMeta = - const VerificationMeta('inviteAcceptedAt'); - GeneratedDateTimeColumn _inviteAcceptedAt; - @override - GeneratedDateTimeColumn get inviteAcceptedAt => - _inviteAcceptedAt ??= _constructInviteAcceptedAt(); - GeneratedDateTimeColumn _constructInviteAcceptedAt() { - return GeneratedDateTimeColumn( - 'invite_accepted_at', - $tableName, - true, - ); - } - - final VerificationMeta _inviteRejectedAtMeta = - const VerificationMeta('inviteRejectedAt'); - GeneratedDateTimeColumn _inviteRejectedAt; - @override - GeneratedDateTimeColumn get inviteRejectedAt => - _inviteRejectedAt ??= _constructInviteRejectedAt(); - GeneratedDateTimeColumn _constructInviteRejectedAt() { - return GeneratedDateTimeColumn( - 'invite_rejected_at', - $tableName, - true, - ); - } - - final VerificationMeta _invitedMeta = const VerificationMeta('invited'); - GeneratedBoolColumn _invited; - @override - GeneratedBoolColumn get invited => _invited ??= _constructInvited(); - GeneratedBoolColumn _constructInvited() { - return GeneratedBoolColumn( - 'invited', - $tableName, - true, - ); - } - - final VerificationMeta _bannedMeta = const VerificationMeta('banned'); - GeneratedBoolColumn _banned; - @override - GeneratedBoolColumn get banned => _banned ??= _constructBanned(); - GeneratedBoolColumn _constructBanned() { - return GeneratedBoolColumn( - 'banned', - $tableName, - true, - ); - } - - final VerificationMeta _shadowBannedMeta = - const VerificationMeta('shadowBanned'); - GeneratedBoolColumn _shadowBanned; - @override - GeneratedBoolColumn get shadowBanned => - _shadowBanned ??= _constructShadowBanned(); - GeneratedBoolColumn _constructShadowBanned() { - return GeneratedBoolColumn( - 'shadow_banned', - $tableName, - true, - ); - } - - final VerificationMeta _isModeratorMeta = - const VerificationMeta('isModerator'); - GeneratedBoolColumn _isModerator; - @override - GeneratedBoolColumn get isModerator => - _isModerator ??= _constructIsModerator(); - GeneratedBoolColumn _constructIsModerator() { - return GeneratedBoolColumn( - 'is_moderator', - $tableName, - true, - ); - } - - final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); - GeneratedDateTimeColumn _createdAt; - @override - GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); - GeneratedDateTimeColumn _constructCreatedAt() { - return GeneratedDateTimeColumn( - 'created_at', - $tableName, - false, - ); - } - - final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); - GeneratedDateTimeColumn _updatedAt; - @override - GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); - GeneratedDateTimeColumn _constructUpdatedAt() { - return GeneratedDateTimeColumn( - 'updated_at', - $tableName, - true, - ); - } - - @override - List get $columns => [ - userId, - channelCid, - role, - inviteAcceptedAt, - inviteRejectedAt, - invited, - banned, - shadowBanned, - isModerator, - createdAt, - updatedAt - ]; - @override - $_MembersTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'members'; - @override - final String actualTableName = 'members'; - @override - VerificationContext validateIntegrity(Insertable<_Member> instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('user_id')) { - context.handle(_userIdMeta, - userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); - } else if (isInserting) { - context.missing(_userIdMeta); - } - if (data.containsKey('channel_cid')) { - context.handle( - _channelCidMeta, - channelCid.isAcceptableOrUnknown( - data['channel_cid'], _channelCidMeta)); - } else if (isInserting) { - context.missing(_channelCidMeta); - } - if (data.containsKey('role')) { - context.handle( - _roleMeta, role.isAcceptableOrUnknown(data['role'], _roleMeta)); - } - if (data.containsKey('invite_accepted_at')) { - context.handle( - _inviteAcceptedAtMeta, - inviteAcceptedAt.isAcceptableOrUnknown( - data['invite_accepted_at'], _inviteAcceptedAtMeta)); - } - if (data.containsKey('invite_rejected_at')) { - context.handle( - _inviteRejectedAtMeta, - inviteRejectedAt.isAcceptableOrUnknown( - data['invite_rejected_at'], _inviteRejectedAtMeta)); - } - if (data.containsKey('invited')) { - context.handle(_invitedMeta, - invited.isAcceptableOrUnknown(data['invited'], _invitedMeta)); - } - if (data.containsKey('banned')) { - context.handle(_bannedMeta, - banned.isAcceptableOrUnknown(data['banned'], _bannedMeta)); - } - if (data.containsKey('shadow_banned')) { - context.handle( - _shadowBannedMeta, - shadowBanned.isAcceptableOrUnknown( - data['shadow_banned'], _shadowBannedMeta)); - } - if (data.containsKey('is_moderator')) { - context.handle( - _isModeratorMeta, - isModerator.isAcceptableOrUnknown( - data['is_moderator'], _isModeratorMeta)); - } - if (data.containsKey('created_at')) { - context.handle(_createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); - } else if (isInserting) { - context.missing(_createdAtMeta); - } - if (data.containsKey('updated_at')) { - context.handle(_updatedAtMeta, - updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); - } - return context; - } - - @override - Set get $primaryKey => {userId, channelCid}; - @override - _Member map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return _Member.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_MembersTable createAlias(String alias) { - return $_MembersTable(_db, alias); - } -} - -class ChannelQuery extends DataClass implements Insertable { - final String queryHash; - final String channelCid; - ChannelQuery({@required this.queryHash, @required this.channelCid}); - factory ChannelQuery.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final stringType = db.typeSystem.forDartType(); - return ChannelQuery( - queryHash: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}query_hash']), - channelCid: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || queryHash != null) { - map['query_hash'] = Variable(queryHash); - } - if (!nullToAbsent || channelCid != null) { - map['channel_cid'] = Variable(channelCid); - } - return map; - } - - _ChannelQueriesCompanion toCompanion(bool nullToAbsent) { - return _ChannelQueriesCompanion( - queryHash: queryHash == null && nullToAbsent - ? const Value.absent() - : Value(queryHash), - channelCid: channelCid == null && nullToAbsent - ? const Value.absent() - : Value(channelCid), - ); - } - - factory ChannelQuery.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return ChannelQuery( - queryHash: serializer.fromJson(json['queryHash']), - channelCid: serializer.fromJson(json['channelCid']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'queryHash': serializer.toJson(queryHash), - 'channelCid': serializer.toJson(channelCid), - }; - } - - ChannelQuery copyWith({String queryHash, String channelCid}) => ChannelQuery( - queryHash: queryHash ?? this.queryHash, - channelCid: channelCid ?? this.channelCid, - ); - @override - String toString() { - return (StringBuffer('ChannelQuery(') - ..write('queryHash: $queryHash, ') - ..write('channelCid: $channelCid') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc(queryHash.hashCode, channelCid.hashCode)); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is ChannelQuery && - other.queryHash == this.queryHash && - other.channelCid == this.channelCid); -} - -class _ChannelQueriesCompanion extends UpdateCompanion { - final Value queryHash; - final Value channelCid; - const _ChannelQueriesCompanion({ - this.queryHash = const Value.absent(), - this.channelCid = const Value.absent(), - }); - _ChannelQueriesCompanion.insert({ - @required String queryHash, - @required String channelCid, - }) : queryHash = Value(queryHash), - channelCid = Value(channelCid); - static Insertable custom({ - Expression queryHash, - Expression channelCid, - }) { - return RawValuesInsertable({ - if (queryHash != null) 'query_hash': queryHash, - if (channelCid != null) 'channel_cid': channelCid, - }); - } - - _ChannelQueriesCompanion copyWith( - {Value queryHash, Value channelCid}) { - return _ChannelQueriesCompanion( - queryHash: queryHash ?? this.queryHash, - channelCid: channelCid ?? this.channelCid, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (queryHash.present) { - map['query_hash'] = Variable(queryHash.value); - } - if (channelCid.present) { - map['channel_cid'] = Variable(channelCid.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_ChannelQueriesCompanion(') - ..write('queryHash: $queryHash, ') - ..write('channelCid: $channelCid') - ..write(')')) - .toString(); - } -} - -class $_ChannelQueriesTable extends _ChannelQueries - with TableInfo<$_ChannelQueriesTable, ChannelQuery> { - final GeneratedDatabase _db; - final String _alias; - $_ChannelQueriesTable(this._db, [this._alias]); - final VerificationMeta _queryHashMeta = const VerificationMeta('queryHash'); - GeneratedTextColumn _queryHash; - @override - GeneratedTextColumn get queryHash => _queryHash ??= _constructQueryHash(); - GeneratedTextColumn _constructQueryHash() { - return GeneratedTextColumn( - 'query_hash', - $tableName, - false, - ); - } - - final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); - GeneratedTextColumn _channelCid; - @override - GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); - GeneratedTextColumn _constructChannelCid() { - return GeneratedTextColumn( - 'channel_cid', - $tableName, - false, - ); - } - - @override - List get $columns => [queryHash, channelCid]; - @override - $_ChannelQueriesTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'channel_queries'; - @override - final String actualTableName = 'channel_queries'; - @override - VerificationContext validateIntegrity(Insertable instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('query_hash')) { - context.handle(_queryHashMeta, - queryHash.isAcceptableOrUnknown(data['query_hash'], _queryHashMeta)); - } else if (isInserting) { - context.missing(_queryHashMeta); - } - if (data.containsKey('channel_cid')) { - context.handle( - _channelCidMeta, - channelCid.isAcceptableOrUnknown( - data['channel_cid'], _channelCidMeta)); - } else if (isInserting) { - context.missing(_channelCidMeta); - } - return context; - } - - @override - Set get $primaryKey => {queryHash, channelCid}; - @override - ChannelQuery map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return ChannelQuery.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_ChannelQueriesTable createAlias(String alias) { - return $_ChannelQueriesTable(_db, alias); - } -} - -class _Reaction extends DataClass implements Insertable<_Reaction> { - final String messageId; - final String type; - final DateTime createdAt; - final int score; - final String userId; - final Map extraData; - _Reaction( - {@required this.messageId, - @required this.type, - @required this.createdAt, - this.score, - @required this.userId, - this.extraData}); - factory _Reaction.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final stringType = db.typeSystem.forDartType(); - final dateTimeType = db.typeSystem.forDartType(); - final intType = db.typeSystem.forDartType(); - return _Reaction( - messageId: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}message_id']), - type: stringType.mapFromDatabaseResponse(data['${effectivePrefix}type']), - createdAt: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), - score: intType.mapFromDatabaseResponse(data['${effectivePrefix}score']), - userId: - stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), - extraData: $_ReactionsTable.$converter0.mapToDart(stringType - .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (!nullToAbsent || messageId != null) { - map['message_id'] = Variable(messageId); - } - if (!nullToAbsent || type != null) { - map['type'] = Variable(type); - } - if (!nullToAbsent || createdAt != null) { - map['created_at'] = Variable(createdAt); - } - if (!nullToAbsent || score != null) { - map['score'] = Variable(score); - } - if (!nullToAbsent || userId != null) { - map['user_id'] = Variable(userId); - } - if (!nullToAbsent || extraData != null) { - final converter = $_ReactionsTable.$converter0; - map['extra_data'] = Variable(converter.mapToSql(extraData)); - } - return map; - } - - _ReactionsCompanion toCompanion(bool nullToAbsent) { - return _ReactionsCompanion( - messageId: messageId == null && nullToAbsent - ? const Value.absent() - : Value(messageId), - type: type == null && nullToAbsent ? const Value.absent() : Value(type), - createdAt: createdAt == null && nullToAbsent - ? const Value.absent() - : Value(createdAt), - score: - score == null && nullToAbsent ? const Value.absent() : Value(score), - userId: - userId == null && nullToAbsent ? const Value.absent() : Value(userId), - extraData: extraData == null && nullToAbsent - ? const Value.absent() - : Value(extraData), - ); - } - - factory _Reaction.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return _Reaction( - messageId: serializer.fromJson(json['messageId']), - type: serializer.fromJson(json['type']), - createdAt: serializer.fromJson(json['createdAt']), - score: serializer.fromJson(json['score']), - userId: serializer.fromJson(json['userId']), - extraData: serializer.fromJson>(json['extraData']), - ); - } - @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'messageId': serializer.toJson(messageId), - 'type': serializer.toJson(type), - 'createdAt': serializer.toJson(createdAt), - 'score': serializer.toJson(score), - 'userId': serializer.toJson(userId), - 'extraData': serializer.toJson>(extraData), - }; - } - - _Reaction copyWith( - {String messageId, - String type, - DateTime createdAt, - int score, - String userId, - Map extraData}) => - _Reaction( - messageId: messageId ?? this.messageId, - type: type ?? this.type, - createdAt: createdAt ?? this.createdAt, - score: score ?? this.score, - userId: userId ?? this.userId, - extraData: extraData ?? this.extraData, - ); - @override - String toString() { - return (StringBuffer('_Reaction(') - ..write('messageId: $messageId, ') - ..write('type: $type, ') - ..write('createdAt: $createdAt, ') - ..write('score: $score, ') - ..write('userId: $userId, ') - ..write('extraData: $extraData') - ..write(')')) - .toString(); - } - - @override - int get hashCode => $mrjf($mrjc( - messageId.hashCode, - $mrjc( - type.hashCode, - $mrjc( - createdAt.hashCode, - $mrjc(score.hashCode, - $mrjc(userId.hashCode, extraData.hashCode)))))); - @override - bool operator ==(dynamic other) => - identical(this, other) || - (other is _Reaction && - other.messageId == this.messageId && - other.type == this.type && - other.createdAt == this.createdAt && - other.score == this.score && - other.userId == this.userId && - other.extraData == this.extraData); -} - -class _ReactionsCompanion extends UpdateCompanion<_Reaction> { - final Value messageId; - final Value type; - final Value createdAt; - final Value score; - final Value userId; - final Value> extraData; - const _ReactionsCompanion({ - this.messageId = const Value.absent(), - this.type = const Value.absent(), - this.createdAt = const Value.absent(), - this.score = const Value.absent(), - this.userId = const Value.absent(), - this.extraData = const Value.absent(), - }); - _ReactionsCompanion.insert({ - @required String messageId, - @required String type, - @required DateTime createdAt, - this.score = const Value.absent(), - @required String userId, - this.extraData = const Value.absent(), - }) : messageId = Value(messageId), - type = Value(type), - createdAt = Value(createdAt), - userId = Value(userId); - static Insertable<_Reaction> custom({ - Expression messageId, - Expression type, - Expression createdAt, - Expression score, - Expression userId, - Expression extraData, - }) { - return RawValuesInsertable({ - if (messageId != null) 'message_id': messageId, - if (type != null) 'type': type, - if (createdAt != null) 'created_at': createdAt, - if (score != null) 'score': score, - if (userId != null) 'user_id': userId, - if (extraData != null) 'extra_data': extraData, - }); - } - - _ReactionsCompanion copyWith( - {Value messageId, - Value type, - Value createdAt, - Value score, - Value userId, - Value> extraData}) { - return _ReactionsCompanion( - messageId: messageId ?? this.messageId, - type: type ?? this.type, - createdAt: createdAt ?? this.createdAt, - score: score ?? this.score, - userId: userId ?? this.userId, - extraData: extraData ?? this.extraData, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (messageId.present) { - map['message_id'] = Variable(messageId.value); - } - if (type.present) { - map['type'] = Variable(type.value); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (score.present) { - map['score'] = Variable(score.value); - } - if (userId.present) { - map['user_id'] = Variable(userId.value); - } - if (extraData.present) { - final converter = $_ReactionsTable.$converter0; - map['extra_data'] = Variable(converter.mapToSql(extraData.value)); - } - return map; - } - - @override - String toString() { - return (StringBuffer('_ReactionsCompanion(') - ..write('messageId: $messageId, ') - ..write('type: $type, ') - ..write('createdAt: $createdAt, ') - ..write('score: $score, ') - ..write('userId: $userId, ') - ..write('extraData: $extraData') - ..write(')')) - .toString(); - } -} - -class $_ReactionsTable extends _Reactions - with TableInfo<$_ReactionsTable, _Reaction> { - final GeneratedDatabase _db; - final String _alias; - $_ReactionsTable(this._db, [this._alias]); - final VerificationMeta _messageIdMeta = const VerificationMeta('messageId'); - GeneratedTextColumn _messageId; - @override - GeneratedTextColumn get messageId => _messageId ??= _constructMessageId(); - GeneratedTextColumn _constructMessageId() { - return GeneratedTextColumn( - 'message_id', - $tableName, - false, - ); - } - - final VerificationMeta _typeMeta = const VerificationMeta('type'); - GeneratedTextColumn _type; - @override - GeneratedTextColumn get type => _type ??= _constructType(); - GeneratedTextColumn _constructType() { - return GeneratedTextColumn( - 'type', - $tableName, - false, - ); - } - - final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); - GeneratedDateTimeColumn _createdAt; - @override - GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); - GeneratedDateTimeColumn _constructCreatedAt() { - return GeneratedDateTimeColumn( - 'created_at', - $tableName, - false, - ); - } - - final VerificationMeta _scoreMeta = const VerificationMeta('score'); - GeneratedIntColumn _score; - @override - GeneratedIntColumn get score => _score ??= _constructScore(); - GeneratedIntColumn _constructScore() { - return GeneratedIntColumn( - 'score', - $tableName, - true, - ); - } - - final VerificationMeta _userIdMeta = const VerificationMeta('userId'); - GeneratedTextColumn _userId; - @override - GeneratedTextColumn get userId => _userId ??= _constructUserId(); - GeneratedTextColumn _constructUserId() { - return GeneratedTextColumn( - 'user_id', - $tableName, - false, - ); - } - - final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); - GeneratedTextColumn _extraData; - @override - GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); - GeneratedTextColumn _constructExtraData() { - return GeneratedTextColumn( - 'extra_data', - $tableName, - true, - ); - } - - @override - List get $columns => - [messageId, type, createdAt, score, userId, extraData]; - @override - $_ReactionsTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'reactions'; - @override - final String actualTableName = 'reactions'; - @override - VerificationContext validateIntegrity(Insertable<_Reaction> instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('message_id')) { - context.handle(_messageIdMeta, - messageId.isAcceptableOrUnknown(data['message_id'], _messageIdMeta)); - } else if (isInserting) { - context.missing(_messageIdMeta); - } - if (data.containsKey('type')) { - context.handle( - _typeMeta, type.isAcceptableOrUnknown(data['type'], _typeMeta)); - } else if (isInserting) { - context.missing(_typeMeta); - } - if (data.containsKey('created_at')) { - context.handle(_createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); - } else if (isInserting) { - context.missing(_createdAtMeta); - } - if (data.containsKey('score')) { - context.handle( - _scoreMeta, score.isAcceptableOrUnknown(data['score'], _scoreMeta)); - } - if (data.containsKey('user_id')) { - context.handle(_userIdMeta, - userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); - } else if (isInserting) { - context.missing(_userIdMeta); - } - context.handle(_extraDataMeta, const VerificationResult.success()); - return context; - } - - @override - Set get $primaryKey => {messageId, type, userId}; - @override - _Reaction map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return _Reaction.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $_ReactionsTable createAlias(String alias) { - return $_ReactionsTable(_db, alias); - } - - static TypeConverter, String> $converter0 = - _ExtraDataConverter(); -} - -abstract class _$OfflineStorage extends GeneratedDatabase { - _$OfflineStorage(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e); - _$OfflineStorage.connect(DatabaseConnection c) : super.connect(c); - $_ConnectionEventTable _connectionEvent; - $_ConnectionEventTable get connectionEvent => - _connectionEvent ??= $_ConnectionEventTable(this); - $_ChannelsTable _channels; - $_ChannelsTable get channels => _channels ??= $_ChannelsTable(this); - $_UsersTable _users; - $_UsersTable get users => _users ??= $_UsersTable(this); - $_MessagesTable _messages; - $_MessagesTable get messages => _messages ??= $_MessagesTable(this); - $_ReadsTable _reads; - $_ReadsTable get reads => _reads ??= $_ReadsTable(this); - $_MembersTable _members; - $_MembersTable get members => _members ??= $_MembersTable(this); - $_ChannelQueriesTable _channelQueries; - $_ChannelQueriesTable get channelQueries => - _channelQueries ??= $_ChannelQueriesTable(this); - $_ReactionsTable _reactions; - $_ReactionsTable get reactions => _reactions ??= $_ReactionsTable(this); - @override - Iterable get allTables => allSchemaEntities.whereType(); - @override - List get allSchemaEntities => [ - connectionEvent, - channels, - users, - messages, - reads, - members, - channelQueries, - reactions - ]; -} diff --git a/packages/dart_client/lib/src/db/shared/native_db.dart b/packages/dart_client/lib/src/db/shared/native_db.dart deleted file mode 100644 index deee5b08..00000000 --- a/packages/dart_client/lib/src/db/shared/native_db.dart +++ /dev/null @@ -1,65 +0,0 @@ -//ignore_for_file: public_member_api_docs -import 'dart:io'; -import 'dart:isolate'; -import 'package:flutter/material.dart'; -import 'package:moor/ffi.dart'; -import 'package:moor/isolate.dart'; -import 'package:moor/moor.dart'; -import 'package:path/path.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:stream_chat/src/db/offline_storage.dart'; - -class SharedDB { - static Future constructDatabase(dbName) async { - final dir = await getApplicationDocumentsDirectory(); - final path = join(dir.path, dbName); - final file = File(path); - return VmDatabase(file); - } - - static Future createMoorIsolate(String userId) async { - WidgetsFlutterBinding.ensureInitialized(); - final dir = await getApplicationDocumentsDirectory(); - final path = join(dir.path, 'db_$userId.sqlite'); - - final receivePort = ReceivePort(); - await Isolate.spawn( - startBackground, - _IsolateStartRequest(receivePort.sendPort, path), - ); - - return (await receivePort.first as MoorIsolate); - } - - static void startBackground(_IsolateStartRequest request) { - final executor = LazyDatabase(() async { - return VmDatabase(File(request.targetPath)); - }); - final moorIsolate = MoorIsolate.inCurrent( - () => DatabaseConnection.fromExecutor(executor), - ); - request.sendMoorIsolate.send(moorIsolate); - } - - static Future constructOfflineStorage({ - userId, - logger, - }) async { - logger.info('Connecting on background isolate'); - final isolate = await createMoorIsolate(userId); - final connection = await isolate.connect(); - return OfflineStorage.connect( - connection, - userId, - isolate, - logger, - ); - } -} - -class _IsolateStartRequest { - final SendPort sendMoorIsolate; - final String targetPath; - - _IsolateStartRequest(this.sendMoorIsolate, this.targetPath); -} diff --git a/packages/dart_client/lib/src/db/shared/shared_db.dart b/packages/dart_client/lib/src/db/shared/shared_db.dart deleted file mode 100644 index 25120fcf..00000000 --- a/packages/dart_client/lib/src/db/shared/shared_db.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'unsupported_db.dart' - if (dart.library.io) 'native_db.dart' // implementation using dart:io - if (dart.library.html) 'web_db.dart'; diff --git a/packages/dart_client/lib/src/db/shared/unsupported_db.dart b/packages/dart_client/lib/src/db/shared/unsupported_db.dart deleted file mode 100644 index bbb4ccb7..00000000 --- a/packages/dart_client/lib/src/db/shared/unsupported_db.dart +++ /dev/null @@ -1,14 +0,0 @@ -//ignore_for_file: public_member_api_docs -//ignore_for_file: always_declare_return_types -class SharedDB { - static constructDatabase(dbName) async { - print('Unsupported Platform'); - return null; - } - - static createMoorIsolate(userId) {} - - static startBackground(request) {} - - static constructOfflineStorage({userId, logger}) {} -} diff --git a/packages/dart_client/lib/src/db/shared/web_db.dart b/packages/dart_client/lib/src/db/shared/web_db.dart deleted file mode 100644 index f79c224a..00000000 --- a/packages/dart_client/lib/src/db/shared/web_db.dart +++ /dev/null @@ -1,20 +0,0 @@ -//ignore_for_file: public_member_api_docs -//ignore_for_file: always_declare_return_types -import 'package:moor/moor_web.dart'; -import 'package:stream_chat/src/db/offline_storage.dart'; - -class SharedDB { - static constructDatabase(dbName) async { - return WebDatabase(dbName); - } - - static Future constructOfflineStorage({ - userId, - logger, - }) async { - return OfflineStorage( - userId, - logger, - ); - } -} diff --git a/packages/dart_client/lib/src/db/stream_chat_database.dart b/packages/dart_client/lib/src/db/stream_chat_database.dart deleted file mode 100644 index 87ab828e..00000000 --- a/packages/dart_client/lib/src/db/stream_chat_database.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:stream_chat/src/api/requests.dart'; -import 'package:stream_chat/src/models/channel_model.dart'; -import 'package:stream_chat/src/models/channel_state.dart'; -import 'package:stream_chat/src/models/event.dart'; -import 'package:stream_chat/src/models/member.dart'; -import 'package:stream_chat/src/models/message.dart'; -import 'package:stream_chat/src/models/reaction.dart'; -import 'package:stream_chat/src/models/read.dart'; -import 'package:stream_chat/src/models/user.dart'; - -/// -abstract class StreamChatDatabase { - /// Creates a new connection to the database - Future connect({ - bool connectBackground = false, - bool logStatements = false, - }); - - /// Closes the database instance - /// If [flush] is true, the database data will be deleted - Future disconnect({bool flush = false}); - - /// Get stored replies by messageId - Future> getReplies( - String parentId, { - String lessThan, - }); - - /// Get stored connection event - Future getConnectionInfo(); - - /// Get stored lastSyncAt - Future getLastSyncAt(); - - /// Update stored connection event - Future updateConnectionInfo(Event event); - - /// Update stored lastSyncAt - Future updateLastSyncAt(DateTime lastSyncAt); - - /// Get the channel cids saved in the offline storage - Future> getChannelCids(); - - Future getChannelByCid(String cid); - - Future> getMembersByCid(String cid); - - Future> getReadsByCid(String cid); - - Future> getMessagesByCid( - String cid, { - int limit = 20, - String messageLessThan, - String messageGreaterThan, - }); - - /// Get list of channels by filter, sort and paginationParams - Future> getChannelStates({ - Map filter, - List sort = const [], - PaginationParams paginationParams, - }); - - /// Update list of channel queries - /// If [clearQueryCache] is true before the insert - /// the list of matching rows will be deleted - Future updateChannelQueries( - Map filter, - List cids, - bool clearQueryCache, - ); - - /// Remove a message by message id - Future deleteMessageByIds(List messageIds); - - /// Remove a message by message id - Future deleteMessageByCids(List cids); - - /// Remove a channel by cid - Future deleteChannelByCids(List cids); - - /// Update messages data from a list - Future updateMessages(String cid, List messages); - - /// Get the info about channel threads - Future>> getChannelThreads(String cid); - - Future updateChannels(List channels); - - Future updateMembers(String cid, List members); - - Future updateReads(String cid, List reads); - - Future updateUsers(List users); - - Future updateReactions(List reactions); -} diff --git a/packages/dart_client/lib/src/db/stream_chat_persistence.dart b/packages/dart_client/lib/src/db/stream_chat_persistence.dart new file mode 100644 index 00000000..40004825 --- /dev/null +++ b/packages/dart_client/lib/src/db/stream_chat_persistence.dart @@ -0,0 +1,196 @@ +import 'package:stream_chat/src/api/requests.dart'; +import 'package:stream_chat/src/models/channel_model.dart'; +import 'package:stream_chat/src/models/channel_state.dart'; +import 'package:stream_chat/src/models/event.dart'; +import 'package:stream_chat/src/models/member.dart'; +import 'package:stream_chat/src/models/message.dart'; +import 'package:stream_chat/src/models/reaction.dart'; +import 'package:stream_chat/src/models/read.dart'; +import 'package:stream_chat/src/models/user.dart'; + +/// +abstract class StreamChatPersistence { + /// Creates a new connection to the database + Future connect({ + bool connectBackground = false, + bool logStatements = false, + }); + + /// Closes the database instance + /// If [flush] is true, the database data will be deleted + Future disconnect({bool flush = false}); + + /// Get stored replies by messageId + Future> getReplies( + String parentId, { + String lessThan, + }); + + /// Get stored connection event + Future getConnectionInfo(); + + /// Get stored lastSyncAt + Future getLastSyncAt(); + + /// Update stored connection event + Future updateConnectionInfo(Event event); + + /// Update stored lastSyncAt + Future updateLastSyncAt(DateTime lastSyncAt); + + /// Get the channel cids saved in the offline storage + Future> getChannelCids(); + + /// + Future getChannelByCid(String cid); + + /// + Future> getMembersByCid(String cid); + + /// + Future> getReadsByCid(String cid); + + /// + Future> getMessagesByCid( + String cid, { + PaginationParams messagePagination, + }); + + /// Get channel data by cid + Future getChannelStateByCid( + String cid, { + PaginationParams messagePagination, + }) async { + final members = await getMembersByCid(cid); + final reads = await getReadsByCid(cid); + final channel = await getChannelByCid(cid); + final messages = await getMessagesByCid( + cid, + messagePagination: messagePagination, + ); + return ChannelState( + members: members, + read: reads, + messages: messages, + channel: channel, + ); + } + + /// Get list of channels by filter, sort and paginationParams + Future> getChannelStates({ + Map filter, + List sort = const [], + PaginationParams paginationParams, + }); + + /// Update list of channel queries + /// If [clearQueryCache] is true before the insert + /// the list of matching rows will be deleted + Future updateChannelQueries( + Map filter, + List cids, + bool clearQueryCache, + ); + + /// Remove a message by message id + Future deleteMessageById(String messageId) { + return deleteMessageByIds([messageId]); + } + + /// Remove a message by message ids + Future deleteMessageByIds(List messageIds); + + /// Remove a message by channel cid + Future deleteMessageByCid(String cid) { + return deleteMessageByCids([cid]); + } + + /// Remove a message by message cids + Future deleteMessageByCids(List cids); + + /// Remove a channel by cid + Future deleteChannels(List cids); + + /// Update messages data from a list + Future updateMessages(String cid, List messages); + + /// Get the info about channel threads + Future>> getChannelThreads(String cid); + + /// + Future updateChannels(List channels); + + /// + Future updateMembers(String cid, List members); + + /// + Future updateReads(String cid, List reads); + + /// + Future updateUsers(List users); + + /// + Future updateReactions(List reactions); + + /// + Future updateChannelState(ChannelState channelState) { + return updateChannelStates([channelState]); + } + + /// Update list of channel states + Future updateChannelStates(List channelStates) async { + final channels = channelStates.map((it) { + return it.channel; + }).where((it) => it != null); + + final reactions = channelStates.expand((it) => it.messages).expand((it) { + return [ + ...it.ownReactions.where((r) => r.userId != null), + ...it.latestReactions.where((r) => r.userId != null) + ]; + }).where((it) => it != null); + + final users = channelStates + .map((cs) => [ + cs.channel?.createdBy, + ...cs.messages?.map((m) { + return [ + m.user, + ...m.latestReactions?.map((r) => r.user), + ...m.ownReactions?.map((r) => r.user), + ]; + })?.expand((v) => v), + ...cs.read?.map((r) => r.user), + ...cs.members?.map((m) => m.user), + ]) + .expand((it) => it) + .where((it) => it != null); + + final updateMessagesFuture = channelStates.map((it) { + final cid = it.channel.cid; + final messages = it.messages.where((it) => it != null); + return updateMessages(cid, messages.toList(growable: false)); + }).toList(growable: false); + + final updateReadsFuture = channelStates.map((it) { + final cid = it.channel.cid; + final reads = it.read.where((it) => it != null); + return updateReads(cid, reads.toList(growable: false)); + }).toList(growable: false); + + final updateMembersFuture = channelStates.map((it) { + final cid = it.channel.cid; + final members = it.members.where((it) => it != null); + return updateMembers(cid, members.toList(growable: false)); + }).toList(growable: false); + + await Future.wait([ + ...updateMessagesFuture, + ...updateReadsFuture, + ...updateMembersFuture, + updateChannels(channels.toList(growable: false)), + updateReactions(reactions.toList(growable: false)), + updateUsers(users.toList(growable: false)), + ]); + } +} diff --git a/packages/dart_client/lib/src/notifications.dart b/packages/dart_client/lib/src/notifications.dart index 2fc500cf..e4cef9b5 100644 --- a/packages/dart_client/lib/src/notifications.dart +++ b/packages/dart_client/lib/src/notifications.dart @@ -3,10 +3,10 @@ import 'dart:convert'; import 'package:logging/logging.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stream_chat/src/api/responses.dart'; -import 'package:stream_chat/src/db/offline_storage.dart'; import 'package:stream_chat/src/models/channel_model.dart'; import 'package:stream_chat/src/models/channel_state.dart'; import 'package:stream_chat/src/models/message.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'client.dart'; import 'models/own_user.dart'; @@ -23,14 +23,18 @@ class NotificationService { final sharedPreferences = await _getSharedPreferences(); final userId = sharedPreferences.getString(KEY_USER_ID); - final offlineStorage = OfflineStorage(userId, Logger('💽')); - await offlineStorage.updateChannelState( + final chatPersistence = StreamChatPersistenceImpl( + userId, + logger: Logger('💽'), + ); + await chatPersistence.connect(); + await chatPersistence.updateChannelState( ChannelState( channel: channelModel, messages: [message], ), ); - await offlineStorage.disconnect(); + await chatPersistence.disconnect(); } else { final channel = client.state.channels[channelModel.cid]; channel.state.updateChannelState( @@ -44,6 +48,7 @@ class NotificationService { } static SharedPreferences _sharedPreferences; + static Future _getSharedPreferences() async { _sharedPreferences ??= await SharedPreferences.getInstance(); return _sharedPreferences; @@ -74,17 +79,18 @@ class NotificationService { final sharedPreferences = await _getSharedPreferences(); final userId = sharedPreferences.getString(KEY_USER_ID); - final offlineStorage = OfflineStorage( + final chatPersistence = StreamChatPersistenceImpl( userId, - Logger('💽'), + logger: Logger('💽'), ); + await chatPersistence.connect(); - await offlineStorage.updateChannelState(ChannelState( + await chatPersistence.updateChannelState(ChannelState( messages: [messageResponse.message], channel: messageResponse.channel, )); - await offlineStorage.disconnect(); + await chatPersistence.disconnect(); } /// Gets the message using the client and stores it in the offline storage diff --git a/packages/dart_client/lib/stream_chat.dart b/packages/dart_client/lib/stream_chat.dart index 8bac944f..f9a366c3 100644 --- a/packages/dart_client/lib/stream_chat.dart +++ b/packages/dart_client/lib/stream_chat.dart @@ -27,5 +27,5 @@ export './src/models/reaction.dart'; export './src/models/read.dart'; export './src/models/user.dart'; export './src/notifications.dart'; -export './src/db/stream_chat_database.dart'; -export './src/utils/result.dart'; +export './src/db/stream_chat_persistence.dart'; +export './src/utils/result.dart' hide Success, Error; diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index d4734e44..0032453a 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -19,12 +19,8 @@ dependencies: uuid: ^2.2.2 async: ^2.4.1 stream_channel: ^2.0.0 - moor: ^3.3.1 - path_provider: ^1.6.10 - path: ^1.6.4 rxdart: ^0.24.1 collection: ^1.14.12 - sqlite3_flutter_libs: ^0.3.0 pedantic: ^1.9.2 freezed: ^0.12.7 stream_chat_persistence: @@ -33,7 +29,6 @@ dependencies: dev_dependencies: build_runner: ^1.10.0 json_serializable: ^3.3.0 - moor_generator: ^3.1.0 flutter_test: sdk: flutter mockito: ^4.1.1 diff --git a/packages/flutter_widgets/pubspec.yaml b/packages/flutter_widgets/pubspec.yaml index 2b82aca2..5d7ff855 100644 --- a/packages/flutter_widgets/pubspec.yaml +++ b/packages/flutter_widgets/pubspec.yaml @@ -29,7 +29,8 @@ dependencies: image_picker: ^0.6.7+17 flutter_keyboard_visibility: ^4.0.2 mime: ^0.9.7 - stream_chat: ^0.2.24 + stream_chat: + path: ../dart_client video_compress: ^2.1.1 visibility_detector: ^0.1.5 http_parser: ^3.1.4 From ad979529d2c9d07219233d103644cdf9fe835683 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 26 Jan 2021 16:12:14 +0530 Subject: [PATCH 06/46] remove unwanted dependencies Signed-off-by: Sahil Kumar --- packages/dart_client/build.yaml | 3 -- .../dart_client/lib/src/utils/result.dart | 45 ------------------- packages/dart_client/lib/stream_chat.dart | 3 +- packages/dart_client/pubspec.yaml | 2 - packages/stream_chat_persistence/pubspec.yaml | 1 - 5 files changed, 1 insertion(+), 53 deletions(-) delete mode 100644 packages/dart_client/lib/src/utils/result.dart diff --git a/packages/dart_client/build.yaml b/packages/dart_client/build.yaml index ea58f519..ddbd70dd 100644 --- a/packages/dart_client/build.yaml +++ b/packages/dart_client/build.yaml @@ -1,9 +1,6 @@ targets: $default: builders: - moor_generator: - options: - generate_connect_constructor: true json_serializable: options: explicit_to_json: true diff --git a/packages/dart_client/lib/src/utils/result.dart b/packages/dart_client/lib/src/utils/result.dart deleted file mode 100644 index a2961ec4..00000000 --- a/packages/dart_client/lib/src/utils/result.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; - -import '../exceptions.dart'; - -part 'result.freezed.dart'; - -/// -@freezed -abstract class Result with _$Result { - /// - const factory Result.success({@required T data}) = Success; - - /// - const factory Result.error({@required ApiError error}) = Error; -} - -/// -extension ResultX on Result { - /// - bool get isSuccess => this is Success; - - /// - bool get isError => this is Error; - - /// - T get data { - if (isError) { - throw Exception( - 'Result is not successful. Check result.isSuccess before reading the data.', - ); - } - return (this as Success).data; - } - - /// - ApiError get error { - if (isSuccess) { - throw Exception( - 'Result is successful, not an error. Check result.isError before reading the error.', - ); - } - return (this as Error).error; - } -} diff --git a/packages/dart_client/lib/stream_chat.dart b/packages/dart_client/lib/stream_chat.dart index f9a366c3..0ff1f871 100644 --- a/packages/dart_client/lib/stream_chat.dart +++ b/packages/dart_client/lib/stream_chat.dart @@ -27,5 +27,4 @@ export './src/models/reaction.dart'; export './src/models/read.dart'; export './src/models/user.dart'; export './src/notifications.dart'; -export './src/db/stream_chat_persistence.dart'; -export './src/utils/result.dart' hide Success, Error; +export './src/db/stream_chat_persistence.dart'; \ No newline at end of file diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index 1c4afa80..5eca907a 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -18,11 +18,9 @@ dependencies: web_socket_channel: ^1.1.0 uuid: ^2.2.2 async: ^2.4.1 - stream_channel: ^2.0.0 rxdart: ^0.24.1 collection: ^1.14.12 pedantic: ^1.9.2 - freezed: ^0.12.7 stream_chat_persistence: path: ../stream_chat_persistence diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index a0c97c89..1ce6e604 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -11,7 +11,6 @@ dependencies: moor: ^3.4.0 path: ^1.7.0 path_provider: ^1.6.27 - sqlite3_flutter_libs: ^0.3.0 stream_chat: path: ../dart_client From 959aeab567bdde08f8d565782ed1777cf0f22d3a Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 26 Jan 2021 16:49:05 +0530 Subject: [PATCH 07/46] [StreamChatPersistence] Minor changes Signed-off-by: Sahil Kumar --- packages/stream_chat_persistence/build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/stream_chat_persistence/build.yaml b/packages/stream_chat_persistence/build.yaml index b07425b6..373486d0 100644 --- a/packages/stream_chat_persistence/build.yaml +++ b/packages/stream_chat_persistence/build.yaml @@ -4,3 +4,6 @@ targets: moor_generator: options: generate_connect_constructor: true + data_class_to_companions: false + apply_converters_on_variables: true + generate_values_in_copy_with: true From a869e458f440264deba19fc7d4b8210625a3af63 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 26 Jan 2021 16:52:08 +0530 Subject: [PATCH 08/46] [StreamChatPersistence] Add generated files Signed-off-by: Sahil Kumar --- .../lib/src/dao/channel_dao.g.dart | 12 + .../lib/src/dao/channel_query_dao.g.dart | 13 + .../lib/src/dao/connection_event_dao.g.dart | 13 + .../lib/src/dao/member_dao.g.dart | 12 + .../lib/src/dao/message_dao.g.dart | 12 + .../lib/src/dao/reaction_dao.g.dart | 12 + .../lib/src/dao/read_dao.g.dart | 12 + .../lib/src/dao/user_dao.g.dart | 11 + .../lib/src/db/moor_chat_database.g.dart | 4030 +++++++++++++++++ 9 files changed, 4127 insertions(+) create mode 100644 packages/stream_chat_persistence/lib/src/dao/channel_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/channel_query_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/connection_event_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/member_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/message_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/reaction_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/read_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/user_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/db/moor_chat_database.g.dart diff --git a/packages/stream_chat_persistence/lib/src/dao/channel_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/channel_dao.g.dart new file mode 100644 index 00000000..a3ac1713 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/channel_dao.g.dart @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'channel_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$ChannelDaoMixin on DatabaseAccessor { + $ChannelsTable get channels => attachedDatabase.channels; + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.g.dart new file mode 100644 index 00000000..5879d8bb --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.g.dart @@ -0,0 +1,13 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'channel_query_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$ChannelQueryDaoMixin on DatabaseAccessor { + $ChannelQueriesTable get channelQueries => attachedDatabase.channelQueries; + $ChannelsTable get channels => attachedDatabase.channels; + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.g.dart new file mode 100644 index 00000000..a8245982 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.g.dart @@ -0,0 +1,13 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'connection_event_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$ConnectionEventDaoMixin on DatabaseAccessor { + $ConnectionEventsTable get connectionEvents => + attachedDatabase.connectionEvents; + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/dao/member_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/member_dao.g.dart new file mode 100644 index 00000000..dbda1351 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/member_dao.g.dart @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'member_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$MemberDaoMixin on DatabaseAccessor { + $MembersTable get members => attachedDatabase.members; + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.g.dart new file mode 100644 index 00000000..e27a5d42 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.g.dart @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'message_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$MessageDaoMixin on DatabaseAccessor { + $MessagesTable get messages => attachedDatabase.messages; + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.g.dart new file mode 100644 index 00000000..b95e2126 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.g.dart @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'reaction_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$ReactionDaoMixin on DatabaseAccessor { + $ReactionsTable get reactions => attachedDatabase.reactions; + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/dao/read_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/read_dao.g.dart new file mode 100644 index 00000000..b9ac9228 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/read_dao.g.dart @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'read_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$ReadDaoMixin on DatabaseAccessor { + $ReadsTable get reads => attachedDatabase.reads; + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/dao/user_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/user_dao.g.dart new file mode 100644 index 00000000..edd9a33b --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/user_dao.g.dart @@ -0,0 +1,11 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_dao.dart'; + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$UserDaoMixin on DatabaseAccessor { + $UsersTable get users => attachedDatabase.users; +} diff --git a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.g.dart b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.g.dart new file mode 100644 index 00000000..0ff6e9f5 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.g.dart @@ -0,0 +1,4030 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'moor_chat_database.dart'; + +// ************************************************************************** +// MoorGenerator +// ************************************************************************** + +// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this +class ChannelEntity extends DataClass implements Insertable { + final String id; + final String type; + final String cid; + final Map config; + final bool frozen; + final DateTime lastMessageAt; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime deletedAt; + final int memberCount; + final String createdById; + final Map extraData; + ChannelEntity( + {@required this.id, + @required this.type, + @required this.cid, + @required this.config, + @required this.frozen, + this.lastMessageAt, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.memberCount, + this.createdById, + this.extraData}); + factory ChannelEntity.fromData( + Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final stringType = db.typeSystem.forDartType(); + final boolType = db.typeSystem.forDartType(); + final dateTimeType = db.typeSystem.forDartType(); + final intType = db.typeSystem.forDartType(); + return ChannelEntity( + id: stringType.mapFromDatabaseResponse(data['${effectivePrefix}id']), + type: stringType.mapFromDatabaseResponse(data['${effectivePrefix}type']), + cid: stringType.mapFromDatabaseResponse(data['${effectivePrefix}cid']), + config: $ChannelsTable.$converter0.mapToDart( + stringType.mapFromDatabaseResponse(data['${effectivePrefix}config'])), + frozen: + boolType.mapFromDatabaseResponse(data['${effectivePrefix}frozen']), + lastMessageAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}last_message_at']), + createdAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), + updatedAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), + deletedAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}deleted_at']), + memberCount: intType + .mapFromDatabaseResponse(data['${effectivePrefix}member_count']), + createdById: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}created_by_id']), + extraData: $ChannelsTable.$converter1.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || type != null) { + map['type'] = Variable(type); + } + if (!nullToAbsent || cid != null) { + map['cid'] = Variable(cid); + } + if (!nullToAbsent || config != null) { + final converter = $ChannelsTable.$converter0; + map['config'] = Variable(converter.mapToSql(config)); + } + if (!nullToAbsent || frozen != null) { + map['frozen'] = Variable(frozen); + } + if (!nullToAbsent || lastMessageAt != null) { + map['last_message_at'] = Variable(lastMessageAt); + } + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || memberCount != null) { + map['member_count'] = Variable(memberCount); + } + if (!nullToAbsent || createdById != null) { + map['created_by_id'] = Variable(createdById); + } + if (!nullToAbsent || extraData != null) { + final converter = $ChannelsTable.$converter1; + map['extra_data'] = Variable(converter.mapToSql(extraData)); + } + return map; + } + + factory ChannelEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return ChannelEntity( + id: serializer.fromJson(json['id']), + type: serializer.fromJson(json['type']), + cid: serializer.fromJson(json['cid']), + config: serializer.fromJson>(json['config']), + frozen: serializer.fromJson(json['frozen']), + lastMessageAt: serializer.fromJson(json['lastMessageAt']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + memberCount: serializer.fromJson(json['memberCount']), + createdById: serializer.fromJson(json['createdById']), + extraData: serializer.fromJson>(json['extraData']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'type': serializer.toJson(type), + 'cid': serializer.toJson(cid), + 'config': serializer.toJson>(config), + 'frozen': serializer.toJson(frozen), + 'lastMessageAt': serializer.toJson(lastMessageAt), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'memberCount': serializer.toJson(memberCount), + 'createdById': serializer.toJson(createdById), + 'extraData': serializer.toJson>(extraData), + }; + } + + ChannelEntity copyWith( + {String id, + String type, + String cid, + Map config, + bool frozen, + Value lastMessageAt = const Value.absent(), + Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), + Value deletedAt = const Value.absent(), + Value memberCount = const Value.absent(), + Value createdById = const Value.absent(), + Value> extraData = const Value.absent()}) => + ChannelEntity( + id: id ?? this.id, + type: type ?? this.type, + cid: cid ?? this.cid, + config: config ?? this.config, + frozen: frozen ?? this.frozen, + lastMessageAt: + lastMessageAt.present ? lastMessageAt.value : this.lastMessageAt, + createdAt: createdAt.present ? createdAt.value : this.createdAt, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + memberCount: memberCount.present ? memberCount.value : this.memberCount, + createdById: createdById.present ? createdById.value : this.createdById, + extraData: extraData.present ? extraData.value : this.extraData, + ); + @override + String toString() { + return (StringBuffer('ChannelEntity(') + ..write('id: $id, ') + ..write('type: $type, ') + ..write('cid: $cid, ') + ..write('config: $config, ') + ..write('frozen: $frozen, ') + ..write('lastMessageAt: $lastMessageAt, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('memberCount: $memberCount, ') + ..write('createdById: $createdById, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + id.hashCode, + $mrjc( + type.hashCode, + $mrjc( + cid.hashCode, + $mrjc( + config.hashCode, + $mrjc( + frozen.hashCode, + $mrjc( + lastMessageAt.hashCode, + $mrjc( + createdAt.hashCode, + $mrjc( + updatedAt.hashCode, + $mrjc( + deletedAt.hashCode, + $mrjc( + memberCount.hashCode, + $mrjc(createdById.hashCode, + extraData.hashCode)))))))))))); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is ChannelEntity && + other.id == this.id && + other.type == this.type && + other.cid == this.cid && + other.config == this.config && + other.frozen == this.frozen && + other.lastMessageAt == this.lastMessageAt && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.memberCount == this.memberCount && + other.createdById == this.createdById && + other.extraData == this.extraData); +} + +class ChannelsCompanion extends UpdateCompanion { + final Value id; + final Value type; + final Value cid; + final Value> config; + final Value frozen; + final Value lastMessageAt; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value memberCount; + final Value createdById; + final Value> extraData; + const ChannelsCompanion({ + this.id = const Value.absent(), + this.type = const Value.absent(), + this.cid = const Value.absent(), + this.config = const Value.absent(), + this.frozen = const Value.absent(), + this.lastMessageAt = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.memberCount = const Value.absent(), + this.createdById = const Value.absent(), + this.extraData = const Value.absent(), + }); + ChannelsCompanion.insert({ + @required String id, + @required String type, + @required String cid, + @required Map config, + this.frozen = const Value.absent(), + this.lastMessageAt = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.memberCount = const Value.absent(), + this.createdById = const Value.absent(), + this.extraData = const Value.absent(), + }) : id = Value(id), + type = Value(type), + cid = Value(cid), + config = Value(config); + static Insertable custom({ + Expression id, + Expression type, + Expression cid, + Expression config, + Expression frozen, + Expression lastMessageAt, + Expression createdAt, + Expression updatedAt, + Expression deletedAt, + Expression memberCount, + Expression createdById, + Expression extraData, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (type != null) 'type': type, + if (cid != null) 'cid': cid, + if (config != null) 'config': config, + if (frozen != null) 'frozen': frozen, + if (lastMessageAt != null) 'last_message_at': lastMessageAt, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (memberCount != null) 'member_count': memberCount, + if (createdById != null) 'created_by_id': createdById, + if (extraData != null) 'extra_data': extraData, + }); + } + + ChannelsCompanion copyWith( + {Value id, + Value type, + Value cid, + Value> config, + Value frozen, + Value lastMessageAt, + Value createdAt, + Value updatedAt, + Value deletedAt, + Value memberCount, + Value createdById, + Value> extraData}) { + return ChannelsCompanion( + id: id ?? this.id, + type: type ?? this.type, + cid: cid ?? this.cid, + config: config ?? this.config, + frozen: frozen ?? this.frozen, + lastMessageAt: lastMessageAt ?? this.lastMessageAt, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + memberCount: memberCount ?? this.memberCount, + createdById: createdById ?? this.createdById, + extraData: extraData ?? this.extraData, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (cid.present) { + map['cid'] = Variable(cid.value); + } + if (config.present) { + final converter = $ChannelsTable.$converter0; + map['config'] = Variable(converter.mapToSql(config.value)); + } + if (frozen.present) { + map['frozen'] = Variable(frozen.value); + } + if (lastMessageAt.present) { + map['last_message_at'] = Variable(lastMessageAt.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (memberCount.present) { + map['member_count'] = Variable(memberCount.value); + } + if (createdById.present) { + map['created_by_id'] = Variable(createdById.value); + } + if (extraData.present) { + final converter = $ChannelsTable.$converter1; + map['extra_data'] = Variable(converter.mapToSql(extraData.value)); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ChannelsCompanion(') + ..write('id: $id, ') + ..write('type: $type, ') + ..write('cid: $cid, ') + ..write('config: $config, ') + ..write('frozen: $frozen, ') + ..write('lastMessageAt: $lastMessageAt, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('memberCount: $memberCount, ') + ..write('createdById: $createdById, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } +} + +class $ChannelsTable extends Channels + with TableInfo<$ChannelsTable, ChannelEntity> { + final GeneratedDatabase _db; + final String _alias; + $ChannelsTable(this._db, [this._alias]); + final VerificationMeta _idMeta = const VerificationMeta('id'); + GeneratedTextColumn _id; + @override + GeneratedTextColumn get id => _id ??= _constructId(); + GeneratedTextColumn _constructId() { + return GeneratedTextColumn( + 'id', + $tableName, + false, + ); + } + + final VerificationMeta _typeMeta = const VerificationMeta('type'); + GeneratedTextColumn _type; + @override + GeneratedTextColumn get type => _type ??= _constructType(); + GeneratedTextColumn _constructType() { + return GeneratedTextColumn( + 'type', + $tableName, + false, + ); + } + + final VerificationMeta _cidMeta = const VerificationMeta('cid'); + GeneratedTextColumn _cid; + @override + GeneratedTextColumn get cid => _cid ??= _constructCid(); + GeneratedTextColumn _constructCid() { + return GeneratedTextColumn( + 'cid', + $tableName, + false, + ); + } + + final VerificationMeta _configMeta = const VerificationMeta('config'); + GeneratedTextColumn _config; + @override + GeneratedTextColumn get config => _config ??= _constructConfig(); + GeneratedTextColumn _constructConfig() { + return GeneratedTextColumn( + 'config', + $tableName, + false, + ); + } + + final VerificationMeta _frozenMeta = const VerificationMeta('frozen'); + GeneratedBoolColumn _frozen; + @override + GeneratedBoolColumn get frozen => _frozen ??= _constructFrozen(); + GeneratedBoolColumn _constructFrozen() { + return GeneratedBoolColumn('frozen', $tableName, false, + defaultValue: Constant(false)); + } + + final VerificationMeta _lastMessageAtMeta = + const VerificationMeta('lastMessageAt'); + GeneratedDateTimeColumn _lastMessageAt; + @override + GeneratedDateTimeColumn get lastMessageAt => + _lastMessageAt ??= _constructLastMessageAt(); + GeneratedDateTimeColumn _constructLastMessageAt() { + return GeneratedDateTimeColumn( + 'last_message_at', + $tableName, + true, + ); + } + + final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); + GeneratedDateTimeColumn _createdAt; + @override + GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); + GeneratedDateTimeColumn _constructCreatedAt() { + return GeneratedDateTimeColumn( + 'created_at', + $tableName, + true, + ); + } + + final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); + GeneratedDateTimeColumn _updatedAt; + @override + GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); + GeneratedDateTimeColumn _constructUpdatedAt() { + return GeneratedDateTimeColumn( + 'updated_at', + $tableName, + true, + ); + } + + final VerificationMeta _deletedAtMeta = const VerificationMeta('deletedAt'); + GeneratedDateTimeColumn _deletedAt; + @override + GeneratedDateTimeColumn get deletedAt => _deletedAt ??= _constructDeletedAt(); + GeneratedDateTimeColumn _constructDeletedAt() { + return GeneratedDateTimeColumn( + 'deleted_at', + $tableName, + true, + ); + } + + final VerificationMeta _memberCountMeta = + const VerificationMeta('memberCount'); + GeneratedIntColumn _memberCount; + @override + GeneratedIntColumn get memberCount => + _memberCount ??= _constructMemberCount(); + GeneratedIntColumn _constructMemberCount() { + return GeneratedIntColumn( + 'member_count', + $tableName, + true, + ); + } + + final VerificationMeta _createdByIdMeta = + const VerificationMeta('createdById'); + GeneratedTextColumn _createdById; + @override + GeneratedTextColumn get createdById => + _createdById ??= _constructCreatedById(); + GeneratedTextColumn _constructCreatedById() { + return GeneratedTextColumn( + 'created_by_id', + $tableName, + true, + ); + } + + final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); + GeneratedTextColumn _extraData; + @override + GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); + GeneratedTextColumn _constructExtraData() { + return GeneratedTextColumn( + 'extra_data', + $tableName, + true, + ); + } + + @override + List get $columns => [ + id, + type, + cid, + config, + frozen, + lastMessageAt, + createdAt, + updatedAt, + deletedAt, + memberCount, + createdById, + extraData + ]; + @override + $ChannelsTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'channels'; + @override + final String actualTableName = 'channels'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('type')) { + context.handle( + _typeMeta, type.isAcceptableOrUnknown(data['type'], _typeMeta)); + } else if (isInserting) { + context.missing(_typeMeta); + } + if (data.containsKey('cid')) { + context.handle( + _cidMeta, cid.isAcceptableOrUnknown(data['cid'], _cidMeta)); + } else if (isInserting) { + context.missing(_cidMeta); + } + context.handle(_configMeta, const VerificationResult.success()); + if (data.containsKey('frozen')) { + context.handle(_frozenMeta, + frozen.isAcceptableOrUnknown(data['frozen'], _frozenMeta)); + } + if (data.containsKey('last_message_at')) { + context.handle( + _lastMessageAtMeta, + lastMessageAt.isAcceptableOrUnknown( + data['last_message_at'], _lastMessageAtMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); + } + if (data.containsKey('deleted_at')) { + context.handle(_deletedAtMeta, + deletedAt.isAcceptableOrUnknown(data['deleted_at'], _deletedAtMeta)); + } + if (data.containsKey('member_count')) { + context.handle( + _memberCountMeta, + memberCount.isAcceptableOrUnknown( + data['member_count'], _memberCountMeta)); + } + if (data.containsKey('created_by_id')) { + context.handle( + _createdByIdMeta, + createdById.isAcceptableOrUnknown( + data['created_by_id'], _createdByIdMeta)); + } + context.handle(_extraDataMeta, const VerificationResult.success()); + return context; + } + + @override + Set get $primaryKey => {cid}; + @override + ChannelEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return ChannelEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $ChannelsTable createAlias(String alias) { + return $ChannelsTable(_db, alias); + } + + static TypeConverter, String> $converter0 = + MapConverter(); + static TypeConverter, String> $converter1 = + MapConverter(); +} + +class MessageEntity extends DataClass implements Insertable { + final String id; + final String messageText; + final List attachments; + final MessageSendingStatus status; + final String type; + final List mentionedUsers; + final Map reactionCounts; + final Map reactionScores; + final String parentId; + final String quotedMessageId; + final int replyCount; + final bool showInChannel; + final bool shadowed; + final String command; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime deletedAt; + final String userId; + final String channelCid; + final Map extraData; + MessageEntity( + {@required this.id, + this.messageText, + this.attachments, + this.status, + this.type, + this.mentionedUsers, + this.reactionCounts, + this.reactionScores, + this.parentId, + this.quotedMessageId, + this.replyCount, + this.showInChannel, + this.shadowed, + this.command, + @required this.createdAt, + this.updatedAt, + this.deletedAt, + this.userId, + this.channelCid, + this.extraData}); + factory MessageEntity.fromData( + Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final stringType = db.typeSystem.forDartType(); + final intType = db.typeSystem.forDartType(); + final boolType = db.typeSystem.forDartType(); + final dateTimeType = db.typeSystem.forDartType(); + return MessageEntity( + id: stringType.mapFromDatabaseResponse(data['${effectivePrefix}id']), + messageText: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}message_text']), + attachments: $MessagesTable.$converter0.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}attachments'])), + status: $MessagesTable.$converter1.mapToDart( + intType.mapFromDatabaseResponse(data['${effectivePrefix}status'])), + type: stringType.mapFromDatabaseResponse(data['${effectivePrefix}type']), + mentionedUsers: $MessagesTable.$converter2.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}mentioned_users'])), + reactionCounts: $MessagesTable.$converter3.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}reaction_counts'])), + reactionScores: $MessagesTable.$converter4.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}reaction_scores'])), + parentId: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}parent_id']), + quotedMessageId: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}quoted_message_id']), + replyCount: intType + .mapFromDatabaseResponse(data['${effectivePrefix}reply_count']), + showInChannel: boolType + .mapFromDatabaseResponse(data['${effectivePrefix}show_in_channel']), + shadowed: + boolType.mapFromDatabaseResponse(data['${effectivePrefix}shadowed']), + command: + stringType.mapFromDatabaseResponse(data['${effectivePrefix}command']), + createdAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), + updatedAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), + deletedAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}deleted_at']), + userId: + stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), + channelCid: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), + extraData: $MessagesTable.$converter5.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || messageText != null) { + map['message_text'] = Variable(messageText); + } + if (!nullToAbsent || attachments != null) { + final converter = $MessagesTable.$converter0; + map['attachments'] = Variable(converter.mapToSql(attachments)); + } + if (!nullToAbsent || status != null) { + final converter = $MessagesTable.$converter1; + map['status'] = Variable(converter.mapToSql(status)); + } + if (!nullToAbsent || type != null) { + map['type'] = Variable(type); + } + if (!nullToAbsent || mentionedUsers != null) { + final converter = $MessagesTable.$converter2; + map['mentioned_users'] = + Variable(converter.mapToSql(mentionedUsers)); + } + if (!nullToAbsent || reactionCounts != null) { + final converter = $MessagesTable.$converter3; + map['reaction_counts'] = + Variable(converter.mapToSql(reactionCounts)); + } + if (!nullToAbsent || reactionScores != null) { + final converter = $MessagesTable.$converter4; + map['reaction_scores'] = + Variable(converter.mapToSql(reactionScores)); + } + if (!nullToAbsent || parentId != null) { + map['parent_id'] = Variable(parentId); + } + if (!nullToAbsent || quotedMessageId != null) { + map['quoted_message_id'] = Variable(quotedMessageId); + } + if (!nullToAbsent || replyCount != null) { + map['reply_count'] = Variable(replyCount); + } + if (!nullToAbsent || showInChannel != null) { + map['show_in_channel'] = Variable(showInChannel); + } + if (!nullToAbsent || shadowed != null) { + map['shadowed'] = Variable(shadowed); + } + if (!nullToAbsent || command != null) { + map['command'] = Variable(command); + } + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + if (!nullToAbsent || channelCid != null) { + map['channel_cid'] = Variable(channelCid); + } + if (!nullToAbsent || extraData != null) { + final converter = $MessagesTable.$converter5; + map['extra_data'] = Variable(converter.mapToSql(extraData)); + } + return map; + } + + factory MessageEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return MessageEntity( + id: serializer.fromJson(json['id']), + messageText: serializer.fromJson(json['messageText']), + attachments: serializer.fromJson>(json['attachments']), + status: serializer.fromJson(json['status']), + type: serializer.fromJson(json['type']), + mentionedUsers: serializer.fromJson>(json['mentionedUsers']), + reactionCounts: + serializer.fromJson>(json['reactionCounts']), + reactionScores: + serializer.fromJson>(json['reactionScores']), + parentId: serializer.fromJson(json['parentId']), + quotedMessageId: serializer.fromJson(json['quotedMessageId']), + replyCount: serializer.fromJson(json['replyCount']), + showInChannel: serializer.fromJson(json['showInChannel']), + shadowed: serializer.fromJson(json['shadowed']), + command: serializer.fromJson(json['command']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + userId: serializer.fromJson(json['userId']), + channelCid: serializer.fromJson(json['channelCid']), + extraData: serializer.fromJson>(json['extraData']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'messageText': serializer.toJson(messageText), + 'attachments': serializer.toJson>(attachments), + 'status': serializer.toJson(status), + 'type': serializer.toJson(type), + 'mentionedUsers': serializer.toJson>(mentionedUsers), + 'reactionCounts': serializer.toJson>(reactionCounts), + 'reactionScores': serializer.toJson>(reactionScores), + 'parentId': serializer.toJson(parentId), + 'quotedMessageId': serializer.toJson(quotedMessageId), + 'replyCount': serializer.toJson(replyCount), + 'showInChannel': serializer.toJson(showInChannel), + 'shadowed': serializer.toJson(shadowed), + 'command': serializer.toJson(command), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'userId': serializer.toJson(userId), + 'channelCid': serializer.toJson(channelCid), + 'extraData': serializer.toJson>(extraData), + }; + } + + MessageEntity copyWith( + {String id, + Value messageText = const Value.absent(), + Value> attachments = const Value.absent(), + Value status = const Value.absent(), + Value type = const Value.absent(), + Value> mentionedUsers = const Value.absent(), + Value> reactionCounts = const Value.absent(), + Value> reactionScores = const Value.absent(), + Value parentId = const Value.absent(), + Value quotedMessageId = const Value.absent(), + Value replyCount = const Value.absent(), + Value showInChannel = const Value.absent(), + Value shadowed = const Value.absent(), + Value command = const Value.absent(), + DateTime createdAt, + Value updatedAt = const Value.absent(), + Value deletedAt = const Value.absent(), + Value userId = const Value.absent(), + Value channelCid = const Value.absent(), + Value> extraData = const Value.absent()}) => + MessageEntity( + id: id ?? this.id, + messageText: messageText.present ? messageText.value : this.messageText, + attachments: attachments.present ? attachments.value : this.attachments, + status: status.present ? status.value : this.status, + type: type.present ? type.value : this.type, + mentionedUsers: + mentionedUsers.present ? mentionedUsers.value : this.mentionedUsers, + reactionCounts: + reactionCounts.present ? reactionCounts.value : this.reactionCounts, + reactionScores: + reactionScores.present ? reactionScores.value : this.reactionScores, + parentId: parentId.present ? parentId.value : this.parentId, + quotedMessageId: quotedMessageId.present + ? quotedMessageId.value + : this.quotedMessageId, + replyCount: replyCount.present ? replyCount.value : this.replyCount, + showInChannel: + showInChannel.present ? showInChannel.value : this.showInChannel, + shadowed: shadowed.present ? shadowed.value : this.shadowed, + command: command.present ? command.value : this.command, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + userId: userId.present ? userId.value : this.userId, + channelCid: channelCid.present ? channelCid.value : this.channelCid, + extraData: extraData.present ? extraData.value : this.extraData, + ); + @override + String toString() { + return (StringBuffer('MessageEntity(') + ..write('id: $id, ') + ..write('messageText: $messageText, ') + ..write('attachments: $attachments, ') + ..write('status: $status, ') + ..write('type: $type, ') + ..write('mentionedUsers: $mentionedUsers, ') + ..write('reactionCounts: $reactionCounts, ') + ..write('reactionScores: $reactionScores, ') + ..write('parentId: $parentId, ') + ..write('quotedMessageId: $quotedMessageId, ') + ..write('replyCount: $replyCount, ') + ..write('showInChannel: $showInChannel, ') + ..write('shadowed: $shadowed, ') + ..write('command: $command, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('userId: $userId, ') + ..write('channelCid: $channelCid, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + id.hashCode, + $mrjc( + messageText.hashCode, + $mrjc( + attachments.hashCode, + $mrjc( + status.hashCode, + $mrjc( + type.hashCode, + $mrjc( + mentionedUsers.hashCode, + $mrjc( + reactionCounts.hashCode, + $mrjc( + reactionScores.hashCode, + $mrjc( + parentId.hashCode, + $mrjc( + quotedMessageId.hashCode, + $mrjc( + replyCount.hashCode, + $mrjc( + showInChannel.hashCode, + $mrjc( + shadowed.hashCode, + $mrjc( + command.hashCode, + $mrjc( + createdAt + .hashCode, + $mrjc( + updatedAt + .hashCode, + $mrjc( + deletedAt + .hashCode, + $mrjc( + userId + .hashCode, + $mrjc( + channelCid.hashCode, + extraData.hashCode)))))))))))))))))))); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is MessageEntity && + other.id == this.id && + other.messageText == this.messageText && + other.attachments == this.attachments && + other.status == this.status && + other.type == this.type && + other.mentionedUsers == this.mentionedUsers && + other.reactionCounts == this.reactionCounts && + other.reactionScores == this.reactionScores && + other.parentId == this.parentId && + other.quotedMessageId == this.quotedMessageId && + other.replyCount == this.replyCount && + other.showInChannel == this.showInChannel && + other.shadowed == this.shadowed && + other.command == this.command && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.userId == this.userId && + other.channelCid == this.channelCid && + other.extraData == this.extraData); +} + +class MessagesCompanion extends UpdateCompanion { + final Value id; + final Value messageText; + final Value> attachments; + final Value status; + final Value type; + final Value> mentionedUsers; + final Value> reactionCounts; + final Value> reactionScores; + final Value parentId; + final Value quotedMessageId; + final Value replyCount; + final Value showInChannel; + final Value shadowed; + final Value command; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value userId; + final Value channelCid; + final Value> extraData; + const MessagesCompanion({ + this.id = const Value.absent(), + this.messageText = const Value.absent(), + this.attachments = const Value.absent(), + this.status = const Value.absent(), + this.type = const Value.absent(), + this.mentionedUsers = const Value.absent(), + this.reactionCounts = const Value.absent(), + this.reactionScores = const Value.absent(), + this.parentId = const Value.absent(), + this.quotedMessageId = const Value.absent(), + this.replyCount = const Value.absent(), + this.showInChannel = const Value.absent(), + this.shadowed = const Value.absent(), + this.command = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.userId = const Value.absent(), + this.channelCid = const Value.absent(), + this.extraData = const Value.absent(), + }); + MessagesCompanion.insert({ + @required String id, + this.messageText = const Value.absent(), + this.attachments = const Value.absent(), + this.status = const Value.absent(), + this.type = const Value.absent(), + this.mentionedUsers = const Value.absent(), + this.reactionCounts = const Value.absent(), + this.reactionScores = const Value.absent(), + this.parentId = const Value.absent(), + this.quotedMessageId = const Value.absent(), + this.replyCount = const Value.absent(), + this.showInChannel = const Value.absent(), + this.shadowed = const Value.absent(), + this.command = const Value.absent(), + @required DateTime createdAt, + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.userId = const Value.absent(), + this.channelCid = const Value.absent(), + this.extraData = const Value.absent(), + }) : id = Value(id), + createdAt = Value(createdAt); + static Insertable custom({ + Expression id, + Expression messageText, + Expression attachments, + Expression status, + Expression type, + Expression mentionedUsers, + Expression reactionCounts, + Expression reactionScores, + Expression parentId, + Expression quotedMessageId, + Expression replyCount, + Expression showInChannel, + Expression shadowed, + Expression command, + Expression createdAt, + Expression updatedAt, + Expression deletedAt, + Expression userId, + Expression channelCid, + Expression extraData, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (messageText != null) 'message_text': messageText, + if (attachments != null) 'attachments': attachments, + if (status != null) 'status': status, + if (type != null) 'type': type, + if (mentionedUsers != null) 'mentioned_users': mentionedUsers, + if (reactionCounts != null) 'reaction_counts': reactionCounts, + if (reactionScores != null) 'reaction_scores': reactionScores, + if (parentId != null) 'parent_id': parentId, + if (quotedMessageId != null) 'quoted_message_id': quotedMessageId, + if (replyCount != null) 'reply_count': replyCount, + if (showInChannel != null) 'show_in_channel': showInChannel, + if (shadowed != null) 'shadowed': shadowed, + if (command != null) 'command': command, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (userId != null) 'user_id': userId, + if (channelCid != null) 'channel_cid': channelCid, + if (extraData != null) 'extra_data': extraData, + }); + } + + MessagesCompanion copyWith( + {Value id, + Value messageText, + Value> attachments, + Value status, + Value type, + Value> mentionedUsers, + Value> reactionCounts, + Value> reactionScores, + Value parentId, + Value quotedMessageId, + Value replyCount, + Value showInChannel, + Value shadowed, + Value command, + Value createdAt, + Value updatedAt, + Value deletedAt, + Value userId, + Value channelCid, + Value> extraData}) { + return MessagesCompanion( + id: id ?? this.id, + messageText: messageText ?? this.messageText, + attachments: attachments ?? this.attachments, + status: status ?? this.status, + type: type ?? this.type, + mentionedUsers: mentionedUsers ?? this.mentionedUsers, + reactionCounts: reactionCounts ?? this.reactionCounts, + reactionScores: reactionScores ?? this.reactionScores, + parentId: parentId ?? this.parentId, + quotedMessageId: quotedMessageId ?? this.quotedMessageId, + replyCount: replyCount ?? this.replyCount, + showInChannel: showInChannel ?? this.showInChannel, + shadowed: shadowed ?? this.shadowed, + command: command ?? this.command, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + userId: userId ?? this.userId, + channelCid: channelCid ?? this.channelCid, + extraData: extraData ?? this.extraData, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (messageText.present) { + map['message_text'] = Variable(messageText.value); + } + if (attachments.present) { + final converter = $MessagesTable.$converter0; + map['attachments'] = + Variable(converter.mapToSql(attachments.value)); + } + if (status.present) { + final converter = $MessagesTable.$converter1; + map['status'] = Variable(converter.mapToSql(status.value)); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (mentionedUsers.present) { + final converter = $MessagesTable.$converter2; + map['mentioned_users'] = + Variable(converter.mapToSql(mentionedUsers.value)); + } + if (reactionCounts.present) { + final converter = $MessagesTable.$converter3; + map['reaction_counts'] = + Variable(converter.mapToSql(reactionCounts.value)); + } + if (reactionScores.present) { + final converter = $MessagesTable.$converter4; + map['reaction_scores'] = + Variable(converter.mapToSql(reactionScores.value)); + } + if (parentId.present) { + map['parent_id'] = Variable(parentId.value); + } + if (quotedMessageId.present) { + map['quoted_message_id'] = Variable(quotedMessageId.value); + } + if (replyCount.present) { + map['reply_count'] = Variable(replyCount.value); + } + if (showInChannel.present) { + map['show_in_channel'] = Variable(showInChannel.value); + } + if (shadowed.present) { + map['shadowed'] = Variable(shadowed.value); + } + if (command.present) { + map['command'] = Variable(command.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (channelCid.present) { + map['channel_cid'] = Variable(channelCid.value); + } + if (extraData.present) { + final converter = $MessagesTable.$converter5; + map['extra_data'] = Variable(converter.mapToSql(extraData.value)); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MessagesCompanion(') + ..write('id: $id, ') + ..write('messageText: $messageText, ') + ..write('attachments: $attachments, ') + ..write('status: $status, ') + ..write('type: $type, ') + ..write('mentionedUsers: $mentionedUsers, ') + ..write('reactionCounts: $reactionCounts, ') + ..write('reactionScores: $reactionScores, ') + ..write('parentId: $parentId, ') + ..write('quotedMessageId: $quotedMessageId, ') + ..write('replyCount: $replyCount, ') + ..write('showInChannel: $showInChannel, ') + ..write('shadowed: $shadowed, ') + ..write('command: $command, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('userId: $userId, ') + ..write('channelCid: $channelCid, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } +} + +class $MessagesTable extends Messages + with TableInfo<$MessagesTable, MessageEntity> { + final GeneratedDatabase _db; + final String _alias; + $MessagesTable(this._db, [this._alias]); + final VerificationMeta _idMeta = const VerificationMeta('id'); + GeneratedTextColumn _id; + @override + GeneratedTextColumn get id => _id ??= _constructId(); + GeneratedTextColumn _constructId() { + return GeneratedTextColumn( + 'id', + $tableName, + false, + ); + } + + final VerificationMeta _messageTextMeta = + const VerificationMeta('messageText'); + GeneratedTextColumn _messageText; + @override + GeneratedTextColumn get messageText => + _messageText ??= _constructMessageText(); + GeneratedTextColumn _constructMessageText() { + return GeneratedTextColumn( + 'message_text', + $tableName, + true, + ); + } + + final VerificationMeta _attachmentsMeta = + const VerificationMeta('attachments'); + GeneratedTextColumn _attachments; + @override + GeneratedTextColumn get attachments => + _attachments ??= _constructAttachments(); + GeneratedTextColumn _constructAttachments() { + return GeneratedTextColumn( + 'attachments', + $tableName, + true, + ); + } + + final VerificationMeta _statusMeta = const VerificationMeta('status'); + GeneratedIntColumn _status; + @override + GeneratedIntColumn get status => _status ??= _constructStatus(); + GeneratedIntColumn _constructStatus() { + return GeneratedIntColumn( + 'status', + $tableName, + true, + ); + } + + final VerificationMeta _typeMeta = const VerificationMeta('type'); + GeneratedTextColumn _type; + @override + GeneratedTextColumn get type => _type ??= _constructType(); + GeneratedTextColumn _constructType() { + return GeneratedTextColumn( + 'type', + $tableName, + true, + ); + } + + final VerificationMeta _mentionedUsersMeta = + const VerificationMeta('mentionedUsers'); + GeneratedTextColumn _mentionedUsers; + @override + GeneratedTextColumn get mentionedUsers => + _mentionedUsers ??= _constructMentionedUsers(); + GeneratedTextColumn _constructMentionedUsers() { + return GeneratedTextColumn( + 'mentioned_users', + $tableName, + true, + ); + } + + final VerificationMeta _reactionCountsMeta = + const VerificationMeta('reactionCounts'); + GeneratedTextColumn _reactionCounts; + @override + GeneratedTextColumn get reactionCounts => + _reactionCounts ??= _constructReactionCounts(); + GeneratedTextColumn _constructReactionCounts() { + return GeneratedTextColumn( + 'reaction_counts', + $tableName, + true, + ); + } + + final VerificationMeta _reactionScoresMeta = + const VerificationMeta('reactionScores'); + GeneratedTextColumn _reactionScores; + @override + GeneratedTextColumn get reactionScores => + _reactionScores ??= _constructReactionScores(); + GeneratedTextColumn _constructReactionScores() { + return GeneratedTextColumn( + 'reaction_scores', + $tableName, + true, + ); + } + + final VerificationMeta _parentIdMeta = const VerificationMeta('parentId'); + GeneratedTextColumn _parentId; + @override + GeneratedTextColumn get parentId => _parentId ??= _constructParentId(); + GeneratedTextColumn _constructParentId() { + return GeneratedTextColumn( + 'parent_id', + $tableName, + true, + ); + } + + final VerificationMeta _quotedMessageIdMeta = + const VerificationMeta('quotedMessageId'); + GeneratedTextColumn _quotedMessageId; + @override + GeneratedTextColumn get quotedMessageId => + _quotedMessageId ??= _constructQuotedMessageId(); + GeneratedTextColumn _constructQuotedMessageId() { + return GeneratedTextColumn( + 'quoted_message_id', + $tableName, + true, + ); + } + + final VerificationMeta _replyCountMeta = const VerificationMeta('replyCount'); + GeneratedIntColumn _replyCount; + @override + GeneratedIntColumn get replyCount => _replyCount ??= _constructReplyCount(); + GeneratedIntColumn _constructReplyCount() { + return GeneratedIntColumn( + 'reply_count', + $tableName, + true, + ); + } + + final VerificationMeta _showInChannelMeta = + const VerificationMeta('showInChannel'); + GeneratedBoolColumn _showInChannel; + @override + GeneratedBoolColumn get showInChannel => + _showInChannel ??= _constructShowInChannel(); + GeneratedBoolColumn _constructShowInChannel() { + return GeneratedBoolColumn( + 'show_in_channel', + $tableName, + true, + ); + } + + final VerificationMeta _shadowedMeta = const VerificationMeta('shadowed'); + GeneratedBoolColumn _shadowed; + @override + GeneratedBoolColumn get shadowed => _shadowed ??= _constructShadowed(); + GeneratedBoolColumn _constructShadowed() { + return GeneratedBoolColumn( + 'shadowed', + $tableName, + true, + ); + } + + final VerificationMeta _commandMeta = const VerificationMeta('command'); + GeneratedTextColumn _command; + @override + GeneratedTextColumn get command => _command ??= _constructCommand(); + GeneratedTextColumn _constructCommand() { + return GeneratedTextColumn( + 'command', + $tableName, + true, + ); + } + + final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); + GeneratedDateTimeColumn _createdAt; + @override + GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); + GeneratedDateTimeColumn _constructCreatedAt() { + return GeneratedDateTimeColumn( + 'created_at', + $tableName, + false, + ); + } + + final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); + GeneratedDateTimeColumn _updatedAt; + @override + GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); + GeneratedDateTimeColumn _constructUpdatedAt() { + return GeneratedDateTimeColumn( + 'updated_at', + $tableName, + true, + ); + } + + final VerificationMeta _deletedAtMeta = const VerificationMeta('deletedAt'); + GeneratedDateTimeColumn _deletedAt; + @override + GeneratedDateTimeColumn get deletedAt => _deletedAt ??= _constructDeletedAt(); + GeneratedDateTimeColumn _constructDeletedAt() { + return GeneratedDateTimeColumn( + 'deleted_at', + $tableName, + true, + ); + } + + final VerificationMeta _userIdMeta = const VerificationMeta('userId'); + GeneratedTextColumn _userId; + @override + GeneratedTextColumn get userId => _userId ??= _constructUserId(); + GeneratedTextColumn _constructUserId() { + return GeneratedTextColumn( + 'user_id', + $tableName, + true, + ); + } + + final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); + GeneratedTextColumn _channelCid; + @override + GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); + GeneratedTextColumn _constructChannelCid() { + return GeneratedTextColumn('channel_cid', $tableName, true, + $customConstraints: + 'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE'); + } + + final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); + GeneratedTextColumn _extraData; + @override + GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); + GeneratedTextColumn _constructExtraData() { + return GeneratedTextColumn( + 'extra_data', + $tableName, + true, + ); + } + + @override + List get $columns => [ + id, + messageText, + attachments, + status, + type, + mentionedUsers, + reactionCounts, + reactionScores, + parentId, + quotedMessageId, + replyCount, + showInChannel, + shadowed, + command, + createdAt, + updatedAt, + deletedAt, + userId, + channelCid, + extraData + ]; + @override + $MessagesTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'messages'; + @override + final String actualTableName = 'messages'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('message_text')) { + context.handle( + _messageTextMeta, + messageText.isAcceptableOrUnknown( + data['message_text'], _messageTextMeta)); + } + context.handle(_attachmentsMeta, const VerificationResult.success()); + context.handle(_statusMeta, const VerificationResult.success()); + if (data.containsKey('type')) { + context.handle( + _typeMeta, type.isAcceptableOrUnknown(data['type'], _typeMeta)); + } + context.handle(_mentionedUsersMeta, const VerificationResult.success()); + context.handle(_reactionCountsMeta, const VerificationResult.success()); + context.handle(_reactionScoresMeta, const VerificationResult.success()); + if (data.containsKey('parent_id')) { + context.handle(_parentIdMeta, + parentId.isAcceptableOrUnknown(data['parent_id'], _parentIdMeta)); + } + if (data.containsKey('quoted_message_id')) { + context.handle( + _quotedMessageIdMeta, + quotedMessageId.isAcceptableOrUnknown( + data['quoted_message_id'], _quotedMessageIdMeta)); + } + if (data.containsKey('reply_count')) { + context.handle( + _replyCountMeta, + replyCount.isAcceptableOrUnknown( + data['reply_count'], _replyCountMeta)); + } + if (data.containsKey('show_in_channel')) { + context.handle( + _showInChannelMeta, + showInChannel.isAcceptableOrUnknown( + data['show_in_channel'], _showInChannelMeta)); + } + if (data.containsKey('shadowed')) { + context.handle(_shadowedMeta, + shadowed.isAcceptableOrUnknown(data['shadowed'], _shadowedMeta)); + } + if (data.containsKey('command')) { + context.handle(_commandMeta, + command.isAcceptableOrUnknown(data['command'], _commandMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); + } + if (data.containsKey('deleted_at')) { + context.handle(_deletedAtMeta, + deletedAt.isAcceptableOrUnknown(data['deleted_at'], _deletedAtMeta)); + } + if (data.containsKey('user_id')) { + context.handle(_userIdMeta, + userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); + } + if (data.containsKey('channel_cid')) { + context.handle( + _channelCidMeta, + channelCid.isAcceptableOrUnknown( + data['channel_cid'], _channelCidMeta)); + } + context.handle(_extraDataMeta, const VerificationResult.success()); + return context; + } + + @override + Set get $primaryKey => {id}; + @override + MessageEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return MessageEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $MessagesTable createAlias(String alias) { + return $MessagesTable(_db, alias); + } + + static TypeConverter, String> $converter0 = + ListConverter(); + static TypeConverter $converter1 = + MessageSendingStatusConverter(); + static TypeConverter, String> $converter2 = + ListConverter(); + static TypeConverter, String> $converter3 = + MapConverter(); + static TypeConverter, String> $converter4 = + MapConverter(); + static TypeConverter, String> $converter5 = + MapConverter(); +} + +class ReactionEntity extends DataClass implements Insertable { + final String userId; + final String messageId; + final String type; + final DateTime createdAt; + final int score; + final Map extraData; + ReactionEntity( + {@required this.userId, + @required this.messageId, + @required this.type, + @required this.createdAt, + this.score, + this.extraData}); + factory ReactionEntity.fromData( + Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final stringType = db.typeSystem.forDartType(); + final dateTimeType = db.typeSystem.forDartType(); + final intType = db.typeSystem.forDartType(); + return ReactionEntity( + userId: + stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), + messageId: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}message_id']), + type: stringType.mapFromDatabaseResponse(data['${effectivePrefix}type']), + createdAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), + score: intType.mapFromDatabaseResponse(data['${effectivePrefix}score']), + extraData: $ReactionsTable.$converter0.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + if (!nullToAbsent || messageId != null) { + map['message_id'] = Variable(messageId); + } + if (!nullToAbsent || type != null) { + map['type'] = Variable(type); + } + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); + } + if (!nullToAbsent || score != null) { + map['score'] = Variable(score); + } + if (!nullToAbsent || extraData != null) { + final converter = $ReactionsTable.$converter0; + map['extra_data'] = Variable(converter.mapToSql(extraData)); + } + return map; + } + + factory ReactionEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return ReactionEntity( + userId: serializer.fromJson(json['userId']), + messageId: serializer.fromJson(json['messageId']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + score: serializer.fromJson(json['score']), + extraData: serializer.fromJson>(json['extraData']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'userId': serializer.toJson(userId), + 'messageId': serializer.toJson(messageId), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'score': serializer.toJson(score), + 'extraData': serializer.toJson>(extraData), + }; + } + + ReactionEntity copyWith( + {String userId, + String messageId, + String type, + DateTime createdAt, + Value score = const Value.absent(), + Value> extraData = const Value.absent()}) => + ReactionEntity( + userId: userId ?? this.userId, + messageId: messageId ?? this.messageId, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + score: score.present ? score.value : this.score, + extraData: extraData.present ? extraData.value : this.extraData, + ); + @override + String toString() { + return (StringBuffer('ReactionEntity(') + ..write('userId: $userId, ') + ..write('messageId: $messageId, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('score: $score, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + userId.hashCode, + $mrjc( + messageId.hashCode, + $mrjc( + type.hashCode, + $mrjc(createdAt.hashCode, + $mrjc(score.hashCode, extraData.hashCode)))))); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is ReactionEntity && + other.userId == this.userId && + other.messageId == this.messageId && + other.type == this.type && + other.createdAt == this.createdAt && + other.score == this.score && + other.extraData == this.extraData); +} + +class ReactionsCompanion extends UpdateCompanion { + final Value userId; + final Value messageId; + final Value type; + final Value createdAt; + final Value score; + final Value> extraData; + const ReactionsCompanion({ + this.userId = const Value.absent(), + this.messageId = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.score = const Value.absent(), + this.extraData = const Value.absent(), + }); + ReactionsCompanion.insert({ + @required String userId, + @required String messageId, + @required String type, + @required DateTime createdAt, + this.score = const Value.absent(), + this.extraData = const Value.absent(), + }) : userId = Value(userId), + messageId = Value(messageId), + type = Value(type), + createdAt = Value(createdAt); + static Insertable custom({ + Expression userId, + Expression messageId, + Expression type, + Expression createdAt, + Expression score, + Expression extraData, + }) { + return RawValuesInsertable({ + if (userId != null) 'user_id': userId, + if (messageId != null) 'message_id': messageId, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (score != null) 'score': score, + if (extraData != null) 'extra_data': extraData, + }); + } + + ReactionsCompanion copyWith( + {Value userId, + Value messageId, + Value type, + Value createdAt, + Value score, + Value> extraData}) { + return ReactionsCompanion( + userId: userId ?? this.userId, + messageId: messageId ?? this.messageId, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + score: score ?? this.score, + extraData: extraData ?? this.extraData, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (messageId.present) { + map['message_id'] = Variable(messageId.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (score.present) { + map['score'] = Variable(score.value); + } + if (extraData.present) { + final converter = $ReactionsTable.$converter0; + map['extra_data'] = Variable(converter.mapToSql(extraData.value)); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ReactionsCompanion(') + ..write('userId: $userId, ') + ..write('messageId: $messageId, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('score: $score, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } +} + +class $ReactionsTable extends Reactions + with TableInfo<$ReactionsTable, ReactionEntity> { + final GeneratedDatabase _db; + final String _alias; + $ReactionsTable(this._db, [this._alias]); + final VerificationMeta _userIdMeta = const VerificationMeta('userId'); + GeneratedTextColumn _userId; + @override + GeneratedTextColumn get userId => _userId ??= _constructUserId(); + GeneratedTextColumn _constructUserId() { + return GeneratedTextColumn( + 'user_id', + $tableName, + false, + ); + } + + final VerificationMeta _messageIdMeta = const VerificationMeta('messageId'); + GeneratedTextColumn _messageId; + @override + GeneratedTextColumn get messageId => _messageId ??= _constructMessageId(); + GeneratedTextColumn _constructMessageId() { + return GeneratedTextColumn('message_id', $tableName, false, + $customConstraints: 'REFERENCES messages(id) ON DELETE CASCADE'); + } + + final VerificationMeta _typeMeta = const VerificationMeta('type'); + GeneratedTextColumn _type; + @override + GeneratedTextColumn get type => _type ??= _constructType(); + GeneratedTextColumn _constructType() { + return GeneratedTextColumn( + 'type', + $tableName, + false, + ); + } + + final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); + GeneratedDateTimeColumn _createdAt; + @override + GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); + GeneratedDateTimeColumn _constructCreatedAt() { + return GeneratedDateTimeColumn( + 'created_at', + $tableName, + false, + ); + } + + final VerificationMeta _scoreMeta = const VerificationMeta('score'); + GeneratedIntColumn _score; + @override + GeneratedIntColumn get score => _score ??= _constructScore(); + GeneratedIntColumn _constructScore() { + return GeneratedIntColumn( + 'score', + $tableName, + true, + ); + } + + final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); + GeneratedTextColumn _extraData; + @override + GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); + GeneratedTextColumn _constructExtraData() { + return GeneratedTextColumn( + 'extra_data', + $tableName, + true, + ); + } + + @override + List get $columns => + [userId, messageId, type, createdAt, score, extraData]; + @override + $ReactionsTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'reactions'; + @override + final String actualTableName = 'reactions'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('user_id')) { + context.handle(_userIdMeta, + userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); + } else if (isInserting) { + context.missing(_userIdMeta); + } + if (data.containsKey('message_id')) { + context.handle(_messageIdMeta, + messageId.isAcceptableOrUnknown(data['message_id'], _messageIdMeta)); + } else if (isInserting) { + context.missing(_messageIdMeta); + } + if (data.containsKey('type')) { + context.handle( + _typeMeta, type.isAcceptableOrUnknown(data['type'], _typeMeta)); + } else if (isInserting) { + context.missing(_typeMeta); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('score')) { + context.handle( + _scoreMeta, score.isAcceptableOrUnknown(data['score'], _scoreMeta)); + } + context.handle(_extraDataMeta, const VerificationResult.success()); + return context; + } + + @override + Set get $primaryKey => {messageId, type, userId}; + @override + ReactionEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return ReactionEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $ReactionsTable createAlias(String alias) { + return $ReactionsTable(_db, alias); + } + + static TypeConverter, String> $converter0 = + MapConverter(); +} + +class UserEntity extends DataClass implements Insertable { + final String id; + final String role; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime lastActive; + final bool online; + final bool banned; + final Map extraData; + UserEntity( + {@required this.id, + this.role, + this.createdAt, + this.updatedAt, + this.lastActive, + this.online, + this.banned, + this.extraData}); + factory UserEntity.fromData(Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final stringType = db.typeSystem.forDartType(); + final dateTimeType = db.typeSystem.forDartType(); + final boolType = db.typeSystem.forDartType(); + return UserEntity( + id: stringType.mapFromDatabaseResponse(data['${effectivePrefix}id']), + role: stringType.mapFromDatabaseResponse(data['${effectivePrefix}role']), + createdAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), + updatedAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), + lastActive: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}last_active']), + online: + boolType.mapFromDatabaseResponse(data['${effectivePrefix}online']), + banned: + boolType.mapFromDatabaseResponse(data['${effectivePrefix}banned']), + extraData: $UsersTable.$converter0.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || role != null) { + map['role'] = Variable(role); + } + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + if (!nullToAbsent || lastActive != null) { + map['last_active'] = Variable(lastActive); + } + if (!nullToAbsent || online != null) { + map['online'] = Variable(online); + } + if (!nullToAbsent || banned != null) { + map['banned'] = Variable(banned); + } + if (!nullToAbsent || extraData != null) { + final converter = $UsersTable.$converter0; + map['extra_data'] = Variable(converter.mapToSql(extraData)); + } + return map; + } + + factory UserEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return UserEntity( + id: serializer.fromJson(json['id']), + role: serializer.fromJson(json['role']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + lastActive: serializer.fromJson(json['lastActive']), + online: serializer.fromJson(json['online']), + banned: serializer.fromJson(json['banned']), + extraData: serializer.fromJson>(json['extraData']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'role': serializer.toJson(role), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'lastActive': serializer.toJson(lastActive), + 'online': serializer.toJson(online), + 'banned': serializer.toJson(banned), + 'extraData': serializer.toJson>(extraData), + }; + } + + UserEntity copyWith( + {String id, + Value role = const Value.absent(), + Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), + Value lastActive = const Value.absent(), + Value online = const Value.absent(), + Value banned = const Value.absent(), + Value> extraData = const Value.absent()}) => + UserEntity( + id: id ?? this.id, + role: role.present ? role.value : this.role, + createdAt: createdAt.present ? createdAt.value : this.createdAt, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + lastActive: lastActive.present ? lastActive.value : this.lastActive, + online: online.present ? online.value : this.online, + banned: banned.present ? banned.value : this.banned, + extraData: extraData.present ? extraData.value : this.extraData, + ); + @override + String toString() { + return (StringBuffer('UserEntity(') + ..write('id: $id, ') + ..write('role: $role, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('lastActive: $lastActive, ') + ..write('online: $online, ') + ..write('banned: $banned, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + id.hashCode, + $mrjc( + role.hashCode, + $mrjc( + createdAt.hashCode, + $mrjc( + updatedAt.hashCode, + $mrjc( + lastActive.hashCode, + $mrjc(online.hashCode, + $mrjc(banned.hashCode, extraData.hashCode)))))))); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is UserEntity && + other.id == this.id && + other.role == this.role && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.lastActive == this.lastActive && + other.online == this.online && + other.banned == this.banned && + other.extraData == this.extraData); +} + +class UsersCompanion extends UpdateCompanion { + final Value id; + final Value role; + final Value createdAt; + final Value updatedAt; + final Value lastActive; + final Value online; + final Value banned; + final Value> extraData; + const UsersCompanion({ + this.id = const Value.absent(), + this.role = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.lastActive = const Value.absent(), + this.online = const Value.absent(), + this.banned = const Value.absent(), + this.extraData = const Value.absent(), + }); + UsersCompanion.insert({ + @required String id, + this.role = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.lastActive = const Value.absent(), + this.online = const Value.absent(), + this.banned = const Value.absent(), + this.extraData = const Value.absent(), + }) : id = Value(id); + static Insertable custom({ + Expression id, + Expression role, + Expression createdAt, + Expression updatedAt, + Expression lastActive, + Expression online, + Expression banned, + Expression extraData, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (role != null) 'role': role, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (lastActive != null) 'last_active': lastActive, + if (online != null) 'online': online, + if (banned != null) 'banned': banned, + if (extraData != null) 'extra_data': extraData, + }); + } + + UsersCompanion copyWith( + {Value id, + Value role, + Value createdAt, + Value updatedAt, + Value lastActive, + Value online, + Value banned, + Value> extraData}) { + return UsersCompanion( + id: id ?? this.id, + role: role ?? this.role, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + lastActive: lastActive ?? this.lastActive, + online: online ?? this.online, + banned: banned ?? this.banned, + extraData: extraData ?? this.extraData, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (role.present) { + map['role'] = Variable(role.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (lastActive.present) { + map['last_active'] = Variable(lastActive.value); + } + if (online.present) { + map['online'] = Variable(online.value); + } + if (banned.present) { + map['banned'] = Variable(banned.value); + } + if (extraData.present) { + final converter = $UsersTable.$converter0; + map['extra_data'] = Variable(converter.mapToSql(extraData.value)); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UsersCompanion(') + ..write('id: $id, ') + ..write('role: $role, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('lastActive: $lastActive, ') + ..write('online: $online, ') + ..write('banned: $banned, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } +} + +class $UsersTable extends Users with TableInfo<$UsersTable, UserEntity> { + final GeneratedDatabase _db; + final String _alias; + $UsersTable(this._db, [this._alias]); + final VerificationMeta _idMeta = const VerificationMeta('id'); + GeneratedTextColumn _id; + @override + GeneratedTextColumn get id => _id ??= _constructId(); + GeneratedTextColumn _constructId() { + return GeneratedTextColumn( + 'id', + $tableName, + false, + ); + } + + final VerificationMeta _roleMeta = const VerificationMeta('role'); + GeneratedTextColumn _role; + @override + GeneratedTextColumn get role => _role ??= _constructRole(); + GeneratedTextColumn _constructRole() { + return GeneratedTextColumn( + 'role', + $tableName, + true, + ); + } + + final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); + GeneratedDateTimeColumn _createdAt; + @override + GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); + GeneratedDateTimeColumn _constructCreatedAt() { + return GeneratedDateTimeColumn( + 'created_at', + $tableName, + true, + ); + } + + final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); + GeneratedDateTimeColumn _updatedAt; + @override + GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); + GeneratedDateTimeColumn _constructUpdatedAt() { + return GeneratedDateTimeColumn( + 'updated_at', + $tableName, + true, + ); + } + + final VerificationMeta _lastActiveMeta = const VerificationMeta('lastActive'); + GeneratedDateTimeColumn _lastActive; + @override + GeneratedDateTimeColumn get lastActive => + _lastActive ??= _constructLastActive(); + GeneratedDateTimeColumn _constructLastActive() { + return GeneratedDateTimeColumn( + 'last_active', + $tableName, + true, + ); + } + + final VerificationMeta _onlineMeta = const VerificationMeta('online'); + GeneratedBoolColumn _online; + @override + GeneratedBoolColumn get online => _online ??= _constructOnline(); + GeneratedBoolColumn _constructOnline() { + return GeneratedBoolColumn( + 'online', + $tableName, + true, + ); + } + + final VerificationMeta _bannedMeta = const VerificationMeta('banned'); + GeneratedBoolColumn _banned; + @override + GeneratedBoolColumn get banned => _banned ??= _constructBanned(); + GeneratedBoolColumn _constructBanned() { + return GeneratedBoolColumn( + 'banned', + $tableName, + true, + ); + } + + final VerificationMeta _extraDataMeta = const VerificationMeta('extraData'); + GeneratedTextColumn _extraData; + @override + GeneratedTextColumn get extraData => _extraData ??= _constructExtraData(); + GeneratedTextColumn _constructExtraData() { + return GeneratedTextColumn( + 'extra_data', + $tableName, + true, + ); + } + + @override + List get $columns => + [id, role, createdAt, updatedAt, lastActive, online, banned, extraData]; + @override + $UsersTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'users'; + @override + final String actualTableName = 'users'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('role')) { + context.handle( + _roleMeta, role.isAcceptableOrUnknown(data['role'], _roleMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); + } + if (data.containsKey('last_active')) { + context.handle( + _lastActiveMeta, + lastActive.isAcceptableOrUnknown( + data['last_active'], _lastActiveMeta)); + } + if (data.containsKey('online')) { + context.handle(_onlineMeta, + online.isAcceptableOrUnknown(data['online'], _onlineMeta)); + } + if (data.containsKey('banned')) { + context.handle(_bannedMeta, + banned.isAcceptableOrUnknown(data['banned'], _bannedMeta)); + } + context.handle(_extraDataMeta, const VerificationResult.success()); + return context; + } + + @override + Set get $primaryKey => {id}; + @override + UserEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return UserEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $UsersTable createAlias(String alias) { + return $UsersTable(_db, alias); + } + + static TypeConverter, String> $converter0 = + MapConverter(); +} + +class MemberEntity extends DataClass implements Insertable { + final String userId; + final String channelCid; + final String role; + final DateTime inviteAcceptedAt; + final DateTime inviteRejectedAt; + final bool invited; + final bool banned; + final bool shadowBanned; + final bool isModerator; + final DateTime createdAt; + final DateTime updatedAt; + MemberEntity( + {@required this.userId, + @required this.channelCid, + this.role, + this.inviteAcceptedAt, + this.inviteRejectedAt, + this.invited, + this.banned, + this.shadowBanned, + this.isModerator, + @required this.createdAt, + this.updatedAt}); + factory MemberEntity.fromData(Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final stringType = db.typeSystem.forDartType(); + final dateTimeType = db.typeSystem.forDartType(); + final boolType = db.typeSystem.forDartType(); + return MemberEntity( + userId: + stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), + channelCid: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), + role: stringType.mapFromDatabaseResponse(data['${effectivePrefix}role']), + inviteAcceptedAt: dateTimeType.mapFromDatabaseResponse( + data['${effectivePrefix}invite_accepted_at']), + inviteRejectedAt: dateTimeType.mapFromDatabaseResponse( + data['${effectivePrefix}invite_rejected_at']), + invited: + boolType.mapFromDatabaseResponse(data['${effectivePrefix}invited']), + banned: + boolType.mapFromDatabaseResponse(data['${effectivePrefix}banned']), + shadowBanned: boolType + .mapFromDatabaseResponse(data['${effectivePrefix}shadow_banned']), + isModerator: boolType + .mapFromDatabaseResponse(data['${effectivePrefix}is_moderator']), + createdAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}created_at']), + updatedAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}updated_at']), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + if (!nullToAbsent || channelCid != null) { + map['channel_cid'] = Variable(channelCid); + } + if (!nullToAbsent || role != null) { + map['role'] = Variable(role); + } + if (!nullToAbsent || inviteAcceptedAt != null) { + map['invite_accepted_at'] = Variable(inviteAcceptedAt); + } + if (!nullToAbsent || inviteRejectedAt != null) { + map['invite_rejected_at'] = Variable(inviteRejectedAt); + } + if (!nullToAbsent || invited != null) { + map['invited'] = Variable(invited); + } + if (!nullToAbsent || banned != null) { + map['banned'] = Variable(banned); + } + if (!nullToAbsent || shadowBanned != null) { + map['shadow_banned'] = Variable(shadowBanned); + } + if (!nullToAbsent || isModerator != null) { + map['is_moderator'] = Variable(isModerator); + } + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + return map; + } + + factory MemberEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return MemberEntity( + userId: serializer.fromJson(json['userId']), + channelCid: serializer.fromJson(json['channelCid']), + role: serializer.fromJson(json['role']), + inviteAcceptedAt: serializer.fromJson(json['inviteAcceptedAt']), + inviteRejectedAt: serializer.fromJson(json['inviteRejectedAt']), + invited: serializer.fromJson(json['invited']), + banned: serializer.fromJson(json['banned']), + shadowBanned: serializer.fromJson(json['shadowBanned']), + isModerator: serializer.fromJson(json['isModerator']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'userId': serializer.toJson(userId), + 'channelCid': serializer.toJson(channelCid), + 'role': serializer.toJson(role), + 'inviteAcceptedAt': serializer.toJson(inviteAcceptedAt), + 'inviteRejectedAt': serializer.toJson(inviteRejectedAt), + 'invited': serializer.toJson(invited), + 'banned': serializer.toJson(banned), + 'shadowBanned': serializer.toJson(shadowBanned), + 'isModerator': serializer.toJson(isModerator), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + }; + } + + MemberEntity copyWith( + {String userId, + String channelCid, + Value role = const Value.absent(), + Value inviteAcceptedAt = const Value.absent(), + Value inviteRejectedAt = const Value.absent(), + Value invited = const Value.absent(), + Value banned = const Value.absent(), + Value shadowBanned = const Value.absent(), + Value isModerator = const Value.absent(), + DateTime createdAt, + Value updatedAt = const Value.absent()}) => + MemberEntity( + userId: userId ?? this.userId, + channelCid: channelCid ?? this.channelCid, + role: role.present ? role.value : this.role, + inviteAcceptedAt: inviteAcceptedAt.present + ? inviteAcceptedAt.value + : this.inviteAcceptedAt, + inviteRejectedAt: inviteRejectedAt.present + ? inviteRejectedAt.value + : this.inviteRejectedAt, + invited: invited.present ? invited.value : this.invited, + banned: banned.present ? banned.value : this.banned, + shadowBanned: + shadowBanned.present ? shadowBanned.value : this.shadowBanned, + isModerator: isModerator.present ? isModerator.value : this.isModerator, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + ); + @override + String toString() { + return (StringBuffer('MemberEntity(') + ..write('userId: $userId, ') + ..write('channelCid: $channelCid, ') + ..write('role: $role, ') + ..write('inviteAcceptedAt: $inviteAcceptedAt, ') + ..write('inviteRejectedAt: $inviteRejectedAt, ') + ..write('invited: $invited, ') + ..write('banned: $banned, ') + ..write('shadowBanned: $shadowBanned, ') + ..write('isModerator: $isModerator, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + userId.hashCode, + $mrjc( + channelCid.hashCode, + $mrjc( + role.hashCode, + $mrjc( + inviteAcceptedAt.hashCode, + $mrjc( + inviteRejectedAt.hashCode, + $mrjc( + invited.hashCode, + $mrjc( + banned.hashCode, + $mrjc( + shadowBanned.hashCode, + $mrjc( + isModerator.hashCode, + $mrjc(createdAt.hashCode, + updatedAt.hashCode))))))))))); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is MemberEntity && + other.userId == this.userId && + other.channelCid == this.channelCid && + other.role == this.role && + other.inviteAcceptedAt == this.inviteAcceptedAt && + other.inviteRejectedAt == this.inviteRejectedAt && + other.invited == this.invited && + other.banned == this.banned && + other.shadowBanned == this.shadowBanned && + other.isModerator == this.isModerator && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt); +} + +class MembersCompanion extends UpdateCompanion { + final Value userId; + final Value channelCid; + final Value role; + final Value inviteAcceptedAt; + final Value inviteRejectedAt; + final Value invited; + final Value banned; + final Value shadowBanned; + final Value isModerator; + final Value createdAt; + final Value updatedAt; + const MembersCompanion({ + this.userId = const Value.absent(), + this.channelCid = const Value.absent(), + this.role = const Value.absent(), + this.inviteAcceptedAt = const Value.absent(), + this.inviteRejectedAt = const Value.absent(), + this.invited = const Value.absent(), + this.banned = const Value.absent(), + this.shadowBanned = const Value.absent(), + this.isModerator = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + }); + MembersCompanion.insert({ + @required String userId, + @required String channelCid, + this.role = const Value.absent(), + this.inviteAcceptedAt = const Value.absent(), + this.inviteRejectedAt = const Value.absent(), + this.invited = const Value.absent(), + this.banned = const Value.absent(), + this.shadowBanned = const Value.absent(), + this.isModerator = const Value.absent(), + @required DateTime createdAt, + this.updatedAt = const Value.absent(), + }) : userId = Value(userId), + channelCid = Value(channelCid), + createdAt = Value(createdAt); + static Insertable custom({ + Expression userId, + Expression channelCid, + Expression role, + Expression inviteAcceptedAt, + Expression inviteRejectedAt, + Expression invited, + Expression banned, + Expression shadowBanned, + Expression isModerator, + Expression createdAt, + Expression updatedAt, + }) { + return RawValuesInsertable({ + if (userId != null) 'user_id': userId, + if (channelCid != null) 'channel_cid': channelCid, + if (role != null) 'role': role, + if (inviteAcceptedAt != null) 'invite_accepted_at': inviteAcceptedAt, + if (inviteRejectedAt != null) 'invite_rejected_at': inviteRejectedAt, + if (invited != null) 'invited': invited, + if (banned != null) 'banned': banned, + if (shadowBanned != null) 'shadow_banned': shadowBanned, + if (isModerator != null) 'is_moderator': isModerator, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + }); + } + + MembersCompanion copyWith( + {Value userId, + Value channelCid, + Value role, + Value inviteAcceptedAt, + Value inviteRejectedAt, + Value invited, + Value banned, + Value shadowBanned, + Value isModerator, + Value createdAt, + Value updatedAt}) { + return MembersCompanion( + userId: userId ?? this.userId, + channelCid: channelCid ?? this.channelCid, + role: role ?? this.role, + inviteAcceptedAt: inviteAcceptedAt ?? this.inviteAcceptedAt, + inviteRejectedAt: inviteRejectedAt ?? this.inviteRejectedAt, + invited: invited ?? this.invited, + banned: banned ?? this.banned, + shadowBanned: shadowBanned ?? this.shadowBanned, + isModerator: isModerator ?? this.isModerator, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (channelCid.present) { + map['channel_cid'] = Variable(channelCid.value); + } + if (role.present) { + map['role'] = Variable(role.value); + } + if (inviteAcceptedAt.present) { + map['invite_accepted_at'] = Variable(inviteAcceptedAt.value); + } + if (inviteRejectedAt.present) { + map['invite_rejected_at'] = Variable(inviteRejectedAt.value); + } + if (invited.present) { + map['invited'] = Variable(invited.value); + } + if (banned.present) { + map['banned'] = Variable(banned.value); + } + if (shadowBanned.present) { + map['shadow_banned'] = Variable(shadowBanned.value); + } + if (isModerator.present) { + map['is_moderator'] = Variable(isModerator.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MembersCompanion(') + ..write('userId: $userId, ') + ..write('channelCid: $channelCid, ') + ..write('role: $role, ') + ..write('inviteAcceptedAt: $inviteAcceptedAt, ') + ..write('inviteRejectedAt: $inviteRejectedAt, ') + ..write('invited: $invited, ') + ..write('banned: $banned, ') + ..write('shadowBanned: $shadowBanned, ') + ..write('isModerator: $isModerator, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } +} + +class $MembersTable extends Members + with TableInfo<$MembersTable, MemberEntity> { + final GeneratedDatabase _db; + final String _alias; + $MembersTable(this._db, [this._alias]); + final VerificationMeta _userIdMeta = const VerificationMeta('userId'); + GeneratedTextColumn _userId; + @override + GeneratedTextColumn get userId => _userId ??= _constructUserId(); + GeneratedTextColumn _constructUserId() { + return GeneratedTextColumn( + 'user_id', + $tableName, + false, + ); + } + + final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); + GeneratedTextColumn _channelCid; + @override + GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); + GeneratedTextColumn _constructChannelCid() { + return GeneratedTextColumn('channel_cid', $tableName, false, + $customConstraints: 'REFERENCES channels(cid) ON DELETE CASCADE'); + } + + final VerificationMeta _roleMeta = const VerificationMeta('role'); + GeneratedTextColumn _role; + @override + GeneratedTextColumn get role => _role ??= _constructRole(); + GeneratedTextColumn _constructRole() { + return GeneratedTextColumn( + 'role', + $tableName, + true, + ); + } + + final VerificationMeta _inviteAcceptedAtMeta = + const VerificationMeta('inviteAcceptedAt'); + GeneratedDateTimeColumn _inviteAcceptedAt; + @override + GeneratedDateTimeColumn get inviteAcceptedAt => + _inviteAcceptedAt ??= _constructInviteAcceptedAt(); + GeneratedDateTimeColumn _constructInviteAcceptedAt() { + return GeneratedDateTimeColumn( + 'invite_accepted_at', + $tableName, + true, + ); + } + + final VerificationMeta _inviteRejectedAtMeta = + const VerificationMeta('inviteRejectedAt'); + GeneratedDateTimeColumn _inviteRejectedAt; + @override + GeneratedDateTimeColumn get inviteRejectedAt => + _inviteRejectedAt ??= _constructInviteRejectedAt(); + GeneratedDateTimeColumn _constructInviteRejectedAt() { + return GeneratedDateTimeColumn( + 'invite_rejected_at', + $tableName, + true, + ); + } + + final VerificationMeta _invitedMeta = const VerificationMeta('invited'); + GeneratedBoolColumn _invited; + @override + GeneratedBoolColumn get invited => _invited ??= _constructInvited(); + GeneratedBoolColumn _constructInvited() { + return GeneratedBoolColumn( + 'invited', + $tableName, + true, + ); + } + + final VerificationMeta _bannedMeta = const VerificationMeta('banned'); + GeneratedBoolColumn _banned; + @override + GeneratedBoolColumn get banned => _banned ??= _constructBanned(); + GeneratedBoolColumn _constructBanned() { + return GeneratedBoolColumn( + 'banned', + $tableName, + true, + ); + } + + final VerificationMeta _shadowBannedMeta = + const VerificationMeta('shadowBanned'); + GeneratedBoolColumn _shadowBanned; + @override + GeneratedBoolColumn get shadowBanned => + _shadowBanned ??= _constructShadowBanned(); + GeneratedBoolColumn _constructShadowBanned() { + return GeneratedBoolColumn( + 'shadow_banned', + $tableName, + true, + ); + } + + final VerificationMeta _isModeratorMeta = + const VerificationMeta('isModerator'); + GeneratedBoolColumn _isModerator; + @override + GeneratedBoolColumn get isModerator => + _isModerator ??= _constructIsModerator(); + GeneratedBoolColumn _constructIsModerator() { + return GeneratedBoolColumn( + 'is_moderator', + $tableName, + true, + ); + } + + final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); + GeneratedDateTimeColumn _createdAt; + @override + GeneratedDateTimeColumn get createdAt => _createdAt ??= _constructCreatedAt(); + GeneratedDateTimeColumn _constructCreatedAt() { + return GeneratedDateTimeColumn( + 'created_at', + $tableName, + false, + ); + } + + final VerificationMeta _updatedAtMeta = const VerificationMeta('updatedAt'); + GeneratedDateTimeColumn _updatedAt; + @override + GeneratedDateTimeColumn get updatedAt => _updatedAt ??= _constructUpdatedAt(); + GeneratedDateTimeColumn _constructUpdatedAt() { + return GeneratedDateTimeColumn( + 'updated_at', + $tableName, + true, + ); + } + + @override + List get $columns => [ + userId, + channelCid, + role, + inviteAcceptedAt, + inviteRejectedAt, + invited, + banned, + shadowBanned, + isModerator, + createdAt, + updatedAt + ]; + @override + $MembersTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'members'; + @override + final String actualTableName = 'members'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('user_id')) { + context.handle(_userIdMeta, + userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); + } else if (isInserting) { + context.missing(_userIdMeta); + } + if (data.containsKey('channel_cid')) { + context.handle( + _channelCidMeta, + channelCid.isAcceptableOrUnknown( + data['channel_cid'], _channelCidMeta)); + } else if (isInserting) { + context.missing(_channelCidMeta); + } + if (data.containsKey('role')) { + context.handle( + _roleMeta, role.isAcceptableOrUnknown(data['role'], _roleMeta)); + } + if (data.containsKey('invite_accepted_at')) { + context.handle( + _inviteAcceptedAtMeta, + inviteAcceptedAt.isAcceptableOrUnknown( + data['invite_accepted_at'], _inviteAcceptedAtMeta)); + } + if (data.containsKey('invite_rejected_at')) { + context.handle( + _inviteRejectedAtMeta, + inviteRejectedAt.isAcceptableOrUnknown( + data['invite_rejected_at'], _inviteRejectedAtMeta)); + } + if (data.containsKey('invited')) { + context.handle(_invitedMeta, + invited.isAcceptableOrUnknown(data['invited'], _invitedMeta)); + } + if (data.containsKey('banned')) { + context.handle(_bannedMeta, + banned.isAcceptableOrUnknown(data['banned'], _bannedMeta)); + } + if (data.containsKey('shadow_banned')) { + context.handle( + _shadowBannedMeta, + shadowBanned.isAcceptableOrUnknown( + data['shadow_banned'], _shadowBannedMeta)); + } + if (data.containsKey('is_moderator')) { + context.handle( + _isModeratorMeta, + isModerator.isAcceptableOrUnknown( + data['is_moderator'], _isModeratorMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at'], _createdAtMeta)); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at'], _updatedAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {userId, channelCid}; + @override + MemberEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return MemberEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $MembersTable createAlias(String alias) { + return $MembersTable(_db, alias); + } +} + +class ReadEntity extends DataClass implements Insertable { + final DateTime lastRead; + final String userId; + final String channelCid; + final int unreadMessages; + ReadEntity( + {@required this.lastRead, + @required this.userId, + @required this.channelCid, + this.unreadMessages}); + factory ReadEntity.fromData(Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final dateTimeType = db.typeSystem.forDartType(); + final stringType = db.typeSystem.forDartType(); + final intType = db.typeSystem.forDartType(); + return ReadEntity( + lastRead: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}last_read']), + userId: + stringType.mapFromDatabaseResponse(data['${effectivePrefix}user_id']), + channelCid: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), + unreadMessages: intType + .mapFromDatabaseResponse(data['${effectivePrefix}unread_messages']), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || lastRead != null) { + map['last_read'] = Variable(lastRead); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + if (!nullToAbsent || channelCid != null) { + map['channel_cid'] = Variable(channelCid); + } + if (!nullToAbsent || unreadMessages != null) { + map['unread_messages'] = Variable(unreadMessages); + } + return map; + } + + factory ReadEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return ReadEntity( + lastRead: serializer.fromJson(json['lastRead']), + userId: serializer.fromJson(json['userId']), + channelCid: serializer.fromJson(json['channelCid']), + unreadMessages: serializer.fromJson(json['unreadMessages']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'lastRead': serializer.toJson(lastRead), + 'userId': serializer.toJson(userId), + 'channelCid': serializer.toJson(channelCid), + 'unreadMessages': serializer.toJson(unreadMessages), + }; + } + + ReadEntity copyWith( + {DateTime lastRead, + String userId, + String channelCid, + Value unreadMessages = const Value.absent()}) => + ReadEntity( + lastRead: lastRead ?? this.lastRead, + userId: userId ?? this.userId, + channelCid: channelCid ?? this.channelCid, + unreadMessages: + unreadMessages.present ? unreadMessages.value : this.unreadMessages, + ); + @override + String toString() { + return (StringBuffer('ReadEntity(') + ..write('lastRead: $lastRead, ') + ..write('userId: $userId, ') + ..write('channelCid: $channelCid, ') + ..write('unreadMessages: $unreadMessages') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + lastRead.hashCode, + $mrjc(userId.hashCode, + $mrjc(channelCid.hashCode, unreadMessages.hashCode)))); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is ReadEntity && + other.lastRead == this.lastRead && + other.userId == this.userId && + other.channelCid == this.channelCid && + other.unreadMessages == this.unreadMessages); +} + +class ReadsCompanion extends UpdateCompanion { + final Value lastRead; + final Value userId; + final Value channelCid; + final Value unreadMessages; + const ReadsCompanion({ + this.lastRead = const Value.absent(), + this.userId = const Value.absent(), + this.channelCid = const Value.absent(), + this.unreadMessages = const Value.absent(), + }); + ReadsCompanion.insert({ + @required DateTime lastRead, + @required String userId, + @required String channelCid, + this.unreadMessages = const Value.absent(), + }) : lastRead = Value(lastRead), + userId = Value(userId), + channelCid = Value(channelCid); + static Insertable custom({ + Expression lastRead, + Expression userId, + Expression channelCid, + Expression unreadMessages, + }) { + return RawValuesInsertable({ + if (lastRead != null) 'last_read': lastRead, + if (userId != null) 'user_id': userId, + if (channelCid != null) 'channel_cid': channelCid, + if (unreadMessages != null) 'unread_messages': unreadMessages, + }); + } + + ReadsCompanion copyWith( + {Value lastRead, + Value userId, + Value channelCid, + Value unreadMessages}) { + return ReadsCompanion( + lastRead: lastRead ?? this.lastRead, + userId: userId ?? this.userId, + channelCid: channelCid ?? this.channelCid, + unreadMessages: unreadMessages ?? this.unreadMessages, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (lastRead.present) { + map['last_read'] = Variable(lastRead.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (channelCid.present) { + map['channel_cid'] = Variable(channelCid.value); + } + if (unreadMessages.present) { + map['unread_messages'] = Variable(unreadMessages.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ReadsCompanion(') + ..write('lastRead: $lastRead, ') + ..write('userId: $userId, ') + ..write('channelCid: $channelCid, ') + ..write('unreadMessages: $unreadMessages') + ..write(')')) + .toString(); + } +} + +class $ReadsTable extends Reads with TableInfo<$ReadsTable, ReadEntity> { + final GeneratedDatabase _db; + final String _alias; + $ReadsTable(this._db, [this._alias]); + final VerificationMeta _lastReadMeta = const VerificationMeta('lastRead'); + GeneratedDateTimeColumn _lastRead; + @override + GeneratedDateTimeColumn get lastRead => _lastRead ??= _constructLastRead(); + GeneratedDateTimeColumn _constructLastRead() { + return GeneratedDateTimeColumn( + 'last_read', + $tableName, + false, + ); + } + + final VerificationMeta _userIdMeta = const VerificationMeta('userId'); + GeneratedTextColumn _userId; + @override + GeneratedTextColumn get userId => _userId ??= _constructUserId(); + GeneratedTextColumn _constructUserId() { + return GeneratedTextColumn( + 'user_id', + $tableName, + false, + ); + } + + final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); + GeneratedTextColumn _channelCid; + @override + GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); + GeneratedTextColumn _constructChannelCid() { + return GeneratedTextColumn('channel_cid', $tableName, false, + $customConstraints: 'REFERENCES channels(cid) ON DELETE CASCADE'); + } + + final VerificationMeta _unreadMessagesMeta = + const VerificationMeta('unreadMessages'); + GeneratedIntColumn _unreadMessages; + @override + GeneratedIntColumn get unreadMessages => + _unreadMessages ??= _constructUnreadMessages(); + GeneratedIntColumn _constructUnreadMessages() { + return GeneratedIntColumn( + 'unread_messages', + $tableName, + true, + ); + } + + @override + List get $columns => + [lastRead, userId, channelCid, unreadMessages]; + @override + $ReadsTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'reads'; + @override + final String actualTableName = 'reads'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('last_read')) { + context.handle(_lastReadMeta, + lastRead.isAcceptableOrUnknown(data['last_read'], _lastReadMeta)); + } else if (isInserting) { + context.missing(_lastReadMeta); + } + if (data.containsKey('user_id')) { + context.handle(_userIdMeta, + userId.isAcceptableOrUnknown(data['user_id'], _userIdMeta)); + } else if (isInserting) { + context.missing(_userIdMeta); + } + if (data.containsKey('channel_cid')) { + context.handle( + _channelCidMeta, + channelCid.isAcceptableOrUnknown( + data['channel_cid'], _channelCidMeta)); + } else if (isInserting) { + context.missing(_channelCidMeta); + } + if (data.containsKey('unread_messages')) { + context.handle( + _unreadMessagesMeta, + unreadMessages.isAcceptableOrUnknown( + data['unread_messages'], _unreadMessagesMeta)); + } + return context; + } + + @override + Set get $primaryKey => {userId, channelCid}; + @override + ReadEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return ReadEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $ReadsTable createAlias(String alias) { + return $ReadsTable(_db, alias); + } +} + +class ChannelQueryEntity extends DataClass + implements Insertable { + final String queryHash; + final String channelCid; + ChannelQueryEntity({@required this.queryHash, @required this.channelCid}); + factory ChannelQueryEntity.fromData( + Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final stringType = db.typeSystem.forDartType(); + return ChannelQueryEntity( + queryHash: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}query_hash']), + channelCid: stringType + .mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || queryHash != null) { + map['query_hash'] = Variable(queryHash); + } + if (!nullToAbsent || channelCid != null) { + map['channel_cid'] = Variable(channelCid); + } + return map; + } + + factory ChannelQueryEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return ChannelQueryEntity( + queryHash: serializer.fromJson(json['queryHash']), + channelCid: serializer.fromJson(json['channelCid']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'queryHash': serializer.toJson(queryHash), + 'channelCid': serializer.toJson(channelCid), + }; + } + + ChannelQueryEntity copyWith({String queryHash, String channelCid}) => + ChannelQueryEntity( + queryHash: queryHash ?? this.queryHash, + channelCid: channelCid ?? this.channelCid, + ); + @override + String toString() { + return (StringBuffer('ChannelQueryEntity(') + ..write('queryHash: $queryHash, ') + ..write('channelCid: $channelCid') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc(queryHash.hashCode, channelCid.hashCode)); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is ChannelQueryEntity && + other.queryHash == this.queryHash && + other.channelCid == this.channelCid); +} + +class ChannelQueriesCompanion extends UpdateCompanion { + final Value queryHash; + final Value channelCid; + const ChannelQueriesCompanion({ + this.queryHash = const Value.absent(), + this.channelCid = const Value.absent(), + }); + ChannelQueriesCompanion.insert({ + @required String queryHash, + @required String channelCid, + }) : queryHash = Value(queryHash), + channelCid = Value(channelCid); + static Insertable custom({ + Expression queryHash, + Expression channelCid, + }) { + return RawValuesInsertable({ + if (queryHash != null) 'query_hash': queryHash, + if (channelCid != null) 'channel_cid': channelCid, + }); + } + + ChannelQueriesCompanion copyWith( + {Value queryHash, Value channelCid}) { + return ChannelQueriesCompanion( + queryHash: queryHash ?? this.queryHash, + channelCid: channelCid ?? this.channelCid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (queryHash.present) { + map['query_hash'] = Variable(queryHash.value); + } + if (channelCid.present) { + map['channel_cid'] = Variable(channelCid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ChannelQueriesCompanion(') + ..write('queryHash: $queryHash, ') + ..write('channelCid: $channelCid') + ..write(')')) + .toString(); + } +} + +class $ChannelQueriesTable extends ChannelQueries + with TableInfo<$ChannelQueriesTable, ChannelQueryEntity> { + final GeneratedDatabase _db; + final String _alias; + $ChannelQueriesTable(this._db, [this._alias]); + final VerificationMeta _queryHashMeta = const VerificationMeta('queryHash'); + GeneratedTextColumn _queryHash; + @override + GeneratedTextColumn get queryHash => _queryHash ??= _constructQueryHash(); + GeneratedTextColumn _constructQueryHash() { + return GeneratedTextColumn( + 'query_hash', + $tableName, + false, + ); + } + + final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); + GeneratedTextColumn _channelCid; + @override + GeneratedTextColumn get channelCid => _channelCid ??= _constructChannelCid(); + GeneratedTextColumn _constructChannelCid() { + return GeneratedTextColumn( + 'channel_cid', + $tableName, + false, + ); + } + + @override + List get $columns => [queryHash, channelCid]; + @override + $ChannelQueriesTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'channel_queries'; + @override + final String actualTableName = 'channel_queries'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('query_hash')) { + context.handle(_queryHashMeta, + queryHash.isAcceptableOrUnknown(data['query_hash'], _queryHashMeta)); + } else if (isInserting) { + context.missing(_queryHashMeta); + } + if (data.containsKey('channel_cid')) { + context.handle( + _channelCidMeta, + channelCid.isAcceptableOrUnknown( + data['channel_cid'], _channelCidMeta)); + } else if (isInserting) { + context.missing(_channelCidMeta); + } + return context; + } + + @override + Set get $primaryKey => {queryHash, channelCid}; + @override + ChannelQueryEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return ChannelQueryEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $ChannelQueriesTable createAlias(String alias) { + return $ChannelQueriesTable(_db, alias); + } +} + +class ConnectionEventEntity extends DataClass + implements Insertable { + final int id; + final Map ownUser; + final int totalUnreadCount; + final int unreadChannels; + final DateTime lastEventAt; + final DateTime lastSyncAt; + ConnectionEventEntity( + {@required this.id, + this.ownUser, + this.totalUnreadCount, + this.unreadChannels, + this.lastEventAt, + this.lastSyncAt}); + factory ConnectionEventEntity.fromData( + Map data, GeneratedDatabase db, + {String prefix}) { + final effectivePrefix = prefix ?? ''; + final intType = db.typeSystem.forDartType(); + final stringType = db.typeSystem.forDartType(); + final dateTimeType = db.typeSystem.forDartType(); + return ConnectionEventEntity( + id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']), + ownUser: $ConnectionEventsTable.$converter0.mapToDart(stringType + .mapFromDatabaseResponse(data['${effectivePrefix}own_user'])), + totalUnreadCount: intType.mapFromDatabaseResponse( + data['${effectivePrefix}total_unread_count']), + unreadChannels: intType + .mapFromDatabaseResponse(data['${effectivePrefix}unread_channels']), + lastEventAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}last_event_at']), + lastSyncAt: dateTimeType + .mapFromDatabaseResponse(data['${effectivePrefix}last_sync_at']), + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || ownUser != null) { + final converter = $ConnectionEventsTable.$converter0; + map['own_user'] = Variable(converter.mapToSql(ownUser)); + } + if (!nullToAbsent || totalUnreadCount != null) { + map['total_unread_count'] = Variable(totalUnreadCount); + } + if (!nullToAbsent || unreadChannels != null) { + map['unread_channels'] = Variable(unreadChannels); + } + if (!nullToAbsent || lastEventAt != null) { + map['last_event_at'] = Variable(lastEventAt); + } + if (!nullToAbsent || lastSyncAt != null) { + map['last_sync_at'] = Variable(lastSyncAt); + } + return map; + } + + factory ConnectionEventEntity.fromJson(Map json, + {ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return ConnectionEventEntity( + id: serializer.fromJson(json['id']), + ownUser: serializer.fromJson>(json['ownUser']), + totalUnreadCount: serializer.fromJson(json['totalUnreadCount']), + unreadChannels: serializer.fromJson(json['unreadChannels']), + lastEventAt: serializer.fromJson(json['lastEventAt']), + lastSyncAt: serializer.fromJson(json['lastSyncAt']), + ); + } + @override + Map toJson({ValueSerializer serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'ownUser': serializer.toJson>(ownUser), + 'totalUnreadCount': serializer.toJson(totalUnreadCount), + 'unreadChannels': serializer.toJson(unreadChannels), + 'lastEventAt': serializer.toJson(lastEventAt), + 'lastSyncAt': serializer.toJson(lastSyncAt), + }; + } + + ConnectionEventEntity copyWith( + {int id, + Value> ownUser = const Value.absent(), + Value totalUnreadCount = const Value.absent(), + Value unreadChannels = const Value.absent(), + Value lastEventAt = const Value.absent(), + Value lastSyncAt = const Value.absent()}) => + ConnectionEventEntity( + id: id ?? this.id, + ownUser: ownUser.present ? ownUser.value : this.ownUser, + totalUnreadCount: totalUnreadCount.present + ? totalUnreadCount.value + : this.totalUnreadCount, + unreadChannels: + unreadChannels.present ? unreadChannels.value : this.unreadChannels, + lastEventAt: lastEventAt.present ? lastEventAt.value : this.lastEventAt, + lastSyncAt: lastSyncAt.present ? lastSyncAt.value : this.lastSyncAt, + ); + @override + String toString() { + return (StringBuffer('ConnectionEventEntity(') + ..write('id: $id, ') + ..write('ownUser: $ownUser, ') + ..write('totalUnreadCount: $totalUnreadCount, ') + ..write('unreadChannels: $unreadChannels, ') + ..write('lastEventAt: $lastEventAt, ') + ..write('lastSyncAt: $lastSyncAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + id.hashCode, + $mrjc( + ownUser.hashCode, + $mrjc( + totalUnreadCount.hashCode, + $mrjc(unreadChannels.hashCode, + $mrjc(lastEventAt.hashCode, lastSyncAt.hashCode)))))); + @override + bool operator ==(dynamic other) => + identical(this, other) || + (other is ConnectionEventEntity && + other.id == this.id && + other.ownUser == this.ownUser && + other.totalUnreadCount == this.totalUnreadCount && + other.unreadChannels == this.unreadChannels && + other.lastEventAt == this.lastEventAt && + other.lastSyncAt == this.lastSyncAt); +} + +class ConnectionEventsCompanion extends UpdateCompanion { + final Value id; + final Value> ownUser; + final Value totalUnreadCount; + final Value unreadChannels; + final Value lastEventAt; + final Value lastSyncAt; + const ConnectionEventsCompanion({ + this.id = const Value.absent(), + this.ownUser = const Value.absent(), + this.totalUnreadCount = const Value.absent(), + this.unreadChannels = const Value.absent(), + this.lastEventAt = const Value.absent(), + this.lastSyncAt = const Value.absent(), + }); + ConnectionEventsCompanion.insert({ + this.id = const Value.absent(), + this.ownUser = const Value.absent(), + this.totalUnreadCount = const Value.absent(), + this.unreadChannels = const Value.absent(), + this.lastEventAt = const Value.absent(), + this.lastSyncAt = const Value.absent(), + }); + static Insertable custom({ + Expression id, + Expression ownUser, + Expression totalUnreadCount, + Expression unreadChannels, + Expression lastEventAt, + Expression lastSyncAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (ownUser != null) 'own_user': ownUser, + if (totalUnreadCount != null) 'total_unread_count': totalUnreadCount, + if (unreadChannels != null) 'unread_channels': unreadChannels, + if (lastEventAt != null) 'last_event_at': lastEventAt, + if (lastSyncAt != null) 'last_sync_at': lastSyncAt, + }); + } + + ConnectionEventsCompanion copyWith( + {Value id, + Value> ownUser, + Value totalUnreadCount, + Value unreadChannels, + Value lastEventAt, + Value lastSyncAt}) { + return ConnectionEventsCompanion( + id: id ?? this.id, + ownUser: ownUser ?? this.ownUser, + totalUnreadCount: totalUnreadCount ?? this.totalUnreadCount, + unreadChannels: unreadChannels ?? this.unreadChannels, + lastEventAt: lastEventAt ?? this.lastEventAt, + lastSyncAt: lastSyncAt ?? this.lastSyncAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (ownUser.present) { + final converter = $ConnectionEventsTable.$converter0; + map['own_user'] = Variable(converter.mapToSql(ownUser.value)); + } + if (totalUnreadCount.present) { + map['total_unread_count'] = Variable(totalUnreadCount.value); + } + if (unreadChannels.present) { + map['unread_channels'] = Variable(unreadChannels.value); + } + if (lastEventAt.present) { + map['last_event_at'] = Variable(lastEventAt.value); + } + if (lastSyncAt.present) { + map['last_sync_at'] = Variable(lastSyncAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ConnectionEventsCompanion(') + ..write('id: $id, ') + ..write('ownUser: $ownUser, ') + ..write('totalUnreadCount: $totalUnreadCount, ') + ..write('unreadChannels: $unreadChannels, ') + ..write('lastEventAt: $lastEventAt, ') + ..write('lastSyncAt: $lastSyncAt') + ..write(')')) + .toString(); + } +} + +class $ConnectionEventsTable extends ConnectionEvents + with TableInfo<$ConnectionEventsTable, ConnectionEventEntity> { + final GeneratedDatabase _db; + final String _alias; + $ConnectionEventsTable(this._db, [this._alias]); + final VerificationMeta _idMeta = const VerificationMeta('id'); + GeneratedIntColumn _id; + @override + GeneratedIntColumn get id => _id ??= _constructId(); + GeneratedIntColumn _constructId() { + return GeneratedIntColumn( + 'id', + $tableName, + false, + ); + } + + final VerificationMeta _ownUserMeta = const VerificationMeta('ownUser'); + GeneratedTextColumn _ownUser; + @override + GeneratedTextColumn get ownUser => _ownUser ??= _constructOwnUser(); + GeneratedTextColumn _constructOwnUser() { + return GeneratedTextColumn( + 'own_user', + $tableName, + true, + ); + } + + final VerificationMeta _totalUnreadCountMeta = + const VerificationMeta('totalUnreadCount'); + GeneratedIntColumn _totalUnreadCount; + @override + GeneratedIntColumn get totalUnreadCount => + _totalUnreadCount ??= _constructTotalUnreadCount(); + GeneratedIntColumn _constructTotalUnreadCount() { + return GeneratedIntColumn( + 'total_unread_count', + $tableName, + true, + ); + } + + final VerificationMeta _unreadChannelsMeta = + const VerificationMeta('unreadChannels'); + GeneratedIntColumn _unreadChannels; + @override + GeneratedIntColumn get unreadChannels => + _unreadChannels ??= _constructUnreadChannels(); + GeneratedIntColumn _constructUnreadChannels() { + return GeneratedIntColumn( + 'unread_channels', + $tableName, + true, + ); + } + + final VerificationMeta _lastEventAtMeta = + const VerificationMeta('lastEventAt'); + GeneratedDateTimeColumn _lastEventAt; + @override + GeneratedDateTimeColumn get lastEventAt => + _lastEventAt ??= _constructLastEventAt(); + GeneratedDateTimeColumn _constructLastEventAt() { + return GeneratedDateTimeColumn( + 'last_event_at', + $tableName, + true, + ); + } + + final VerificationMeta _lastSyncAtMeta = const VerificationMeta('lastSyncAt'); + GeneratedDateTimeColumn _lastSyncAt; + @override + GeneratedDateTimeColumn get lastSyncAt => + _lastSyncAt ??= _constructLastSyncAt(); + GeneratedDateTimeColumn _constructLastSyncAt() { + return GeneratedDateTimeColumn( + 'last_sync_at', + $tableName, + true, + ); + } + + @override + List get $columns => + [id, ownUser, totalUnreadCount, unreadChannels, lastEventAt, lastSyncAt]; + @override + $ConnectionEventsTable get asDslTable => this; + @override + String get $tableName => _alias ?? 'connection_events'; + @override + final String actualTableName = 'connection_events'; + @override + VerificationContext validateIntegrity( + Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); + } + context.handle(_ownUserMeta, const VerificationResult.success()); + if (data.containsKey('total_unread_count')) { + context.handle( + _totalUnreadCountMeta, + totalUnreadCount.isAcceptableOrUnknown( + data['total_unread_count'], _totalUnreadCountMeta)); + } + if (data.containsKey('unread_channels')) { + context.handle( + _unreadChannelsMeta, + unreadChannels.isAcceptableOrUnknown( + data['unread_channels'], _unreadChannelsMeta)); + } + if (data.containsKey('last_event_at')) { + context.handle( + _lastEventAtMeta, + lastEventAt.isAcceptableOrUnknown( + data['last_event_at'], _lastEventAtMeta)); + } + if (data.containsKey('last_sync_at')) { + context.handle( + _lastSyncAtMeta, + lastSyncAt.isAcceptableOrUnknown( + data['last_sync_at'], _lastSyncAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + ConnectionEventEntity map(Map data, {String tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; + return ConnectionEventEntity.fromData(data, _db, prefix: effectivePrefix); + } + + @override + $ConnectionEventsTable createAlias(String alias) { + return $ConnectionEventsTable(_db, alias); + } + + static TypeConverter, String> $converter0 = + MapConverter(); +} + +abstract class _$MoorChatDatabase extends GeneratedDatabase { + _$MoorChatDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e); + _$MoorChatDatabase.connect(DatabaseConnection c) : super.connect(c); + $ChannelsTable _channels; + $ChannelsTable get channels => _channels ??= $ChannelsTable(this); + $MessagesTable _messages; + $MessagesTable get messages => _messages ??= $MessagesTable(this); + $ReactionsTable _reactions; + $ReactionsTable get reactions => _reactions ??= $ReactionsTable(this); + $UsersTable _users; + $UsersTable get users => _users ??= $UsersTable(this); + $MembersTable _members; + $MembersTable get members => _members ??= $MembersTable(this); + $ReadsTable _reads; + $ReadsTable get reads => _reads ??= $ReadsTable(this); + $ChannelQueriesTable _channelQueries; + $ChannelQueriesTable get channelQueries => + _channelQueries ??= $ChannelQueriesTable(this); + $ConnectionEventsTable _connectionEvents; + $ConnectionEventsTable get connectionEvents => + _connectionEvents ??= $ConnectionEventsTable(this); + UserDao _userDao; + UserDao get userDao => _userDao ??= UserDao(this as MoorChatDatabase); + ChannelDao _channelDao; + ChannelDao get channelDao => + _channelDao ??= ChannelDao(this as MoorChatDatabase); + MessageDao _messageDao; + MessageDao get messageDao => + _messageDao ??= MessageDao(this as MoorChatDatabase); + MemberDao _memberDao; + MemberDao get memberDao => _memberDao ??= MemberDao(this as MoorChatDatabase); + ReactionDao _reactionDao; + ReactionDao get reactionDao => + _reactionDao ??= ReactionDao(this as MoorChatDatabase); + ReadDao _readDao; + ReadDao get readDao => _readDao ??= ReadDao(this as MoorChatDatabase); + ChannelQueryDao _channelQueryDao; + ChannelQueryDao get channelQueryDao => + _channelQueryDao ??= ChannelQueryDao(this as MoorChatDatabase); + ConnectionEventDao _connectionEventDao; + ConnectionEventDao get connectionEventDao => + _connectionEventDao ??= ConnectionEventDao(this as MoorChatDatabase); + @override + Iterable get allTables => allSchemaEntities.whereType(); + @override + List get allSchemaEntities => [ + channels, + messages, + reactions, + users, + members, + reads, + channelQueries, + connectionEvents + ]; +} From eaf322f660a8fc04c028e6222076ce7404867537 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 26 Jan 2021 16:55:23 +0530 Subject: [PATCH 09/46] [StreamChatPersistence] Ran formatter Signed-off-by: Sahil Kumar --- .../stream_chat_persistence/lib/src/converter/converter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat_persistence/lib/src/converter/converter.dart b/packages/stream_chat_persistence/lib/src/converter/converter.dart index f32f4b54..a5d7bbdc 100644 --- a/packages/stream_chat_persistence/lib/src/converter/converter.dart +++ b/packages/stream_chat_persistence/lib/src/converter/converter.dart @@ -1,3 +1,3 @@ export 'list_converter.dart'; export 'map_converter.dart'; -export 'message_sending_status_converter.dart'; \ No newline at end of file +export 'message_sending_status_converter.dart'; From f48b7c88826ded1bc5c3fd03941f17c1c5a5dff1 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 26 Jan 2021 16:58:18 +0530 Subject: [PATCH 10/46] [StreamChat] Fix test Signed-off-by: Sahil Kumar --- packages/dart_client/test/src/models/message_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dart_client/test/src/models/message_test.dart b/packages/dart_client/test/src/models/message_test.dart index f318daac..de335c21 100644 --- a/packages/dart_client/test/src/models/message_test.dart +++ b/packages/dart_client/test/src/models/message_test.dart @@ -116,7 +116,7 @@ void main() { showInChannel: true, parentId: 'parentId', extraData: {'hey': 'test'}, - status: MessageSendingStatus.SENT, + status: MessageSendingStatus.sent, ); expect( From 1521558304f536eea2baa8c3ac75a51eeb8edd81 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 27 Jan 2021 12:52:37 +0530 Subject: [PATCH 11/46] Make `stream_chat_persistence` a add on dependency instead of shipping it with the llc Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/api/channel.dart | 18 +++-- packages/dart_client/lib/src/client.dart | 55 ++++++-------- ...ence.dart => chat_persistence_client.dart} | 13 ++-- .../dart_client/lib/src/notifications.dart | 54 ++++---------- packages/dart_client/lib/stream_chat.dart | 2 +- .../example/lib/advanced_options_page.dart | 74 ++----------------- .../flutter_widgets/example/lib/main.dart | 9 ++- .../example/lib/notifications_service.dart | 14 +++- .../example/lib/routes/app_routes.dart | 6 ++ .../example/lib/routes/routes.dart | 1 + packages/flutter_widgets/example/pubspec.yaml | 4 +- .../lib/src/db/shared/unsupported_db.dart | 2 +- .../lib/src/mapper/channel_mapper.dart | 1 - ...rt => stream_chat_persistence_client.dart} | 57 +++++++------- .../lib/stream_chat_persistence.dart | 2 +- packages/stream_chat_persistence/pubspec.yaml | 1 + 16 files changed, 126 insertions(+), 187 deletions(-) rename packages/dart_client/lib/src/db/{stream_chat_persistence.dart => chat_persistence_client.dart} (95%) rename packages/stream_chat_persistence/lib/src/{stream_chat_persistence_impl.dart => stream_chat_persistence_client.dart} (79%) diff --git a/packages/dart_client/lib/src/api/channel.dart b/packages/dart_client/lib/src/api/channel.dart index a8952e34..3ba9aa1f 100644 --- a/packages/dart_client/lib/src/api/channel.dart +++ b/packages/dart_client/lib/src/api/channel.dart @@ -419,7 +419,7 @@ class Channel { } } - await _client.chatPersistence?.deleteMessageById(messageId); + await _client.chatPersistenceClient?.deleteMessageById(messageId); } return res; @@ -487,7 +487,7 @@ class Channel { PaginationParams options, { bool preferOffline = false, }) async { - final cachedReplies = await _client.chatPersistence?.getReplies( + final cachedReplies = await _client.chatPersistenceClient?.getReplies( parentId, lessThan: options?.lessThan, ); @@ -603,7 +603,8 @@ class Channel { } if (preferOffline && cid != null) { - final updatedState = await _client.chatPersistence?.getChannelStateByCid( + final updatedState = + await _client.chatPersistenceClient?.getChannelStateByCid( cid, messagePagination: messagesPagination, ); @@ -730,7 +731,7 @@ class Channel { if (clearHistory == true) { state.truncate(); - await _client.chatPersistence?.deleteMessageByCid(_cid); + await _client.chatPersistenceClient?.deleteMessageByCid(_cid); } return _client.decode(response.data, EmptyResponse.fromJson); @@ -869,7 +870,7 @@ class ChannelClientState { _computeInitialUnread(); - _channel._client.chatPersistence + _channel._client.chatPersistenceClient ?.getChannelThreads(_channel.cid) ?.then((threads) { _threads = threads; @@ -947,7 +948,8 @@ class ChannelClientState { .on(EventType.channelTruncated, EventType.notificationChannelTruncated) .listen((event) async { final channel = event.channel; - await _channel._client.chatPersistence?.deleteMessageByCid(channel.cid); + await _channel._client.chatPersistenceClient + ?.deleteMessageByCid(channel.cid); truncate(); })); } @@ -1401,7 +1403,7 @@ class ChannelClientState { set _channelState(ChannelState v) { _channelStateController.add(v); - _channel._client.chatPersistence?.updateChannelState(v); + _channel._client.chatPersistenceClient?.updateChannelState(v); } /// The channel threads related to this channel @@ -1414,7 +1416,7 @@ class ChannelClientState { BehaviorSubject.seeded({}); set _threads(Map> v) { - _channel._client.chatPersistence?.updateMessages( + _channel._client.chatPersistenceClient?.updateMessages( _channel.cid, v.values.expand((v) => v).toList(), ); diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index 99350636..714acbd5 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -6,7 +6,6 @@ import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; import 'package:logging/logging.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stream_chat/src/api/retry_policy.dart'; import 'package:stream_chat/src/event_type.dart'; @@ -21,7 +20,7 @@ import 'api/connection_status.dart'; import 'api/requests.dart'; import 'api/responses.dart'; import 'api/websocket.dart'; -import 'db/stream_chat_persistence.dart'; +import 'db/chat_persistence_client.dart'; import 'exceptions.dart'; import 'models/event.dart'; import 'models/message.dart'; @@ -87,7 +86,6 @@ class Client { this.baseURL = _defaultBaseURL, this.logLevel = Level.WARNING, this.logHandlerFunction, - this.persistenceEnabled = true, Duration connectTimeout = const Duration(seconds: 6), Duration receiveTimeout = const Duration(seconds: 6), Dio httpClient, @@ -111,10 +109,11 @@ class Client { logger.info('instantiating new client'); } - StreamChatPersistence _chatPersistence; + /// Client chat persistence client + ChatPersistenceClient chatPersistenceClient; - /// If true chat data will persist on disk - final bool persistenceEnabled; + /// Whether the chat persistence is available or not + bool get persistenceEnabled => chatPersistenceClient != null; RetryPolicy _retryPolicy; @@ -131,9 +130,6 @@ class Client { /// The amount of time that will pass before disconnecting the client in the background final Duration backgroundKeepAlive; - /// Client offline database - StreamChatPersistence get chatPersistence => _chatPersistence; - /// This client state ClientState state; @@ -345,7 +341,7 @@ class Client { /// Call this function to dispose the client void dispose() async { - await _chatPersistence?.disconnect(); + await chatPersistenceClient?.disconnect(); await _disconnect(); httpClient.close(); await _controller.close(); @@ -427,8 +423,8 @@ class Client { if (!event.isLocal) { if (_synced && event.createdAt != null) { - await _chatPersistence?.updateConnectionInfo(event); - await _chatPersistence?.updateLastSyncAt(event.createdAt); + await chatPersistenceClient?.updateConnectionInfo(event); + await chatPersistenceClient?.updateLastSyncAt(event.createdAt); } } @@ -459,12 +455,8 @@ class Client { wsConnectionStatus.value = ConnectionStatus.connecting; - if (persistenceEnabled && _chatPersistence == null) { - _chatPersistence = StreamChatPersistenceImpl( - state.user.id, - logger: _detachedLogger('💽'), - ); - await _chatPersistence.connect(); + if (persistenceEnabled) { + await chatPersistenceClient.connect('db_${state.user.id}'); } _ws = WebSocket( @@ -514,10 +506,10 @@ class Client { _ws.connectionStatus.addListener(_connectionStatusListener); - var event = await _chatPersistence?.getConnectionInfo(); + var event = await chatPersistenceClient?.getConnectionInfo(); await _ws.connect().then((e) async { - await _chatPersistence?.updateConnectionInfo(e); + await chatPersistenceClient?.updateConnectionInfo(e); event = e; await resync(); }).catchError((err, stacktrace) { @@ -532,14 +524,14 @@ class Client { /// Get the events missed while offline to sync the offline storage Future resync([List cids]) async { - final lastSyncAt = await chatPersistence?.getLastSyncAt(); + final lastSyncAt = await chatPersistenceClient?.getLastSyncAt(); if (lastSyncAt == null) { _synced = true; return; } - cids ??= await chatPersistence?.getChannelCids(); + cids ??= await chatPersistenceClient?.getChannelCids(); if (cids?.isEmpty == true) { return; @@ -568,7 +560,7 @@ class Client { handleEvent(event); }); - await _chatPersistence?.updateLastSyncAt(DateTime.now()); + await chatPersistenceClient?.updateLastSyncAt(DateTime.now()); _synced = true; } catch (error) { logger.severe('Error during resync $error'); @@ -714,7 +706,7 @@ class Client { channels.add(channel); } else { final newChannel = Channel.fromState(this, channelState); - await _chatPersistence + await chatPersistenceClient ?.updateChannelState(newChannel.state.channelState); newChannel.state?.updateChannelState(channelState); newChannels[newChannel.cid] = newChannel; @@ -725,7 +717,7 @@ class Client { state.channels = newChannels; - await _chatPersistence?.updateChannelQueries( + await chatPersistenceClient?.updateChannelQueries( filter, res.channels.map((c) => c.channel.cid).toList(), paginationParams?.offset == null || paginationParams.offset == 0, @@ -760,7 +752,7 @@ class Client { @required List sort, PaginationParams paginationParams = const PaginationParams(limit: 10), }) async { - final offlineChannels = await _chatPersistence?.getChannelStates( + final offlineChannels = await chatPersistenceClient?.getChannelStates( filter: filter, sort: sort, paginationParams: paginationParams, @@ -775,7 +767,8 @@ class Client { return channel; } else { final newChannel = Channel.fromState(this, channelState); - _chatPersistence?.updateChannelState(newChannel.state.channelState); + chatPersistenceClient + ?.updateChannelState(newChannel.state.channelState); newChannels[newChannel.cid] = newChannel; return newChannel; } @@ -938,8 +931,8 @@ class Client { logger.info( 'Disconnecting flushOfflineStorage: $flushChatPersistence; clearUser: $clearUser'); - await _chatPersistence?.disconnect(flush: flushChatPersistence); - _chatPersistence = null; + await chatPersistenceClient?.disconnect(flush: flushChatPersistence); + chatPersistenceClient = null; if (clearUser == true) { state.dispose(); @@ -1328,7 +1321,7 @@ class ClientState { void _listenChannelHidden() { _subscriptions.add(_client.on(EventType.channelHidden).listen((event) { - _client._chatPersistence?.deleteChannels([event.cid]); + _client.chatPersistenceClient?.deleteChannels([event.cid]); if (channels != null) { channels = channels..removeWhere((cid, ch) => cid == event.cid); } @@ -1353,7 +1346,7 @@ class ClientState { ) .listen((Event event) async { final eventChannel = event.channel; - await _client._chatPersistence?.deleteChannels([eventChannel.cid]); + await _client.chatPersistenceClient?.deleteChannels([eventChannel.cid]); if (channels != null) { channels = channels..remove(eventChannel.cid); } diff --git a/packages/dart_client/lib/src/db/stream_chat_persistence.dart b/packages/dart_client/lib/src/db/chat_persistence_client.dart similarity index 95% rename from packages/dart_client/lib/src/db/stream_chat_persistence.dart rename to packages/dart_client/lib/src/db/chat_persistence_client.dart index 40004825..c435df9e 100644 --- a/packages/dart_client/lib/src/db/stream_chat_persistence.dart +++ b/packages/dart_client/lib/src/db/chat_persistence_client.dart @@ -9,15 +9,12 @@ import 'package:stream_chat/src/models/read.dart'; import 'package:stream_chat/src/models/user.dart'; /// -abstract class StreamChatPersistence { - /// Creates a new connection to the database - Future connect({ - bool connectBackground = false, - bool logStatements = false, - }); +abstract class ChatPersistenceClient { + /// Creates a new connection to the client + Future connect(String name); - /// Closes the database instance - /// If [flush] is true, the database data will be deleted + /// Closes the client connection + /// If [flush] is true, the data will also be deleted Future disconnect({bool flush = false}); /// Get stored replies by messageId diff --git a/packages/dart_client/lib/src/notifications.dart b/packages/dart_client/lib/src/notifications.dart index e4cef9b5..82070fd2 100644 --- a/packages/dart_client/lib/src/notifications.dart +++ b/packages/dart_client/lib/src/notifications.dart @@ -1,12 +1,11 @@ import 'dart:convert'; -import 'package:logging/logging.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stream_chat/src/api/responses.dart'; import 'package:stream_chat/src/models/channel_model.dart'; import 'package:stream_chat/src/models/channel_state.dart'; import 'package:stream_chat/src/models/message.dart'; -import 'package:stream_chat_persistence/stream_chat_persistence.dart'; +import 'package:meta/meta.dart'; import 'client.dart'; import 'models/own_user.dart'; @@ -20,21 +19,13 @@ class NotificationService { ) async { if (message != null && client.persistenceEnabled) { if (client?.state?.channels == null) { - final sharedPreferences = await _getSharedPreferences(); - final userId = sharedPreferences.getString(KEY_USER_ID); - - final chatPersistence = StreamChatPersistenceImpl( - userId, - logger: Logger('💽'), - ); - await chatPersistence.connect(); - await chatPersistence.updateChannelState( + final chatPersistenceClient = client.chatPersistenceClient; + await chatPersistenceClient.updateChannelState( ChannelState( channel: channelModel, messages: [message], ), ); - await chatPersistence.disconnect(); } else { final channel = client.state.channels[channelModel.cid]; channel.state.updateChannelState( @@ -56,14 +47,11 @@ class NotificationService { /// Gets the message using the client without storing it in the offline storage /// It returns an object containing the information about the message and the channel - static Future getMessage(String messageId) async { + static Future _getMessage(String messageId) async { final sharedPreferences = await _getSharedPreferences(); final apiKey = sharedPreferences.getString(KEY_API_KEY); - final client = Client( - apiKey, - persistenceEnabled: false, - ); + final client = Client(apiKey); final userId = sharedPreferences.getString(KEY_USER_ID); final token = sharedPreferences.getString(KEY_TOKEN); @@ -74,30 +62,16 @@ class NotificationService { return res; } - /// Stores the message in the offline storage - static Future storeMessage(GetMessageResponse messageResponse) async { - final sharedPreferences = await _getSharedPreferences(); - final userId = sharedPreferences.getString(KEY_USER_ID); - - final chatPersistence = StreamChatPersistenceImpl( - userId, - logger: Logger('💽'), - ); - await chatPersistence.connect(); - - await chatPersistence.updateChannelState(ChannelState( - messages: [messageResponse.message], - channel: messageResponse.channel, - )); - - await chatPersistence.disconnect(); - } - - /// Gets the message using the client and stores it in the offline storage + /// Gets the message using the client and calls a [storeMessageHandler] callback + /// with the message if the user wants to save the message in db + /// /// It returns an object containing the information about the message and the channel - static Future getAndStoreMessage(String messageId) async { - final getMessageResponse = await getMessage(messageId); - await storeMessage(getMessageResponse); + static Future getAndStoreMessage({ + @required String messageId, + @required Future Function(GetMessageResponse) storeMessageHandler, + }) async { + final getMessageResponse = await _getMessage(messageId); + await storeMessageHandler(getMessageResponse); return getMessageResponse; } diff --git a/packages/dart_client/lib/stream_chat.dart b/packages/dart_client/lib/stream_chat.dart index 0ff1f871..00525b40 100644 --- a/packages/dart_client/lib/stream_chat.dart +++ b/packages/dart_client/lib/stream_chat.dart @@ -27,4 +27,4 @@ export './src/models/reaction.dart'; export './src/models/read.dart'; export './src/models/user.dart'; export './src/notifications.dart'; -export './src/db/stream_chat_persistence.dart'; \ No newline at end of file +export './src/db/chat_persistence_client.dart'; diff --git a/packages/flutter_widgets/example/lib/advanced_options_page.dart b/packages/flutter_widgets/example/lib/advanced_options_page.dart index 023ce32c..915bcfcb 100644 --- a/packages/flutter_widgets/example/lib/advanced_options_page.dart +++ b/packages/flutter_widgets/example/lib/advanced_options_page.dart @@ -8,9 +8,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'choose_user_page.dart'; +import 'main.dart'; import 'notifications_service.dart'; class AdvancedOptionsPage extends StatefulWidget { @@ -278,8 +280,7 @@ class _AdvancedOptionsPageState extends State { showLocalNotification: (!kIsWeb && Platform.isAndroid) ? showLocalNotification : null, - persistenceEnabled: true, - ); + )..chatPersistenceClient = chatPersistentClient; try { await client.setUser( @@ -320,72 +321,13 @@ class _AdvancedOptionsPageState extends State { return; } - if (!kIsWeb) { - initNotifications(client); - } - Navigator.pop(context); - Navigator.pop(context); - await Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) { - return FutureBuilder( - future: StreamingSharedPreferences.instance, - builder: (context, snapshot) { - if (!snapshot.hasData) { - return SizedBox(); - } - return PreferenceBuilder( - preference: snapshot.data.getInt( - 'theme', - defaultValue: 0, - ), - builder: (context, snapshot) => MaterialApp( - builder: (context, child) { - return StreamChat( - client: client, - child: Builder( - builder: (context) => - AnnotatedRegion< - SystemUiOverlayStyle>( - child: child, - value: SystemUiOverlayStyle( - systemNavigationBarColor: - StreamChatTheme.of(context) - .colorTheme - .white, - systemNavigationBarIconBrightness: - Theme.of(context) - .brightness == - Brightness.dark - ? Brightness.light - : Brightness.dark, - ), - ), - ), - ); - }, - debugShowCheckedModeBanner: false, - theme: ThemeData.light(), - darkTheme: ThemeData.dark(), - themeMode: { - -1: ThemeMode.dark, - 0: ThemeMode.system, - 1: ThemeMode.light, - }[snapshot], - onGenerateRoute: AppRoutes.generateRoute, - initialRoute: client.state.user == null - ? Routes.CHOOSE_USER - : Routes.HOME, - ), - ); - }, - ); - }, - ), - ); loading = false; + await Navigator.pushReplacementNamed( + context, + Routes.APP, + arguments: client, + ); } }, ), diff --git a/packages/flutter_widgets/example/lib/main.dart b/packages/flutter_widgets/example/lib/main.dart index 10d73997..caa11198 100644 --- a/packages/flutter_widgets/example/lib/main.dart +++ b/packages/flutter_widgets/example/lib/main.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'notifications_service.dart'; @@ -17,6 +18,11 @@ import 'routes/app_routes.dart'; import 'routes/routes.dart'; import 'search_text_field.dart'; +final chatPersistentClient = StreamChatPersistenceClient( + logLevel: Level.INFO, + connectionMode: ConnectionMode.background, +); + void main() async { WidgetsFlutterBinding.ensureInitialized(); final secureStorage = FlutterSecureStorage(); @@ -29,8 +35,7 @@ void main() async { logLevel: Level.INFO, showLocalNotification: (!kIsWeb && Platform.isAndroid) ? showLocalNotification : null, - persistenceEnabled: true, - ); + )..chatPersistenceClient = chatPersistentClient; if (userId != null) { final token = await secureStorage.read(key: kStreamToken); diff --git a/packages/flutter_widgets/example/lib/notifications_service.dart b/packages/flutter_widgets/example/lib/notifications_service.dart index 298ab3ab..0eeb9cc0 100644 --- a/packages/flutter_widgets/example/lib/notifications_service.dart +++ b/packages/flutter_widgets/example/lib/notifications_service.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:example/main.dart'; import 'package:flutter_apns/flutter_apns.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; @@ -36,8 +37,17 @@ Future backgroundHandler(Map notification) async { print('new notification ${notification}'); final messageId = notification['data']['id']; - final notificationData = - await NotificationService.getAndStoreMessage(messageId); + final notificationData = await NotificationService.getAndStoreMessage( + messageId: messageId, + storeMessageHandler: (messageResponse) { + return chatPersistentClient.updateChannelState( + ChannelState( + messages: [messageResponse.message], + channel: messageResponse.channel, + ), + ); + }, + ); showLocalNotification( notificationData.message, diff --git a/packages/flutter_widgets/example/lib/routes/app_routes.dart b/packages/flutter_widgets/example/lib/routes/app_routes.dart index 0c8a899f..e7c7e318 100644 --- a/packages/flutter_widgets/example/lib/routes/app_routes.dart +++ b/packages/flutter_widgets/example/lib/routes/app_routes.dart @@ -15,6 +15,12 @@ class AppRoutes { static Route generateRoute(RouteSettings settings) { final args = settings.arguments; switch (settings.name) { + case Routes.APP: + return MaterialPageRoute( + settings: const RouteSettings(name: Routes.APP), + builder: (_) { + return MyApp(args); + }); case Routes.HOME: return MaterialPageRoute( settings: const RouteSettings(name: Routes.HOME), diff --git a/packages/flutter_widgets/example/lib/routes/routes.dart b/packages/flutter_widgets/example/lib/routes/routes.dart index 0d2f4e5f..2280ca30 100644 --- a/packages/flutter_widgets/example/lib/routes/routes.dart +++ b/packages/flutter_widgets/example/lib/routes/routes.dart @@ -1,5 +1,6 @@ /// Define all the route names here class Routes { + static const String APP = '/app'; static const String HOME = '/home'; static const String CHOOSE_USER = '/choose_user'; static const String ADVANCED_OPTIONS = '/advance_options'; diff --git a/packages/flutter_widgets/example/pubspec.yaml b/packages/flutter_widgets/example/pubspec.yaml index fea15136..1a3f93df 100644 --- a/packages/flutter_widgets/example/pubspec.yaml +++ b/packages/flutter_widgets/example/pubspec.yaml @@ -9,8 +9,10 @@ environment: dependencies: flutter: sdk: flutter - stream_chat_flutter: + stream_chat_flutter: path: ../ + stream_chat_persistence: + path: ../../stream_chat_persistence flutter_apns: ^1.4.1 flutter_local_notifications: ^2.0.2 flutter_svg: ^0.19.1 diff --git a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart index 7415fdba..647314eb 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart @@ -11,7 +11,7 @@ class SharedDB { static constructOfflineStorage( String dbName, { - logStatements = false, + bool logStatements = false, }) { throw 'Unsupported Platform'; } diff --git a/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart index cdabf17f..4d35340b 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart @@ -1,5 +1,4 @@ import 'package:stream_chat/stream_chat.dart'; -import 'user_mapper.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; /// diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_impl.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart similarity index 79% rename from packages/stream_chat_persistence/lib/src/stream_chat_persistence_impl.dart rename to packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index 2d4caae8..72536b93 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_impl.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -3,18 +3,30 @@ import 'package:stream_chat/stream_chat.dart'; import 'db/moor_chat_database.dart'; import 'db/shared/shared_db.dart'; +/// Various connection modes on which [StreamChatPersistenceClient] can work +enum ConnectionMode { + /// Connects the [StreamChatPersistenceClient] on a regular/default isolate + regular, + + /// Connects the [StreamChatPersistenceClient] on a background isolate + background, +} + /// -class StreamChatPersistenceImpl extends StreamChatPersistence { +class StreamChatPersistenceClient extends ChatPersistenceClient { /// - StreamChatPersistenceImpl( - this._userId, { - Logger logger, - }) : _logger = logger, - assert(_userId != null); + StreamChatPersistenceClient({ + /// Connection mode on which the client will work + ConnectionMode connectionMode = ConnectionMode.regular, + Level logLevel = Level.WARNING, + }) : assert(connectionMode != null), + assert(logLevel != null), + _connectionMode = connectionMode, + _logger = Logger.detached('💽')..level = logLevel; - final String _userId; - final Logger _logger; MoorChatDatabase _db; + final Logger _logger; + final ConnectionMode _connectionMode; bool get _debugAssertConnected { assert(() { @@ -30,27 +42,22 @@ class StreamChatPersistenceImpl extends StreamChatPersistence { } @override - Future connect({ - bool connectBackground = false, - bool logStatements = false, - }) async { + Future connect(String name) async { if (_db != null) { throw Exception( 'An instance of StreamChatDatabase is already connected.\n' 'disconnect the previous instance before connecting again.', ); } - - final dbName = 'db_$_userId'; - if (connectBackground) { - _logger?.info('Connecting on background isolate'); - _db = await SharedDB.constructOfflineStorage( - dbName, - logStatements: logStatements, - ); - } else { - _logger?.info('Connecting on a regular isolate'); - _db = MoorChatDatabase(dbName, logStatements: logStatements); + switch (_connectionMode) { + case ConnectionMode.regular: + _logger.info('Connecting on a regular isolate'); + _db = MoorChatDatabase(name); + return; + case ConnectionMode.background: + _logger.info('Connecting on background isolate'); + _db = await SharedDB.constructOfflineStorage(name); + return; } } @@ -202,9 +209,9 @@ class StreamChatPersistenceImpl extends StreamChatPersistence { @override Future disconnect({bool flush = false}) async { if (_db != null) { - _logger?.info('Disconnecting'); + _logger.info('Disconnecting'); if (flush) { - _logger?.info('Flushing'); + _logger.info('Flushing'); await _db.batch((batch) { _db.allTables.forEach((table) { _db.delete(table).go(); diff --git a/packages/stream_chat_persistence/lib/stream_chat_persistence.dart b/packages/stream_chat_persistence/lib/stream_chat_persistence.dart index 3d58cb17..5f9aff5b 100644 --- a/packages/stream_chat_persistence/lib/stream_chat_persistence.dart +++ b/packages/stream_chat_persistence/lib/stream_chat_persistence.dart @@ -1,3 +1,3 @@ library stream_chat_persistence; -export 'src/stream_chat_persistence_impl.dart'; +export 'src/stream_chat_persistence_client.dart'; diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index 1ce6e604..a0c97c89 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -11,6 +11,7 @@ dependencies: moor: ^3.4.0 path: ^1.7.0 path_provider: ^1.6.27 + sqlite3_flutter_libs: ^0.3.0 stream_chat: path: ../dart_client From 00b561e0185616c71c5071764a60540da8da297b Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 27 Jan 2021 12:55:22 +0530 Subject: [PATCH 12/46] [LLC] Remove `stream_chat_persistence_client` dependency Signed-off-by: Sahil Kumar --- packages/dart_client/pubspec.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index 5eca907a..99d6794b 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -21,8 +21,6 @@ dependencies: rxdart: ^0.24.1 collection: ^1.14.12 pedantic: ^1.9.2 - stream_chat_persistence: - path: ../stream_chat_persistence dev_dependencies: build_runner: ^1.10.0 From e74a0d40ff61c5dc0e4fa554848651cd886910ed Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 27 Jan 2021 14:08:37 +0530 Subject: [PATCH 13/46] [LLC] Fix tests Signed-off-by: Sahil Kumar --- .../dart_client/test/src/client_test.dart | 50 ++----------------- 1 file changed, 3 insertions(+), 47 deletions(-) diff --git a/packages/dart_client/test/src/client_test.dart b/packages/dart_client/test/src/client_test.dart index 8f4dc41e..011789be 100644 --- a/packages/dart_client/test/src/client_test.dart +++ b/packages/dart_client/test/src/client_test.dart @@ -41,10 +41,7 @@ void main() { }); test('should create the object correctly', () { - final client = Client( - 'api-key', - persistenceEnabled: false, - ); + final client = Client('api-key'); expect(client.baseURL, 'chat-us-east-1.stream-io-api.com'); expect(client.apiKey, 'api-key'); @@ -60,7 +57,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, connectTimeout: Duration(seconds: 10), receiveTimeout: Duration(seconds: 12), logLevel: Level.INFO, @@ -82,10 +78,7 @@ void main() { })); test('Channel', () { - final client = Client( - 'test', - persistenceEnabled: false, - ); + final client = Client('test'); final Map data = {'test': 1}; final channelClient = client.channel('type', id: 'id', extraData: data); expect(channelClient.type, 'type'); @@ -103,7 +96,6 @@ void main() { final client = Client( 'api-key', httpClient: mockDio, - persistenceEnabled: false, ); final queryParams = { @@ -135,7 +127,6 @@ void main() { final client = Client( 'api-key', httpClient: mockDio, - persistenceEnabled: false, ); final queryFilter = { @@ -186,7 +177,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -215,7 +205,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -260,7 +249,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -287,7 +275,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -307,7 +294,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -323,10 +309,7 @@ void main() { }); test('devToken', () { - final client = Client( - 'api-key', - persistenceEnabled: false, - ); + final client = Client('api-key'); final token = client.devToken('test'); expect( @@ -344,7 +327,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -373,7 +355,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -417,7 +398,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -439,7 +419,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -455,7 +434,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -477,7 +455,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -503,7 +480,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -533,7 +509,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -555,7 +530,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -578,7 +552,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -600,7 +573,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -624,7 +596,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -646,7 +617,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -668,7 +638,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -696,7 +665,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -718,7 +686,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -740,7 +707,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -763,7 +729,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -789,7 +754,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: dioHttp, ); @@ -809,7 +773,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -833,7 +796,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: dioHttp, ); @@ -853,7 +815,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -877,7 +838,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: dioHttp, ); @@ -897,7 +857,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -922,7 +881,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: dioHttp, ); @@ -942,7 +900,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: mockDio, ); @@ -968,7 +925,6 @@ void main() { final client = Client( 'api-key', - persistenceEnabled: false, httpClient: dioHttp, ); From 3b9af052143858a34ed7f7009c983ffe49093cdf Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 27 Jan 2021 15:51:55 +0530 Subject: [PATCH 14/46] [StreamChatPersistence] Fix ownReactions userId bug Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/client.dart | 2 +- .../lib/src/db/chat_persistence_client.dart | 2 +- .../lib/src/dao/message_dao.dart | 4 ++-- .../lib/src/dao/reaction_dao.dart | 2 +- .../lib/src/db/moor_chat_database.dart | 14 ++++++++++---- .../lib/src/db/shared/native_db.dart | 8 +++++--- .../lib/src/db/shared/unsupported_db.dart | 4 ++-- .../lib/src/db/shared/web_db.dart | 6 ++++-- .../lib/src/stream_chat_persistence_client.dart | 6 +++--- 9 files changed, 29 insertions(+), 19 deletions(-) diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index 714acbd5..f2a6f0c0 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -456,7 +456,7 @@ class Client { wsConnectionStatus.value = ConnectionStatus.connecting; if (persistenceEnabled) { - await chatPersistenceClient.connect('db_${state.user.id}'); + await chatPersistenceClient.connect(state.user.id); } _ws = WebSocket( diff --git a/packages/dart_client/lib/src/db/chat_persistence_client.dart b/packages/dart_client/lib/src/db/chat_persistence_client.dart index c435df9e..c0cb68b2 100644 --- a/packages/dart_client/lib/src/db/chat_persistence_client.dart +++ b/packages/dart_client/lib/src/db/chat_persistence_client.dart @@ -11,7 +11,7 @@ import 'package:stream_chat/src/models/user.dart'; /// abstract class ChatPersistenceClient { /// Creates a new connection to the client - Future connect(String name); + Future connect(String userId); /// Closes the client connection /// If [flush] is true, the data will also be deleted diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart index 320cb022..ee779845 100644 --- a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -36,9 +36,9 @@ class MessageDao extends DatabaseAccessor final userEntity = rows.readTable(users); final msgEntity = rows.readTable(messages); final latestReactions = await _db.reactionDao.getReactions(msgEntity.id); - final ownReactions = await _db.reactionDao.getOwnReactions( + final ownReactions = await _db.reactionDao.getReactionsByUserId( msgEntity.id, - userEntity.id, + _db.userId, ); Message quotedMessage; if (msgEntity.quotedMessageId != null) { diff --git a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart index 8df23d44..dc6faefb 100644 --- a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart @@ -29,7 +29,7 @@ class ReactionDao extends DatabaseAccessor } /// - Future> getOwnReactions( + Future> getReactionsByUserId( String messageId, String userId, ) async { diff --git a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart index e32c3e3c..691961a7 100644 --- a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart @@ -10,12 +10,12 @@ import 'shared/shared_db.dart'; part 'moor_chat_database.g.dart'; LazyDatabase _openConnection( - String dbName, { + String userId, { logStatements = false, }) { return LazyDatabase(() async { return await SharedDB.constructDatabase( - dbName, + userId, logStatements: logStatements, ); }); @@ -44,19 +44,25 @@ LazyDatabase _openConnection( class MoorChatDatabase extends _$MoorChatDatabase { /// Instantiate a new database instance MoorChatDatabase( - String dbName, { + this._userId, { logStatements = false, }) : super(_openConnection( - dbName, + _userId, logStatements: logStatements, )); /// Instantiate a new database instance MoorChatDatabase.connect( + this._userId, this._isolate, DatabaseConnection connection, ) : super.connect(connection); + final String _userId; + + /// User id to which the database is connected + String get userId => _userId; + MoorIsolate _isolate; // you should bump this number whenever you change or add a table definition. diff --git a/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart index 198b9010..90f19de6 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart @@ -12,9 +12,10 @@ import '../moor_chat_database.dart'; class SharedDB { static Future constructDatabase( - String dbName, { + String userId, { bool logStatements = false, }) async { + final dbName = 'db_$userId'; if (Platform.isIOS || Platform.isAndroid) { final dir = await getApplicationDocumentsDirectory(); final path = join(dir.path, '$dbName.sqlite'); @@ -62,15 +63,16 @@ class SharedDB { } static Future constructOfflineStorage( - String dbName, { + String userId, { bool logStatements = false, }) async { + final dbName = 'db_$userId'; final isolate = await _createMoorIsolate( dbName, logStatements: logStatements, ); final connection = await isolate.connect(); - return MoorChatDatabase.connect(isolate, connection); + return MoorChatDatabase.connect(userId, isolate, connection); } } diff --git a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart index 647314eb..b014c833 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart @@ -3,14 +3,14 @@ class SharedDB { static constructDatabase( - String dbName, { + String userId, { bool logStatements = false, }) { throw 'Unsupported Platform'; } static constructOfflineStorage( - String dbName, { + String userId, { bool logStatements = false, }) { throw 'Unsupported Platform'; diff --git a/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart index 31b4f4b6..e30d08ea 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart @@ -6,16 +6,18 @@ import '../moor_chat_database.dart'; class SharedDB { static constructDatabase( - String dbName, { + String userId, { bool logStatements = false, }) async { + final dbName = 'db_$userId'; return WebDatabase(dbName, logStatements: logStatements); } static Future constructOfflineStorage( - String dbName, { + String userId, { bool logStatements = false, }) async { + final dbName = 'db_$userId'; return MoorChatDatabase(dbName, logStatements: logStatements); } } diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index 72536b93..cfcc5c68 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -42,7 +42,7 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { } @override - Future connect(String name) async { + Future connect(String userId) async { if (_db != null) { throw Exception( 'An instance of StreamChatDatabase is already connected.\n' @@ -52,11 +52,11 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { switch (_connectionMode) { case ConnectionMode.regular: _logger.info('Connecting on a regular isolate'); - _db = MoorChatDatabase(name); + _db = MoorChatDatabase(userId); return; case ConnectionMode.background: _logger.info('Connecting on background isolate'); - _db = await SharedDB.constructOfflineStorage(name); + _db = await SharedDB.constructOfflineStorage(userId); return; } } From e906f88975057ca972d624633fe3f1059b2f1dd5 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 27 Jan 2021 18:17:32 +0530 Subject: [PATCH 15/46] [Example] Minor fixes Signed-off-by: Sahil Kumar --- .../flutter_widgets/example/lib/advanced_options_page.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/flutter_widgets/example/lib/advanced_options_page.dart b/packages/flutter_widgets/example/lib/advanced_options_page.dart index 915bcfcb..25cbf51c 100644 --- a/packages/flutter_widgets/example/lib/advanced_options_page.dart +++ b/packages/flutter_widgets/example/lib/advanced_options_page.dart @@ -320,12 +320,11 @@ class _AdvancedOptionsPageState extends State { await client.disconnect(); return; } - - Navigator.pop(context); loading = false; - await Navigator.pushReplacementNamed( + await Navigator.pushNamedAndRemoveUntil( context, Routes.APP, + ModalRoute.withName(Routes.APP), arguments: client, ); } From f162b006ce62e47e7a61bdef9327dafdde4242c2 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 28 Jan 2021 13:32:48 +0530 Subject: [PATCH 16/46] [LLC] Replace `flutter_test` with `test` Signed-off-by: Sahil Kumar --- packages/dart_client/pubspec.yaml | 4 ++-- .../dart_client/test/src/client_test.dart | 2 +- .../test/src/models/action_test.dart | 2 +- .../test/src/models/attachment_test.dart | 2 +- .../test/src/models/channel_state_test.dart | 2 +- .../test/src/models/channel_test.dart | 2 +- .../test/src/models/command_test.dart | 2 +- .../test/src/models/device_test.dart | 2 +- .../test/src/models/event_test.dart | 2 +- .../test/src/models/member_test.dart | 2 +- .../test/src/models/message_test.dart | 2 +- .../test/src/models/reaction_test.dart | 2 +- .../test/src/models/read_test.dart | 2 +- .../test/src/models/serialization_test.dart | 2 +- .../test/src/models/user_test.dart | 2 +- packages/dart_client/test/version_test.dart | 2 +- .../test_integration/client_test.dart | 21 ------------------- 17 files changed, 17 insertions(+), 38 deletions(-) delete mode 100644 packages/dart_client/test_integration/client_test.dart diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index 99d6794b..024f9d90 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -21,10 +21,10 @@ dependencies: rxdart: ^0.24.1 collection: ^1.14.12 pedantic: ^1.9.2 + freezed: ^0.12.7 dev_dependencies: build_runner: ^1.10.0 json_serializable: ^3.3.0 - flutter_test: - sdk: flutter + test: ^1.15.7 mockito: ^4.1.1 diff --git a/packages/dart_client/test/src/client_test.dart b/packages/dart_client/test/src/client_test.dart index 011789be..299ccecb 100644 --- a/packages/dart_client/test/src/client_test.dart +++ b/packages/dart_client/test/src/client_test.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:dio/native_imp.dart'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:logging/logging.dart'; import 'package:mockito/mockito.dart'; import 'package:stream_chat/src/api/requests.dart'; diff --git a/packages/dart_client/test/src/models/action_test.dart b/packages/dart_client/test/src/models/action_test.dart index 2f75dddb..4859fcbe 100644 --- a/packages/dart_client/test/src/models/action_test.dart +++ b/packages/dart_client/test/src/models/action_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/action.dart'; void main() { diff --git a/packages/dart_client/test/src/models/attachment_test.dart b/packages/dart_client/test/src/models/attachment_test.dart index eaa8e9cc..b15458ad 100644 --- a/packages/dart_client/test/src/models/attachment_test.dart +++ b/packages/dart_client/test/src/models/attachment_test.dart @@ -2,7 +2,7 @@ import 'package:stream_chat/src/models/attachment.dart'; import 'package:stream_chat/src/models/action.dart'; import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; void main() { group('src/models/attachment', () { diff --git a/packages/dart_client/test/src/models/channel_state_test.dart b/packages/dart_client/test/src/models/channel_state_test.dart index 21ffb20c..b8ce3c80 100644 --- a/packages/dart_client/test/src/models/channel_state_test.dart +++ b/packages/dart_client/test/src/models/channel_state_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +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'; diff --git a/packages/dart_client/test/src/models/channel_test.dart b/packages/dart_client/test/src/models/channel_test.dart index 7197d083..69b18197 100644 --- a/packages/dart_client/test/src/models/channel_test.dart +++ b/packages/dart_client/test/src/models/channel_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/channel_model.dart'; void main() { diff --git a/packages/dart_client/test/src/models/command_test.dart b/packages/dart_client/test/src/models/command_test.dart index 51774b84..dc44f736 100644 --- a/packages/dart_client/test/src/models/command_test.dart +++ b/packages/dart_client/test/src/models/command_test.dart @@ -1,7 +1,7 @@ import 'package:stream_chat/src/models/command.dart'; import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; void main() { group('src/models/command', () { diff --git a/packages/dart_client/test/src/models/device_test.dart b/packages/dart_client/test/src/models/device_test.dart index 3f68929f..3f8de16e 100644 --- a/packages/dart_client/test/src/models/device_test.dart +++ b/packages/dart_client/test/src/models/device_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/device.dart'; void main() { diff --git a/packages/dart_client/test/src/models/event_test.dart b/packages/dart_client/test/src/models/event_test.dart index eb7d0f5a..db99b01a 100644 --- a/packages/dart_client/test/src/models/event_test.dart +++ b/packages/dart_client/test/src/models/event_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/event.dart'; import 'package:stream_chat/src/models/own_user.dart'; import 'package:stream_chat/stream_chat.dart'; diff --git a/packages/dart_client/test/src/models/member_test.dart b/packages/dart_client/test/src/models/member_test.dart index 121b470f..237f0030 100644 --- a/packages/dart_client/test/src/models/member_test.dart +++ b/packages/dart_client/test/src/models/member_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/member.dart'; import 'package:stream_chat/src/models/user.dart'; diff --git a/packages/dart_client/test/src/models/message_test.dart b/packages/dart_client/test/src/models/message_test.dart index de335c21..7541f722 100644 --- a/packages/dart_client/test/src/models/message_test.dart +++ b/packages/dart_client/test/src/models/message_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +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'; diff --git a/packages/dart_client/test/src/models/reaction_test.dart b/packages/dart_client/test/src/models/reaction_test.dart index 2e8fe5f8..8bc92081 100644 --- a/packages/dart_client/test/src/models/reaction_test.dart +++ b/packages/dart_client/test/src/models/reaction_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/reaction.dart'; import 'dart:convert'; diff --git a/packages/dart_client/test/src/models/read_test.dart b/packages/dart_client/test/src/models/read_test.dart index 83596170..b15ce66a 100644 --- a/packages/dart_client/test/src/models/read_test.dart +++ b/packages/dart_client/test/src/models/read_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/read.dart'; import 'package:stream_chat/src/models/user.dart'; diff --git a/packages/dart_client/test/src/models/serialization_test.dart b/packages/dart_client/test/src/models/serialization_test.dart index c20d0012..e8a2de3f 100644 --- a/packages/dart_client/test/src/models/serialization_test.dart +++ b/packages/dart_client/test/src/models/serialization_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/serialization.dart'; void main() { diff --git a/packages/dart_client/test/src/models/user_test.dart b/packages/dart_client/test/src/models/user_test.dart index a148ec6e..6100b218 100644 --- a/packages/dart_client/test/src/models/user_test.dart +++ b/packages/dart_client/test/src/models/user_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/models/user.dart'; void main() { diff --git a/packages/dart_client/test/version_test.dart b/packages/dart_client/test/version_test.dart index 698f79e1..ada2a85c 100644 --- a/packages/dart_client/test/version_test.dart +++ b/packages/dart_client/test/version_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/version.dart'; void prepareTest() { diff --git a/packages/dart_client/test_integration/client_test.dart b/packages/dart_client/test_integration/client_test.dart deleted file mode 100644 index 98ec39cf..00000000 --- a/packages/dart_client/test_integration/client_test.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:logging/logging.dart'; -import 'package:stream_chat/src/client.dart'; -import 'package:stream_chat/stream_chat.dart'; - -const API_KEY = '6xjf3dex3n7d'; -const TOKEN = - 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo'; - -void main() { - test('test', () async { - final client = Client( - '6xjf3dex3n7d', - logLevel: Level.INFO, - tokenProvider: (_) async => '', - ); - final user = User(id: 'wild-breeze-7'); - - await client.setGuestUser(user); - }); -} From c87c1d5368bdc18a708a3b0656de3d62c5bf00fa Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 28 Jan 2021 16:40:36 +0530 Subject: [PATCH 17/46] [LLC] Remove flutter dependency Signed-off-by: Sahil Kumar --- .../dart_client/lib/src/api/retry_policy.dart | 2 +- .../dart_client/lib/src/api/retry_queue.dart | 3 +- .../dart_client/lib/src/api/websocket.dart | 26 +++++++---- packages/dart_client/lib/src/client.dart | 46 +++++++++++-------- packages/dart_client/pubspec.yaml | 3 -- 5 files changed, 45 insertions(+), 35 deletions(-) diff --git a/packages/dart_client/lib/src/api/retry_policy.dart b/packages/dart_client/lib/src/api/retry_policy.dart index 43af3b8e..270d558c 100644 --- a/packages/dart_client/lib/src/api/retry_policy.dart +++ b/packages/dart_client/lib/src/api/retry_policy.dart @@ -1,4 +1,4 @@ -import 'package:flutter/foundation.dart'; +import 'package:meta/meta.dart'; import 'package:stream_chat/src/client.dart'; import 'package:stream_chat/src/exceptions.dart'; diff --git a/packages/dart_client/lib/src/api/retry_queue.dart b/packages/dart_client/lib/src/api/retry_queue.dart index 376854af..534d9c08 100644 --- a/packages/dart_client/lib/src/api/retry_queue.dart +++ b/packages/dart_client/lib/src/api/retry_queue.dart @@ -1,8 +1,7 @@ import 'dart:async'; import 'package:collection/collection.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/foundation.dart'; +import 'package:meta/meta.dart'; import 'package:logging/logging.dart'; import 'package:stream_chat/src/api/channel.dart'; import 'package:stream_chat/src/api/retry_policy.dart'; diff --git a/packages/dart_client/lib/src/api/websocket.dart b/packages/dart_client/lib/src/api/websocket.dart index bdd14a1e..a610c041 100644 --- a/packages/dart_client/lib/src/api/websocket.dart +++ b/packages/dart_client/lib/src/api/websocket.dart @@ -2,9 +2,9 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:meta/meta.dart'; import 'package:logging/logging.dart'; +import 'package:rxdart/rxdart.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; import '../models/event.dart'; @@ -99,9 +99,15 @@ class WebSocket { /// The timeout that uses the reconnection monitor timer to consider the connection unhealthy final int reconnectionMonitorTimeout; + final _connectionStatusController = + BehaviorSubject.seeded(ConnectionStatus.disconnected); + + set _connectionStatus(ConnectionStatus status) => + _connectionStatusController.add(status); + /// This notifies of connection status changes - final ValueNotifier connectionStatus = - ValueNotifier(ConnectionStatus.disconnected); + Stream get connectionStatusStream => + _connectionStatusController.stream; String _path; int _retryAttempt = 1; @@ -128,7 +134,7 @@ class WebSocket { } _connecting = true; - connectionStatus.value = ConnectionStatus.connecting; + _connectionStatus = ConnectionStatus.connecting; logger.info('connecting to $_path'); @@ -175,7 +181,7 @@ class WebSocket { _reconnecting = false; _lastEventAt = DateTime.now(); - connectionStatus.value = ConnectionStatus.connected; + _connectionStatus = ConnectionStatus.connected; _retryAttempt = 1; if (!_connectionCompleter.isCompleted) { @@ -199,7 +205,7 @@ class WebSocket { _connecting = false; if (!_reconnecting) { - connectionStatus.value = ConnectionStatus.disconnected; + _connectionStatus = ConnectionStatus.disconnected; } if (!_connectionCompleter.isCompleted) { @@ -258,7 +264,7 @@ class WebSocket { logger.info('reconnect'); if (!_reconnecting) { _reconnecting = true; - connectionStatus.value = ConnectionStatus.connecting; + _connectionStatus = ConnectionStatus.connecting; } _reconnectTimer(); @@ -300,8 +306,8 @@ class WebSocket { _cancelTimers(); _reconnecting = false; _manuallyDisconnected = true; - connectionStatus.value = ConnectionStatus.disconnected; - connectionStatus.dispose(); + _connectionStatus = ConnectionStatus.disconnected; + await _connectionStatusController.close(); return _channel.sink.close(); } } diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index f2a6f0c0..603b9b0e 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:dio/dio.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:meta/meta.dart'; import 'package:logging/logging.dart'; import 'package:rxdart/rxdart.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -93,8 +93,6 @@ class Client { this.backgroundKeepAlive = const Duration(minutes: 1), RetryPolicy retryPolicy, }) { - WidgetsFlutterBinding.ensureInitialized(); - _retryPolicy ??= RetryPolicy( retryTimeout: (Client client, int attempt, ApiError error) => Duration(seconds: 1 * attempt), @@ -180,7 +178,8 @@ class Client { static const _defaultBaseURL = 'chat-us-east-1.stream-io-api.com'; static const _tokenExpiredErrorCode = 40; - VoidCallback _connectionStatusListener; + StreamSubscription _connectionStatusSubscription; + Future Function(ConnectionStatus) _connectionStatusHandler; final BehaviorSubject _controller = BehaviorSubject(); @@ -188,10 +187,20 @@ class Client { /// Listen to this or use the [on] method to filter specific event types Stream get stream => _controller.stream; + final _wsConnectionStatusController = + BehaviorSubject.seeded(ConnectionStatus.disconnected); + + set _wsConnectionStatus(ConnectionStatus status) => + _wsConnectionStatusController.add(status); + + /// The current status value of the websocket connection + ConnectionStatus get wsConnectionStatus => + _wsConnectionStatusController.value; + /// This notifies the connection status of the websocket connection. /// Listen to this to get notified when the websocket tries to reconnect. - final ValueNotifier wsConnectionStatus = - ValueNotifier(ConnectionStatus.disconnected); + Stream get wsConnectionStatusStream => + _wsConnectionStatusController.stream; /// The current user token String token; @@ -275,8 +284,6 @@ class Client { httpClient.lock(); final userId = state.user.id; - _ws.connectionStatus.removeListener(_connectionStatusListener); - await _disconnect(); final newToken = await tokenProvider(userId); @@ -345,8 +352,8 @@ class Client { await _disconnect(); httpClient.close(); await _controller.close(); - state.channels.values.forEach((c) => c.dispose()); state.dispose(); + await _wsConnectionStatusController.close(); } Map get _httpHeaders => { @@ -443,17 +450,17 @@ class Client { /// Connect the client websocket Future connect() async { logger.info('connecting'); - if (wsConnectionStatus.value == ConnectionStatus.connecting) { + if (wsConnectionStatus == ConnectionStatus.connecting) { logger.warning('Already connecting'); throw Exception('Already connecting'); } - if (wsConnectionStatus.value == ConnectionStatus.connected) { + if (wsConnectionStatus == ConnectionStatus.connected) { logger.warning('Already connected'); throw Exception('Already connected'); } - wsConnectionStatus.value = ConnectionStatus.connecting; + _wsConnectionStatus = ConnectionStatus.connecting; if (persistenceEnabled) { await chatPersistenceClient.connect(state.user.id); @@ -476,15 +483,14 @@ class Client { logger: _detachedLogger('🔌'), ); - _connectionStatusListener = () async { - final value = _ws.connectionStatus.value; - wsConnectionStatus.value = value; + _connectionStatusHandler = (ConnectionStatus status) async { + _wsConnectionStatus = status; handleEvent(Event( type: EventType.connectionChanged, - online: value == ConnectionStatus.connected, + online: status == ConnectionStatus.connected, )); - if (value == ConnectionStatus.connected && + if (status == ConnectionStatus.connected && state.channels?.isNotEmpty == true) { unawaited(queryChannels(filter: { 'cid': { @@ -504,7 +510,8 @@ class Client { } }; - _ws.connectionStatus.addListener(_connectionStatusListener); + _connectionStatusSubscription = + _ws.connectionStatusStream.listen(_connectionStatusHandler); var event = await chatPersistenceClient?.getConnectionInfo(); @@ -588,7 +595,7 @@ class Client { logger.info('awaiting connection completer'); await _connectCompleter.future; } - if (wsConnectionStatus.value != ConnectionStatus.connected) { + if (wsConnectionStatus != ConnectionStatus.connected) { final errorMessage = 'You cannot use queryChannels without an active connection. Please call setUser to connect the client.'; if (persistenceEnabled) { @@ -946,6 +953,7 @@ class Client { logger.info('Client disconnecting'); await _ws?.disconnect(); + await _connectionStatusSubscription?.cancel(); } /// Requests users with a given query. diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index 024f9d90..c55753e6 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -9,8 +9,6 @@ environment: sdk: ">=2.7.0 <3.0.0" dependencies: - flutter: - sdk: flutter json_annotation: ^3.0.1 shared_preferences: ^0.5.7+3 logging: ^0.11.4 @@ -21,7 +19,6 @@ dependencies: rxdart: ^0.24.1 collection: ^1.14.12 pedantic: ^1.9.2 - freezed: ^0.12.7 dev_dependencies: build_runner: ^1.10.0 From a2a40b5f86c3e6078726d13e9b2191143480965f Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 28 Jan 2021 16:42:51 +0530 Subject: [PATCH 18/46] [LLC] Remove notification handling logics Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/client.dart | 15 --- .../dart_client/lib/src/notifications.dart | 99 ------------------- packages/dart_client/lib/stream_chat.dart | 1 - packages/dart_client/pubspec.yaml | 1 - 4 files changed, 116 deletions(-) delete mode 100644 packages/dart_client/lib/src/notifications.dart diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index 603b9b0e..988f0f8f 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -6,7 +6,6 @@ import 'package:dio/dio.dart'; import 'package:meta/meta.dart'; import 'package:logging/logging.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:stream_chat/src/api/retry_policy.dart'; import 'package:stream_chat/src/event_type.dart'; import 'package:stream_chat/src/models/channel_model.dart'; @@ -37,15 +36,6 @@ typedef DecoderFunction = T Function(Map); /// own backend server. Function requires a single [userId]. typedef TokenProvider = Future Function(String userId); -/// The key used to save the userId to sharedPreferences -const String KEY_USER_ID = 'KEY_USER_ID'; - -/// The key used to save the token to sharedPreferences -const String KEY_TOKEN = 'KEY_TOKEN'; - -/// The key used to save the apiKey to sharedPreferences -const String KEY_API_KEY = 'KEY_API_KEY'; - /// Provider used to send push notifications. enum PushProvider { /// Send notifications using Google's Firebase Cloud Messaging @@ -378,11 +368,6 @@ class Client { this.token = token; _anonymous = false; - final sharedPreferences = await SharedPreferences.getInstance(); - await sharedPreferences.setString(KEY_USER_ID, user.id); - await sharedPreferences.setString(KEY_TOKEN, token); - await sharedPreferences.setString(KEY_API_KEY, apiKey); - return connect().then((event) { _connectCompleter.complete(event); return event; diff --git a/packages/dart_client/lib/src/notifications.dart b/packages/dart_client/lib/src/notifications.dart deleted file mode 100644 index 82070fd2..00000000 --- a/packages/dart_client/lib/src/notifications.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'dart:convert'; - -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:stream_chat/src/api/responses.dart'; -import 'package:stream_chat/src/models/channel_model.dart'; -import 'package:stream_chat/src/models/channel_state.dart'; -import 'package:stream_chat/src/models/message.dart'; -import 'package:meta/meta.dart'; - -import 'client.dart'; -import 'models/own_user.dart'; - -/// Utility class to handle and show notifications -class NotificationService { - static Future _handleNotification( - Message message, - ChannelModel channelModel, - Client client, - ) async { - if (message != null && client.persistenceEnabled) { - if (client?.state?.channels == null) { - final chatPersistenceClient = client.chatPersistenceClient; - await chatPersistenceClient.updateChannelState( - ChannelState( - channel: channelModel, - messages: [message], - ), - ); - } else { - final channel = client.state.channels[channelModel.cid]; - channel.state.updateChannelState( - ChannelState( - channel: channelModel, - messages: [message], - ), - ); - } - } - } - - static SharedPreferences _sharedPreferences; - - static Future _getSharedPreferences() async { - _sharedPreferences ??= await SharedPreferences.getInstance(); - return _sharedPreferences; - } - - /// Gets the message using the client without storing it in the offline storage - /// It returns an object containing the information about the message and the channel - static Future _getMessage(String messageId) async { - final sharedPreferences = await _getSharedPreferences(); - final apiKey = sharedPreferences.getString(KEY_API_KEY); - - final client = Client(apiKey); - final userId = sharedPreferences.getString(KEY_USER_ID); - final token = sharedPreferences.getString(KEY_TOKEN); - - client.state.user = OwnUser(id: userId); - client.token = token; - - final res = await client.getMessage(messageId); - return res; - } - - /// Gets the message using the client and calls a [storeMessageHandler] callback - /// with the message if the user wants to save the message in db - /// - /// It returns an object containing the information about the message and the channel - static Future getAndStoreMessage({ - @required String messageId, - @required Future Function(GetMessageResponse) storeMessageHandler, - }) async { - final getMessageResponse = await _getMessage(messageId); - await storeMessageHandler(getMessageResponse); - return getMessageResponse; - } - - /// Handles the ios message queue generated by the Notification Service Extension - static Future handleIosMessageQueue(Client client) async { - final sharedPreferences = await SharedPreferences.getInstance(); - await sharedPreferences.reload(); - final messageQueue = sharedPreferences.getStringList('messageQueue'); - if (messageQueue != null) { - messageQueue.forEach((m) { - final jsonMessage = jsonDecode(m); - - final message = Message.fromJson(jsonMessage); - final channelModel = ChannelModel.fromJson(jsonMessage['channel']); - - _handleNotification( - message, - channelModel, - client, - ); - }); - await sharedPreferences.remove('messageQueue'); - } - } -} diff --git a/packages/dart_client/lib/stream_chat.dart b/packages/dart_client/lib/stream_chat.dart index 00525b40..590175c4 100644 --- a/packages/dart_client/lib/stream_chat.dart +++ b/packages/dart_client/lib/stream_chat.dart @@ -26,5 +26,4 @@ export './src/models/own_user.dart'; export './src/models/reaction.dart'; export './src/models/read.dart'; export './src/models/user.dart'; -export './src/notifications.dart'; export './src/db/chat_persistence_client.dart'; diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index c55753e6..e548fcae 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -10,7 +10,6 @@ environment: dependencies: json_annotation: ^3.0.1 - shared_preferences: ^0.5.7+3 logging: ^0.11.4 dio: ^3.0.10 web_socket_channel: ^1.1.0 From 6e5894eebeaeb2c735c8a024ec8e93e9ceee63a0 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 28 Jan 2021 17:23:59 +0530 Subject: [PATCH 19/46] [LLC] fix tests Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/api/websocket.dart | 3 +++ packages/dart_client/test/src/api/channel_test.dart | 2 +- packages/dart_client/test/src/api/requests_test.dart | 2 +- packages/dart_client/test/src/api/responses_test.dart | 2 +- packages/dart_client/test/src/api/web_socket_stub_test.dart | 2 +- packages/dart_client/test/src/api/websocket_test.dart | 4 ++-- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/dart_client/lib/src/api/websocket.dart b/packages/dart_client/lib/src/api/websocket.dart index a610c041..15102c6e 100644 --- a/packages/dart_client/lib/src/api/websocket.dart +++ b/packages/dart_client/lib/src/api/websocket.dart @@ -105,6 +105,9 @@ class WebSocket { set _connectionStatus(ConnectionStatus status) => _connectionStatusController.add(status); + /// The current connection status value + ConnectionStatus get connectionStatus => _connectionStatusController.value; + /// This notifies of connection status changes Stream get connectionStatusStream => _connectionStatusController.stream; diff --git a/packages/dart_client/test/src/api/channel_test.dart b/packages/dart_client/test/src/api/channel_test.dart index d83d6f12..3897eb04 100644 --- a/packages/dart_client/test/src/api/channel_test.dart +++ b/packages/dart_client/test/src/api/channel_test.dart @@ -1,6 +1,6 @@ import 'package:dio/dio.dart'; import 'package:dio/native_imp.dart'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:mockito/mockito.dart'; import 'package:stream_chat/src/api/requests.dart'; import 'package:stream_chat/src/client.dart'; diff --git a/packages/dart_client/test/src/api/requests_test.dart b/packages/dart_client/test/src/api/requests_test.dart index 3ad762a7..6f7324ed 100644 --- a/packages/dart_client/test/src/api/requests_test.dart +++ b/packages/dart_client/test/src/api/requests_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/stream_chat.dart'; void main() { diff --git a/packages/dart_client/test/src/api/responses_test.dart b/packages/dart_client/test/src/api/responses_test.dart index df576ba4..bfd4e5a7 100644 --- a/packages/dart_client/test/src/api/responses_test.dart +++ b/packages/dart_client/test/src/api/responses_test.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/api/responses.dart'; import 'package:stream_chat/src/models/device.dart'; import 'package:stream_chat/src/models/member.dart'; diff --git a/packages/dart_client/test/src/api/web_socket_stub_test.dart b/packages/dart_client/test/src/api/web_socket_stub_test.dart index 5de61b4a..e60706dc 100644 --- a/packages/dart_client/test/src/api/web_socket_stub_test.dart +++ b/packages/dart_client/test/src/api/web_socket_stub_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:stream_chat/src/api/web_socket_channel_stub.dart'; void main() { diff --git a/packages/dart_client/test/src/api/websocket_test.dart b/packages/dart_client/test/src/api/websocket_test.dart index e5a88bd8..d9486477 100644 --- a/packages/dart_client/test/src/api/websocket_test.dart +++ b/packages/dart_client/test/src/api/websocket_test.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:logging/logging.dart'; import 'package:mockito/mockito.dart'; import 'package:stream_chat/src/api/connection_status.dart'; @@ -67,7 +67,7 @@ void main() { await ws.connect(); verify(connectFunc(computedUrl)).called(1); - expect(ws.connectionStatus.value, ConnectionStatus.connected); + expect(ws.connectionStatus, ConnectionStatus.connected); await streamController.close(); timer.cancel(); From 86a122aa23f696742515d84454cb8ac08e388b20 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 28 Jan 2021 19:48:54 +0530 Subject: [PATCH 20/46] [LLC, Persistence] Add doc comments Signed-off-by: Sahil Kumar --- .../dart_client/lib/src/models/message.dart | 2 +- .../dart_client/lib/src/models/reaction.dart | 2 +- .../lib/src/converter/list_converter.dart | 3 ++- .../lib/src/converter/map_converter.dart | 3 ++- .../message_sending_status_converter.dart | 3 ++- .../lib/src/dao/channel_dao.dart | 6 ++--- .../lib/src/dao/channel_query_dao.dart | 4 ++-- .../lib/src/dao/connection_event_dao.dart | 4 ++-- .../lib/src/dao/member_dao.dart | 6 ++--- .../lib/src/dao/message_dao.dart | 18 +++++++++------ .../lib/src/dao/reaction_dao.dart | 14 +++++++----- .../lib/src/dao/read_dao.dart | 7 +++--- .../lib/src/dao/user_dao.dart | 6 ++--- .../lib/src/db/moor_chat_database.dart | 4 ++-- .../lib/src/entity/channel_queries.dart | 3 +++ .../lib/src/entity/channels.dart | 13 +++++++++++ .../lib/src/entity/connection_events.dart | 7 ++++++ .../lib/src/entity/members.dart | 12 ++++++++++ .../lib/src/entity/messages.dart | 22 +++++++++++++++++++ .../lib/src/entity/reactions.dart | 7 ++++++ .../lib/src/entity/reads.dart | 5 +++++ .../lib/src/entity/users.dart | 9 ++++++++ .../lib/src/mapper/channel_mapper.dart | 10 ++++----- .../lib/src/mapper/event_mapper.dart | 5 ++--- .../lib/src/mapper/member_mapper.dart | 9 ++++---- .../lib/src/mapper/message_mapper.dart | 8 +++---- .../lib/src/mapper/reaction_mapper.dart | 9 ++++---- .../lib/src/mapper/read_mapper.dart | 9 ++++---- .../lib/src/mapper/user_mapper.dart | 8 +++---- .../src/stream_chat_persistence_client.dart | 4 ++-- 30 files changed, 154 insertions(+), 68 deletions(-) diff --git a/packages/dart_client/lib/src/models/message.dart b/packages/dart_client/lib/src/models/message.dart index df188e35..a2eef86e 100644 --- a/packages/dart_client/lib/src/models/message.dart +++ b/packages/dart_client/lib/src/models/message.dart @@ -72,7 +72,7 @@ class Message { @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) final List ownReactions; - /// The ID of the parent message, if the message is a reply. + /// The ID of the parent message, if the message is a thread reply. final String parentId; /// A quoted reply message diff --git a/packages/dart_client/lib/src/models/reaction.dart b/packages/dart_client/lib/src/models/reaction.dart index fb0c4fad..9a4869f7 100644 --- a/packages/dart_client/lib/src/models/reaction.dart +++ b/packages/dart_client/lib/src/models/reaction.dart @@ -29,7 +29,7 @@ class Reaction { @JsonKey(includeIfNull: false, toJson: Serialization.readOnly) final String userId; - /// The score of the reaction (ie. number of reactions sent) + /// Reaction custom extraData @JsonKey(includeIfNull: false) final Map extraData; diff --git a/packages/stream_chat_persistence/lib/src/converter/list_converter.dart b/packages/stream_chat_persistence/lib/src/converter/list_converter.dart index 5d0a628f..d14642ce 100644 --- a/packages/stream_chat_persistence/lib/src/converter/list_converter.dart +++ b/packages/stream_chat_persistence/lib/src/converter/list_converter.dart @@ -2,7 +2,8 @@ import 'dart:convert'; import 'package:moor/moor.dart'; -/// +/// Maps a [List] of type [T] into a [String] understood +/// by the sqlite backend. class ListConverter extends TypeConverter, String> { @override List mapToDart(fromDb) { diff --git a/packages/stream_chat_persistence/lib/src/converter/map_converter.dart b/packages/stream_chat_persistence/lib/src/converter/map_converter.dart index 9fde0003..6e7a648d 100644 --- a/packages/stream_chat_persistence/lib/src/converter/map_converter.dart +++ b/packages/stream_chat_persistence/lib/src/converter/map_converter.dart @@ -2,7 +2,8 @@ import 'dart:convert'; import 'package:moor/moor.dart'; -/// +/// Maps a [Map] of type [String], [T] into a [String] understood +/// by the sqlite backend. class MapConverter extends TypeConverter, String> { @override Map mapToDart(fromDb) { diff --git a/packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart b/packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart index b8d92b82..75b006bb 100644 --- a/packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart +++ b/packages/stream_chat_persistence/lib/src/converter/message_sending_status_converter.dart @@ -1,7 +1,8 @@ import 'package:moor/moor.dart'; import 'package:stream_chat/stream_chat.dart'; -/// +/// Maps a [MessageSendingStatus] into a [int] understood +/// by the sqlite backend. class MessageSendingStatusConverter extends TypeConverter { @override diff --git a/packages/stream_chat_persistence/lib/src/dao/channel_dao.dart b/packages/stream_chat_persistence/lib/src/dao/channel_dao.dart index fa902f52..57ec95d3 100644 --- a/packages/stream_chat_persistence/lib/src/dao/channel_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/channel_dao.dart @@ -7,11 +7,11 @@ import '../mapper/mapper.dart'; part 'channel_dao.g.dart'; -/// +/// The Data Access Object for operations in [Channels] table. @UseDao(tables: [Channels, Users]) class ChannelDao extends DatabaseAccessor with _$ChannelDaoMixin { - /// + /// Creates a new channel dao instance ChannelDao(MoorChatDatabase db) : super(db); /// Get channel by cid @@ -44,7 +44,7 @@ class ChannelDao extends DatabaseAccessor .get(); } - /// + /// Updates all the channels using the new [channelList] data Future updateChannels(List channelList) { return batch( (it) => it.insertAll( diff --git a/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart b/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart index a42dd01e..1492420c 100644 --- a/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/channel_query_dao.dart @@ -10,11 +10,11 @@ import '../mapper/mapper.dart'; part 'channel_query_dao.g.dart'; -/// +/// The Data Access Object for operations in [ChannelQueries] table. @UseDao(tables: [ChannelQueries, Channels, Users]) class ChannelQueryDao extends DatabaseAccessor with _$ChannelQueryDaoMixin { - /// + /// Creates a new channel query dao instance ChannelQueryDao(this._db) : super(_db); final MoorChatDatabase _db; diff --git a/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart index baf91095..8d2033b2 100644 --- a/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/connection_event_dao.dart @@ -7,11 +7,11 @@ import '../mapper/mapper.dart'; part 'connection_event_dao.g.dart'; -/// +/// The Data Access Object for operations in [ConnectionEvents] table. @UseDao(tables: [ConnectionEvents, Users]) class ConnectionEventDao extends DatabaseAccessor with _$ConnectionEventDaoMixin { - /// + /// Creates a new connection event dao instance ConnectionEventDao(MoorChatDatabase db) : super(db); /// Get the latest stored connection event diff --git a/packages/stream_chat_persistence/lib/src/dao/member_dao.dart b/packages/stream_chat_persistence/lib/src/dao/member_dao.dart index f21ab334..c535af9a 100644 --- a/packages/stream_chat_persistence/lib/src/dao/member_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/member_dao.dart @@ -9,11 +9,11 @@ import '../mapper/mapper.dart'; part 'member_dao.g.dart'; -/// +/// The Data Access Object for operations in [Members] table. @UseDao(tables: [Members, Users]) class MemberDao extends DatabaseAccessor with _$MemberDaoMixin { - /// + /// Creates a new member dao instance MemberDao(MoorChatDatabase db) : super(db); /// Get all members where [members.channelCid] matches [cid] @@ -30,7 +30,7 @@ class MemberDao extends DatabaseAccessor }).get(); } - /// + /// Updates all the members using the new [memberList] data Future updateMembers(String cid, List memberList) async { return batch( (it) => it.insertAll( diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart index ee779845..0b6ba97c 100644 --- a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -7,11 +7,11 @@ import '../mapper/mapper.dart'; part 'message_dao.g.dart'; -/// +/// The Data Access Object for operations in [Messages] table. @UseDao(tables: [Messages, Users]) class MessageDao extends DatabaseAccessor with _$MessageDaoMixin { - /// + /// Creates a new message dao instance MessageDao(this._db) : super(_db); final MoorChatDatabase _db; @@ -52,7 +52,7 @@ class MessageDao extends DatabaseAccessor ); } - /// + /// Returns a single message by matching the [messages.id] with [id] Future getMessageById(String id) async { return await (select(messages).join([ leftOuterJoin(users, messages.userId.equalsExp(users.id)), @@ -62,7 +62,8 @@ class MessageDao extends DatabaseAccessor .getSingle(); } - /// + /// Returns all the messages of a particular thread by matching + /// [messages.channelCid] with [cid] Future> getThreadMessages(String cid) async { return Future.wait(await (select(messages).join([ leftOuterJoin(users, messages.userId.equalsExp(users.id)), @@ -74,7 +75,8 @@ class MessageDao extends DatabaseAccessor .get()); } - /// + /// Returns all the messages of a particular thread by matching + /// [messages.parentId] with [parentId] Future> getThreadMessagesByParentId( String parentId, { String lessThan, @@ -94,7 +96,8 @@ class MessageDao extends DatabaseAccessor return msgList; } - /// + /// Returns all the messages of a channel by matching + /// [messages.channelCid] with [parentId] Future> getMessagesByCid( String cid, { PaginationParams messagePagination, @@ -131,7 +134,8 @@ class MessageDao extends DatabaseAccessor return msgList; } - /// + /// Updates the message data of a particular channel with + /// the new [messageList] data Future updateMessages(String cid, List messageList) { return batch((batch) { batch.insertAll( diff --git a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart index dc6faefb..249bd011 100644 --- a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart @@ -7,14 +7,15 @@ import '../mapper/mapper.dart'; part 'reaction_dao.g.dart'; -/// +/// The Data Access Object for operations in [Reactions] table. @UseDao(tables: [Reactions, Users]) class ReactionDao extends DatabaseAccessor with _$ReactionDaoMixin { - /// + /// Creates a new reaction dao instance ReactionDao(MoorChatDatabase db) : super(db); - /// + /// Returns all the reactions of a particular message by matching + /// [reactions.messageId] with [messageId] Future> getReactions(String messageId) { return (select(reactions).join([ leftOuterJoin(users, reactions.userId.equalsExp(users.id)), @@ -28,7 +29,10 @@ class ReactionDao extends DatabaseAccessor }).get(); } - /// + /// Returns all the reactions of a particular message + /// added by a particular user by matching + /// [reactions.messageId] with [messageId] and + /// [reactions.userId] with [userId] Future> getReactionsByUserId( String messageId, String userId, @@ -37,7 +41,7 @@ class ReactionDao extends DatabaseAccessor return reactions.where((it) => it.userId == userId).toList(); } - /// + /// Updates the reactions data with the new [reactionList] data Future updateReactions(List reactionList) { return batch((it) { it.insertAll( diff --git a/packages/stream_chat_persistence/lib/src/dao/read_dao.dart b/packages/stream_chat_persistence/lib/src/dao/read_dao.dart index cd4da0f6..00af6b6d 100644 --- a/packages/stream_chat_persistence/lib/src/dao/read_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/read_dao.dart @@ -7,10 +7,10 @@ import '../mapper/mapper.dart'; part 'read_dao.g.dart'; -/// +/// The Data Access Object for operations in [Reads] table. @UseDao(tables: [Reads, Users]) class ReadDao extends DatabaseAccessor with _$ReadDaoMixin { - /// + /// Creates a new read dao instance ReadDao(MoorChatDatabase db) : super(db); /// Get all reads where [reads.channelCid] matches [cid] @@ -29,7 +29,8 @@ class ReadDao extends DatabaseAccessor with _$ReadDaoMixin { }).get(); } - /// + /// Updates the read data of a particular channel with + /// the new [readList] data Future updateReads(String cid, List readList) { return batch( (it) => it.insertAll( diff --git a/packages/stream_chat_persistence/lib/src/dao/user_dao.dart b/packages/stream_chat_persistence/lib/src/dao/user_dao.dart index 630a8252..795c7968 100644 --- a/packages/stream_chat_persistence/lib/src/dao/user_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/user_dao.dart @@ -6,13 +6,13 @@ import '../mapper/user_mapper.dart'; part 'user_dao.g.dart'; -/// +/// The Data Access Object for operations in [Users] table. @UseDao(tables: [Users]) class UserDao extends DatabaseAccessor with _$UserDaoMixin { - /// + /// Creates a new user dao instance UserDao(MoorChatDatabase db) : super(db); - /// + /// Updates the users data with the new [userList] data Future updateUsers(List userList) { return batch( (it) => it.insertAll( diff --git a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart index 691961a7..4230f278 100644 --- a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart @@ -21,7 +21,7 @@ LazyDatabase _openConnection( }); } -/// +/// A chat database implemented using moor @UseMoor(tables: [ Channels, Messages, @@ -42,7 +42,7 @@ LazyDatabase _openConnection( ConnectionEventDao, ]) class MoorChatDatabase extends _$MoorChatDatabase { - /// Instantiate a new database instance + /// Creates a new moor chat database instance MoorChatDatabase( this._userId, { logStatements = false, diff --git a/packages/stream_chat_persistence/lib/src/entity/channel_queries.dart b/packages/stream_chat_persistence/lib/src/entity/channel_queries.dart index fefdc925..301e3592 100644 --- a/packages/stream_chat_persistence/lib/src/entity/channel_queries.dart +++ b/packages/stream_chat_persistence/lib/src/entity/channel_queries.dart @@ -1,9 +1,12 @@ import 'package:moor/moor.dart'; +/// Represents a [ChannelQueries] table in [MoorChatDatabase]. @DataClassName('ChannelQueryEntity') class ChannelQueries extends Table { + /// The unique hash of this query TextColumn get queryHash => text()(); + /// The channel cid of this query TextColumn get channelCid => text()(); @override diff --git a/packages/stream_chat_persistence/lib/src/entity/channels.dart b/packages/stream_chat_persistence/lib/src/entity/channels.dart index 9f652ed1..38a40081 100644 --- a/packages/stream_chat_persistence/lib/src/entity/channels.dart +++ b/packages/stream_chat_persistence/lib/src/entity/channels.dart @@ -1,30 +1,43 @@ import 'package:moor/moor.dart'; import 'package:stream_chat_persistence/src/converter/map_converter.dart'; +/// Represents a [Channels] table in [MoorChatDatabase]. @DataClassName('ChannelEntity') class Channels extends Table { + /// The id of this channel TextColumn get id => text()(); + /// The type of this channel TextColumn get type => text()(); + /// The cid of this channel TextColumn get cid => text()(); + /// The channel configuration data TextColumn get config => text().map(MapConverter())(); + /// True if this channel entity is frozen BoolColumn get frozen => boolean().withDefault(Constant(false))(); + /// The date of the last message DateTimeColumn get lastMessageAt => dateTime().nullable()(); + /// The date of channel creation DateTimeColumn get createdAt => dateTime().nullable()(); + /// The date of the last channel update DateTimeColumn get updatedAt => dateTime().nullable()(); + /// The date of channel deletion DateTimeColumn get deletedAt => dateTime().nullable()(); + /// The count of this channel members IntColumn get memberCount => integer().nullable()(); + /// The id of the user that created this channel TextColumn get createdById => text().nullable()(); + /// Map of custom channel extraData TextColumn get extraData => text().nullable().map(MapConverter())(); @override diff --git a/packages/stream_chat_persistence/lib/src/entity/connection_events.dart b/packages/stream_chat_persistence/lib/src/entity/connection_events.dart index 3ca4592e..7caa0407 100644 --- a/packages/stream_chat_persistence/lib/src/entity/connection_events.dart +++ b/packages/stream_chat_persistence/lib/src/entity/connection_events.dart @@ -1,18 +1,25 @@ import 'package:moor/moor.dart'; import 'package:stream_chat_persistence/src/converter/map_converter.dart'; +/// Represents a [ConnectionEvents] table in [MoorChatDatabase]. @DataClassName('ConnectionEventEntity') class ConnectionEvents extends Table { + /// event id IntColumn get id => integer()(); + /// User object of the current user TextColumn get ownUser => text().nullable().map(MapConverter())(); + /// The number of unread messages for current user IntColumn get totalUnreadCount => integer().nullable()(); + /// User total unread channels for current user IntColumn get unreadChannels => integer().nullable()(); + /// DateTime of the last event DateTimeColumn get lastEventAt => dateTime().nullable()(); + /// DateTime of the last sync DateTimeColumn get lastSyncAt => dateTime().nullable()(); @override diff --git a/packages/stream_chat_persistence/lib/src/entity/members.dart b/packages/stream_chat_persistence/lib/src/entity/members.dart index 39e224e0..9eafd4aa 100644 --- a/packages/stream_chat_persistence/lib/src/entity/members.dart +++ b/packages/stream_chat_persistence/lib/src/entity/members.dart @@ -1,28 +1,40 @@ import 'package:moor/moor.dart'; +/// Represents a [Members] table in [MoorChatDatabase]. @DataClassName('MemberEntity') class Members extends Table { + /// The interested user id TextColumn get userId => text()(); + /// The channel cid of which this user is part of TextColumn get channelCid => text().customConstraint('REFERENCES channels(cid) ON DELETE CASCADE')(); + /// The role of the user in the channel TextColumn get role => text().nullable()(); + /// The date on which the user accepted the invite to the channel DateTimeColumn get inviteAcceptedAt => dateTime().nullable()(); + /// The date on which the user rejected the invite to the channel DateTimeColumn get inviteRejectedAt => dateTime().nullable()(); + /// True if the user has been invited to the channel BoolColumn get invited => boolean().nullable()(); + /// True if the member is banned from the channel BoolColumn get banned => boolean().nullable()(); + /// True if the member is shadow banned from the channel BoolColumn get shadowBanned => boolean().nullable()(); + /// True if the user is a moderator of the channel BoolColumn get isModerator => boolean().nullable()(); + /// The date of creation DateTimeColumn get createdAt => dateTime()(); + /// The last date of update DateTimeColumn get updatedAt => dateTime().nullable()(); @override diff --git a/packages/stream_chat_persistence/lib/src/entity/messages.dart b/packages/stream_chat_persistence/lib/src/entity/messages.dart index 10c98315..8a151ae6 100644 --- a/packages/stream_chat_persistence/lib/src/entity/messages.dart +++ b/packages/stream_chat_persistence/lib/src/entity/messages.dart @@ -3,50 +3,72 @@ import 'package:stream_chat_persistence/src/converter/list_converter.dart'; import 'package:stream_chat_persistence/src/converter/map_converter.dart'; import 'package:stream_chat_persistence/src/converter/message_sending_status_converter.dart'; +/// Represents a [Messages] table in [MoorChatDatabase]. @DataClassName('MessageEntity') class Messages extends Table { + /// The message id TextColumn get id => text()(); + /// The text of this message TextColumn get messageText => text().nullable()(); + /// The list of attachments, either provided by the user + /// or generated from a command or as a result of URL scraping. TextColumn get attachments => text().nullable().map(ListConverter())(); + /// The status of a sending message IntColumn get status => integer().nullable().map(MessageSendingStatusConverter())(); + /// The message type TextColumn get type => text().nullable()(); + /// The list of user mentioned in the message TextColumn get mentionedUsers => text().nullable().map(ListConverter())(); + /// A map describing the count of number of every reaction TextColumn get reactionCounts => text().nullable().map(MapConverter())(); + /// A map describing the count of score of every reaction TextColumn get reactionScores => text().nullable().map(MapConverter())(); + /// The ID of the parent message, if the message is a thread reply. TextColumn get parentId => text().nullable()(); + /// The ID of the quoted message, if the message is a quoted reply. TextColumn get quotedMessageId => text().nullable()(); + /// Number of replies for this message. IntColumn get replyCount => integer().nullable()(); + /// Check if this message needs to show in the channel. BoolColumn get showInChannel => boolean().nullable()(); + /// If true the message is shadowed BoolColumn get shadowed => boolean().nullable()(); + /// A used command name. TextColumn get command => text().nullable()(); + /// The DateTime when the message was created. DateTimeColumn get createdAt => dateTime()(); + /// The DateTime when the message was updated last time. DateTimeColumn get updatedAt => dateTime().nullable()(); + /// The DateTime when the message was deleted. DateTimeColumn get deletedAt => dateTime().nullable()(); + /// Id of the User who sent the message TextColumn get userId => text().nullable()(); + /// The channel cid of which this message is part of TextColumn get channelCid => text().nullable().customConstraint( 'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE')(); + /// Message custom extraData TextColumn get extraData => text().nullable().map(MapConverter())(); @override diff --git a/packages/stream_chat_persistence/lib/src/entity/reactions.dart b/packages/stream_chat_persistence/lib/src/entity/reactions.dart index a20ffbeb..b7e6342f 100644 --- a/packages/stream_chat_persistence/lib/src/entity/reactions.dart +++ b/packages/stream_chat_persistence/lib/src/entity/reactions.dart @@ -1,19 +1,26 @@ import 'package:moor/moor.dart'; import 'package:stream_chat_persistence/src/converter/map_converter.dart'; +/// Represents a [Reactions] table in [MoorChatDatabase]. @DataClassName('ReactionEntity') class Reactions extends Table { + /// The id of the user that sent the reaction TextColumn get userId => text()(); + /// The messageId to which the reaction belongs TextColumn get messageId => text().customConstraint('REFERENCES messages(id) ON DELETE CASCADE')(); + /// The type of the reaction TextColumn get type => text()(); + /// The DateTime on which the reaction is created DateTimeColumn get createdAt => dateTime()(); + /// The score of the reaction (ie. number of reactions sent) IntColumn get score => integer().nullable()(); + /// Reaction custom extraData TextColumn get extraData => text().nullable().map(MapConverter())(); @override diff --git a/packages/stream_chat_persistence/lib/src/entity/reads.dart b/packages/stream_chat_persistence/lib/src/entity/reads.dart index c36dceef..4b9ce6fb 100644 --- a/packages/stream_chat_persistence/lib/src/entity/reads.dart +++ b/packages/stream_chat_persistence/lib/src/entity/reads.dart @@ -1,14 +1,19 @@ import 'package:moor/moor.dart'; +/// Represents a [Reads] table in [MoorChatDatabase]. @DataClassName('ReadEntity') class Reads extends Table { + /// Date of the read event DateTimeColumn get lastRead => dateTime()(); + /// Id of the User who sent the event TextColumn get userId => text()(); + /// The channel cid of which this read belongs TextColumn get channelCid => text().customConstraint('REFERENCES channels(cid) ON DELETE CASCADE')(); + /// Number of unread messages IntColumn get unreadMessages => integer().nullable()(); @override diff --git a/packages/stream_chat_persistence/lib/src/entity/users.dart b/packages/stream_chat_persistence/lib/src/entity/users.dart index 4beee396..4916ad28 100644 --- a/packages/stream_chat_persistence/lib/src/entity/users.dart +++ b/packages/stream_chat_persistence/lib/src/entity/users.dart @@ -1,22 +1,31 @@ import 'package:moor/moor.dart'; import 'package:stream_chat_persistence/src/converter/map_converter.dart'; +/// Represents a [Users] table in [MoorChatDatabase]. @DataClassName('UserEntity') class Users extends Table { + /// User id TextColumn get id => text()(); + /// User role TextColumn get role => text().nullable()(); + /// Date of user creation DateTimeColumn get createdAt => dateTime().nullable()(); + /// Date of last user update DateTimeColumn get updatedAt => dateTime().nullable()(); + /// Date of last user connection DateTimeColumn get lastActive => dateTime().nullable()(); + /// True if user is online BoolColumn get online => boolean().nullable()(); + /// True if user is banned from the chat BoolColumn get banned => boolean().nullable()(); + /// Map of custom user extraData TextColumn get extraData => text().nullable().map(MapConverter())(); @override diff --git a/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart index 4d35340b..7d0e152f 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart @@ -1,9 +1,9 @@ import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; -/// +/// Useful mapping functions for [ChannelEntity] extension ChannelEntityX on ChannelEntity { - /// + /// Maps a [ChannelEntity] into [ChannelModel] ChannelModel toChannelModel({User createdBy}) { final config = ChannelConfig.fromJson(this.config ?? {}); return ChannelModel( @@ -22,7 +22,7 @@ extension ChannelEntityX on ChannelEntity { ); } - /// + /// Maps a [ChannelEntity] into [ChannelState] ChannelState toChannelState({ User createdBy, List members, @@ -38,9 +38,9 @@ extension ChannelEntityX on ChannelEntity { } } -/// +/// Useful mapping functions for [ChannelModel] extension ChannelModelX on ChannelModel { - /// + /// Maps a [ChannelModel] into [ChannelEntity] ChannelEntity toEntity() { return ChannelEntity( id: id, diff --git a/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart index 9746dc20..7bc1739c 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/event_mapper.dart @@ -1,10 +1,9 @@ import 'package:stream_chat/stream_chat.dart'; -import 'user_mapper.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; -/// +/// Useful mapping functions for [ConnectionEventEntity] extension ConnectionEventX on ConnectionEventEntity { - /// + /// Maps a [ConnectionEventEntity] into [Event] Event toEvent() { return Event( me: ownUser != null ? OwnUser.fromJson(ownUser) : null, diff --git a/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart index 42f463ba..2d32c9f1 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/member_mapper.dart @@ -1,10 +1,9 @@ import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; -import 'user_mapper.dart'; -/// +/// Useful mapping functions for [MemberEntity] extension MemberEntityX on MemberEntity { - /// + /// Maps a [MemberEntity] into [Member] Member toMember({User user}) { return Member( user: user, @@ -22,9 +21,9 @@ extension MemberEntityX on MemberEntity { } } -/// +/// Useful mapping functions for [Member] extension MemberX on Member { - /// + /// Maps a [Member] into [MemberEntity] MemberEntity toEntity({String cid}) { return MemberEntity( userId: user?.id, diff --git a/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart index 4ea001a1..510675e6 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart @@ -3,9 +3,9 @@ import 'dart:convert'; import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; -/// +/// Useful mapping functions for [MessageEntity] extension MessageEntityX on MessageEntity { - /// + /// Maps a [MessageEntity] into [Message] Message toMessage({ User user, List latestReactions, @@ -41,9 +41,9 @@ extension MessageEntityX on MessageEntity { } } -/// +/// Useful mapping functions for [Message] extension MessageX on Message { - /// + /// Maps a [Message] into [MessageEntity] MessageEntity toEntity({String cid}) { return MessageEntity( id: id, diff --git a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart index d468d11c..407816be 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart @@ -1,9 +1,9 @@ import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; -/// +/// Useful mapping functions for [ReactionEntity] extension ReactionEntityX on ReactionEntity { - /// + /// Maps a [ReactionEntity] into [Reaction] Reaction toReaction({User user}) { return Reaction( extraData: extraData, @@ -17,10 +17,9 @@ extension ReactionEntityX on ReactionEntity { } } -/// +/// Useful mapping functions for [Reaction] extension ReactionX on Reaction { - /// - ReactionEntity toEntity() { + ReactionEntity toEntity() { return ReactionEntity( extraData: extraData, type: type, diff --git a/packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart index 0f9ea560..c79cf8d5 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/read_mapper.dart @@ -1,10 +1,9 @@ import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; -import 'user_mapper.dart'; -/// +/// Useful mapping functions for [ReadEntity] extension ReadEntityX on ReadEntity { - /// + /// Maps a [ReadEntity] into [Read] Read toRead({User user}) { return Read( user: user, @@ -14,9 +13,9 @@ extension ReadEntityX on ReadEntity { } } -/// +/// Useful mapping functions for [Read] extension ReadX on Read { - /// + /// Maps a [Read] into [ReadEntity] ReadEntity toEntity({String cid}) { return ReadEntity( lastRead: lastRead, diff --git a/packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart index cb775ab7..b1e53786 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/user_mapper.dart @@ -1,9 +1,9 @@ import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; -/// +/// Useful mapping functions for [UserEntity] extension UserEntityX on UserEntity { - /// + /// Maps a [UserEntity] into [User] User toUser() { return User( id: id, @@ -18,9 +18,9 @@ extension UserEntityX on UserEntity { } } -/// +/// Useful mapping functions for [User] extension UserX on User { - /// + /// Maps a [User] into [UserEntity] UserEntity toEntity() { return UserEntity( id: id, diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index cfcc5c68..c0aceff5 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -12,9 +12,9 @@ enum ConnectionMode { background, } -/// +/// A [MoorChatDatabase] based implementation of the [ChatPersistenceClient] class StreamChatPersistenceClient extends ChatPersistenceClient { - /// + /// Creates a new instance of the stream chat persistence client StreamChatPersistenceClient({ /// Connection mode on which the client will work ConnectionMode connectionMode = ConnectionMode.regular, From db275bfa7115f9b56910d2af8e9190f2a3882fc5 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 28 Jan 2021 19:51:48 +0530 Subject: [PATCH 21/46] [LLC, Persistence] Use pagination options instead of single filter Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/api/channel.dart | 2 +- .../dart_client/lib/src/db/chat_persistence_client.dart | 2 +- .../stream_chat_persistence/lib/src/dao/message_dao.dart | 6 +++--- .../lib/src/stream_chat_persistence_client.dart | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/dart_client/lib/src/api/channel.dart b/packages/dart_client/lib/src/api/channel.dart index 3ba9aa1f..45dd5da8 100644 --- a/packages/dart_client/lib/src/api/channel.dart +++ b/packages/dart_client/lib/src/api/channel.dart @@ -489,7 +489,7 @@ class Channel { }) async { final cachedReplies = await _client.chatPersistenceClient?.getReplies( parentId, - lessThan: options?.lessThan, + options: options, ); if (cachedReplies != null && cachedReplies.isNotEmpty) { state?.updateThreadInfo(parentId, cachedReplies); diff --git a/packages/dart_client/lib/src/db/chat_persistence_client.dart b/packages/dart_client/lib/src/db/chat_persistence_client.dart index c0cb68b2..19a9164e 100644 --- a/packages/dart_client/lib/src/db/chat_persistence_client.dart +++ b/packages/dart_client/lib/src/db/chat_persistence_client.dart @@ -20,7 +20,7 @@ abstract class ChatPersistenceClient { /// Get stored replies by messageId Future> getReplies( String parentId, { - String lessThan, + PaginationParams options, }); /// Get stored connection event diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart index 0b6ba97c..57aa055d 100644 --- a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -79,7 +79,7 @@ class MessageDao extends DatabaseAccessor /// [messages.parentId] with [parentId] Future> getThreadMessagesByParentId( String parentId, { - String lessThan, + PaginationParams options, }) async { final msgList = await Future.wait(await (select(messages).join([ innerJoin(users, messages.userId.equalsExp(users.id)), @@ -89,8 +89,8 @@ class MessageDao extends DatabaseAccessor .map(_messageFromJoinRow) .get()); - if (lessThan != null) { - final lessThanIndex = msgList.indexWhere((m) => m.id == lessThan); + if (options?.lessThan != null) { + final lessThanIndex = msgList.indexWhere((m) => m.id == options.lessThan); msgList.removeRange(lessThanIndex, msgList.length); } return msgList; diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index c0aceff5..49a59423 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -142,11 +142,11 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { @override Future> getReplies( String parentId, { - String lessThan, + PaginationParams options, }) { return _db.messageDao.getThreadMessagesByParentId( parentId, - lessThan: lessThan, + options: options, ); } From d5c57f3cb5db43deb622af05e2e5e99ae74ae296 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 13:33:45 +0530 Subject: [PATCH 22/46] [UI-KIT] Add connection status builder Signed-off-by: Sahil Kumar --- .../lib/group_chat_details_screen.dart | 200 ++++----- .../example/lib/new_chat_screen.dart | 5 +- .../example/lib/new_group_chat_screen.dart | 406 +++++++++--------- .../lib/src/channel_header.dart | 7 +- .../flutter_widgets/lib/src/channel_info.dart | 7 +- .../lib/src/channel_list_header.dart | 11 +- .../lib/src/connection_status_builder.dart | 55 +++ .../lib/src/message_list_view.dart | 347 ++++++++------- .../lib/stream_chat_flutter.dart | 1 + packages/flutter_widgets/pubspec.yaml | 2 - .../stream_chat_flutter_core/pubspec.yaml | 4 +- 11 files changed, 546 insertions(+), 499 deletions(-) create mode 100644 packages/flutter_widgets/lib/src/connection_status_builder.dart diff --git a/packages/flutter_widgets/example/lib/group_chat_details_screen.dart b/packages/flutter_widgets/example/lib/group_chat_details_screen.dart index 83ec94bb..afc9d12f 100644 --- a/packages/flutter_widgets/example/lib/group_chat_details_screen.dart +++ b/packages/flutter_widgets/example/lib/group_chat_details_screen.dart @@ -150,116 +150,116 @@ class _GroupChatDetailsScreenState extends State { ), ], ), - body: ValueListenableBuilder( - valueListenable: StreamChat.of(context).client.wsConnectionStatus, - builder: (context, status, _) { - String statusString = ''; - bool showStatus = true; + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; - switch (status) { - case ConnectionStatus.connected: - statusString = 'Connected'; - showStatus = false; - break; - case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; - break; - case ConnectionStatus.disconnected: - statusString = 'Disconnected'; - break; - } - return InfoTile( - showMessage: showStatus, - tileAnchor: Alignment.topCenter, - childAnchor: Alignment.topCenter, - message: statusString, - child: Column( - children: [ - Container( - width: double.maxFinite, - decoration: BoxDecoration( - gradient: - StreamChatTheme.of(context).colorTheme.bgGradient, + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } + return InfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: Column( + children: [ + Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, ), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 8, - ), - child: Text( - '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', - style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.grey, - ), + child: Text( + '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', + style: TextStyle( + color: StreamChatTheme.of(context).colorTheme.grey, ), ), ), - Expanded( - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: ListView.separated( - itemCount: _selectedUsers.length + 1, - separatorBuilder: (_, __) => Container( - height: 1, - color: StreamChatTheme.of(context) - .colorTheme - .greyWhisper, - ), - itemBuilder: (_, index) { - if (index == _selectedUsers.length) { - return Container( - height: 1, + ), + Expanded( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: ListView.separated( + itemCount: _selectedUsers.length + 1, + separatorBuilder: (_, __) => Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ), + itemBuilder: (_, index) { + if (index == _selectedUsers.length) { + return Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ); + } + final user = _selectedUsers[index]; + return ListTile( + key: ObjectKey(user), + leading: UserAvatar( + user: user, + constraints: BoxConstraints.tightFor( + width: 40, + height: 40, + ), + ), + title: Text( + user.name, + style: TextStyle(fontWeight: FontWeight.bold), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + trailing: IconButton( + icon: Icon( + Icons.clear_rounded, color: StreamChatTheme.of(context) .colorTheme - .greyWhisper, - ); - } - final user = _selectedUsers[index]; - return ListTile( - key: ObjectKey(user), - leading: UserAvatar( - user: user, - constraints: BoxConstraints.tightFor( - width: 40, - height: 40, - ), + .black, ), - title: Text( - user.name, - style: TextStyle(fontWeight: FontWeight.bold), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - trailing: IconButton( - icon: Icon( - Icons.clear_rounded, - color: StreamChatTheme.of(context) - .colorTheme - .black, - ), - padding: const EdgeInsets.all(0), - splashRadius: 24, - onPressed: () { - setState(() { - _selectedUsers.remove(user); - }); - if (_selectedUsers.isEmpty) { - Navigator.pop(context, _selectedUsers); - } - }, - ), - ); - }, - ), + padding: const EdgeInsets.all(0), + splashRadius: 24, + onPressed: () { + setState(() { + _selectedUsers.remove(user); + }); + if (_selectedUsers.isEmpty) { + Navigator.pop(context, _selectedUsers); + } + }, + ), + ); + }, ), ), - ], - ), - ); - }), + ), + ], + ), + ); + }, + ), ), ); } diff --git a/packages/flutter_widgets/example/lib/new_chat_screen.dart b/packages/flutter_widgets/example/lib/new_chat_screen.dart index baddd570..7f47e871 100644 --- a/packages/flutter_widgets/example/lib/new_chat_screen.dart +++ b/packages/flutter_widgets/example/lib/new_chat_screen.dart @@ -134,9 +134,8 @@ class _NewChatScreenState extends State { ), centerTitle: true, ), - body: ValueListenableBuilder( - valueListenable: StreamChat.of(context).client.wsConnectionStatus, - builder: (context, status, _) { + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; diff --git a/packages/flutter_widgets/example/lib/new_group_chat_screen.dart b/packages/flutter_widgets/example/lib/new_group_chat_screen.dart index 4d0274e2..4e924d86 100644 --- a/packages/flutter_widgets/example/lib/new_group_chat_screen.dart +++ b/packages/flutter_widgets/example/lib/new_group_chat_screen.dart @@ -87,227 +87,225 @@ class _NewGroupChatScreenState extends State { ) ], ), - body: ValueListenableBuilder( - valueListenable: StreamChat.of(context).client.wsConnectionStatus, - builder: (context, status, _) { - String statusString = ''; - bool showStatus = true; + body: ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; - switch (status) { - case ConnectionStatus.connected: - statusString = 'Connected'; - showStatus = false; - break; - case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; - break; - case ConnectionStatus.disconnected: - statusString = 'Disconnected'; - break; - } - return InfoTile( - showMessage: showStatus, - tileAnchor: Alignment.topCenter, - childAnchor: Alignment.topCenter, - message: statusString, - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: - (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverToBoxAdapter( - child: SearchTextField( - controller: _controller, - ), + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } + return InfoTile( + showMessage: showStatus, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: + (BuildContext context, bool innerBoxIsScrolled) { + return [ + SliverToBoxAdapter( + child: SearchTextField( + controller: _controller, ), - if (_selectedUsers.isNotEmpty) - SliverToBoxAdapter( - child: Container( - height: 104, - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: _selectedUsers.length, - padding: const EdgeInsets.all(8), - separatorBuilder: (_, __) => SizedBox(width: 16), - itemBuilder: (_, index) { - final user = _selectedUsers.elementAt(index); - return Column( - children: [ - Stack( - children: [ - UserAvatar( - onlineIndicatorAlignment: - Alignment(0.9, 0.9), - user: user, - showOnlineStatus: true, - borderRadius: BorderRadius.circular(32), - constraints: BoxConstraints.tightFor( - height: 64, - width: 64, - ), + ), + if (_selectedUsers.isNotEmpty) + SliverToBoxAdapter( + child: Container( + height: 104, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: _selectedUsers.length, + padding: const EdgeInsets.all(8), + separatorBuilder: (_, __) => SizedBox(width: 16), + itemBuilder: (_, index) { + final user = _selectedUsers.elementAt(index); + return Column( + children: [ + Stack( + children: [ + UserAvatar( + onlineIndicatorAlignment: + Alignment(0.9, 0.9), + user: user, + showOnlineStatus: true, + borderRadius: BorderRadius.circular(32), + constraints: BoxConstraints.tightFor( + height: 64, + width: 64, ), - Positioned( - top: -4, - right: -4, - child: GestureDetector( - onTap: () { - if (_selectedUsers.contains(user)) { - setState(() => - _selectedUsers.remove(user)); - } - }, - child: Container( - decoration: BoxDecoration( + ), + Positioned( + top: -4, + right: -4, + child: GestureDetector( + onTap: () { + if (_selectedUsers.contains(user)) { + setState(() => + _selectedUsers.remove(user)); + } + }, + child: Container( + decoration: BoxDecoration( + color: StreamChatTheme.of(context) + .colorTheme + .white, + shape: BoxShape.circle, + border: Border.all( color: StreamChatTheme.of(context) .colorTheme - .white, - shape: BoxShape.circle, - border: Border.all( - color: - StreamChatTheme.of(context) - .colorTheme - .whiteSnow, - ), - ), - child: StreamSvgIcon.close( - color: StreamChatTheme.of(context) - .colorTheme - .black, - size: 24, + .whiteSnow, ), ), - ), - ) - ], - ), - SizedBox(height: 4), - Text( - user.name.split(' ')[0], - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 12, - ), - ), - ], - ); - }, - ), - ), - ), - SliverPersistentHeader( - pinned: true, - delegate: _HeaderDelegate( - height: 30, - child: Container( - width: double.maxFinite, - decoration: BoxDecoration( - gradient: StreamChatTheme.of(context) - .colorTheme - .bgGradient, - ), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 8, - ), - child: Text( - _isSearchActive - ? 'Matches for \"$_userNameQuery\"' - : 'On the platform', - style: TextStyle( - color: - StreamChatTheme.of(context).colorTheme.grey, - ), - ), - ), - ), - ), - ), - ]; - }, - body: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanDown: (_) => FocusScope.of(context).unfocus(), - child: UsersBloc( - child: UserListView( - selectedUsers: _selectedUsers, - pullToRefresh: false, - groupAlphabetically: _isSearchActive ? false : true, - onUserTap: (user, _) { - if (!_selectedUsers.contains(user)) { - setState(() { - _selectedUsers.add(user); - }); - } else { - setState(() { - _selectedUsers.remove(user); - }); - } - }, - pagination: PaginationParams( - limit: 25, - ), - filter: { - if (_userNameQuery.isNotEmpty) - 'name': { - r'$autocomplete': _userNameQuery, - }, - 'id': { - r'$ne': StreamChat.of(context).user.id, - } - }, - sort: [ - SortOption( - 'name', - direction: 1, - ), - ], - emptyBuilder: (_) { - return LayoutBuilder( - builder: (context, viewportConstraints) { - return SingleChildScrollView( - physics: AlwaysScrollableScrollPhysics(), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(24), - child: StreamSvgIcon.search( - size: 96, - color: StreamChatTheme.of(context) - .colorTheme - .grey, + child: StreamSvgIcon.close( + color: StreamChatTheme.of(context) + .colorTheme + .black, + size: 24, + ), ), ), - Text( - 'No user matches these keywords...', - style: StreamChatTheme.of(context) - .textTheme - .footnote - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .grey, - ), - ), - ], + ) + ], + ), + SizedBox(height: 4), + Text( + user.name.split(' ')[0], + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 12, ), ), - ), + ], ); }, - ); - }, + ), + ), ), + SliverPersistentHeader( + pinned: true, + delegate: _HeaderDelegate( + height: 30, + child: Container( + width: double.maxFinite, + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 8, + ), + child: Text( + _isSearchActive + ? 'Matches for \"$_userNameQuery\"' + : 'On the platform', + style: TextStyle( + color: + StreamChatTheme.of(context).colorTheme.grey, + ), + ), + ), + ), + ), + ), + ]; + }, + body: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanDown: (_) => FocusScope.of(context).unfocus(), + child: UsersBloc( + child: UserListView( + selectedUsers: _selectedUsers, + pullToRefresh: false, + groupAlphabetically: _isSearchActive ? false : true, + onUserTap: (user, _) { + if (!_selectedUsers.contains(user)) { + setState(() { + _selectedUsers.add(user); + }); + } else { + setState(() { + _selectedUsers.remove(user); + }); + } + }, + pagination: PaginationParams( + limit: 25, + ), + filter: { + if (_userNameQuery.isNotEmpty) + 'name': { + r'$autocomplete': _userNameQuery, + }, + 'id': { + r'$ne': StreamChat.of(context).user.id, + } + }, + sort: [ + SortOption( + 'name', + direction: 1, + ), + ], + emptyBuilder: (_) { + return LayoutBuilder( + builder: (context, viewportConstraints) { + return SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(24), + child: StreamSvgIcon.search( + size: 96, + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + Text( + 'No user matches these keywords...', + style: StreamChatTheme.of(context) + .textTheme + .footnote + .copyWith( + color: StreamChatTheme.of(context) + .colorTheme + .grey, + ), + ), + ], + ), + ), + ), + ); + }, + ); + }, ), ), ), - ); - }), + ), + ); + }, + ), ); } } diff --git a/packages/flutter_widgets/lib/src/channel_header.dart b/packages/flutter_widgets/lib/src/channel_header.dart index fb681d59..954734f9 100644 --- a/packages/flutter_widgets/lib/src/channel_header.dart +++ b/packages/flutter_widgets/lib/src/channel_header.dart @@ -9,6 +9,7 @@ import 'package:stream_chat_flutter/src/stream_chat_theme.dart'; import '../stream_chat_flutter.dart'; import './channel_name.dart'; import 'channel_image.dart'; +import 'connection_status_builder.dart'; /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_header.png) /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_header_paint.png) @@ -85,11 +86,9 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { final channel = StreamChannel.of(context).channel; - final _client = StreamChat.of(context).client; - return ValueListenableBuilder( - valueListenable: _client.wsConnectionStatus, - builder: (context, status, _) { + return ConnectionStatusBuilder( + statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; diff --git a/packages/flutter_widgets/lib/src/channel_info.dart b/packages/flutter_widgets/lib/src/channel_info.dart index b1ab568d..88739bb3 100644 --- a/packages/flutter_widgets/lib/src/channel_info.dart +++ b/packages/flutter_widgets/lib/src/channel_info.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'connection_status_builder.dart'; + class ChannelInfo extends StatelessWidget { final Channel channel; @@ -25,9 +27,8 @@ class ChannelInfo extends StatelessWidget { stream: channel.state.membersStream, initialData: channel.state.members, builder: (context, snapshot) { - return ValueListenableBuilder( - valueListenable: client.wsConnectionStatus, - builder: (context, status, child) { + return ConnectionStatusBuilder( + statusBuilder: (context, status) { switch (status) { case ConnectionStatus.connected: return _buildConnectedTitleState(context, snapshot.data); diff --git a/packages/flutter_widgets/lib/src/channel_list_header.dart b/packages/flutter_widgets/lib/src/channel_list_header.dart index 8ced0422..29126402 100644 --- a/packages/flutter_widgets/lib/src/channel_list_header.dart +++ b/packages/flutter_widgets/lib/src/channel_list_header.dart @@ -6,6 +6,7 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter/src/stream_neumorphic_button.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'connection_status_builder.dart'; import 'info_tile.dart'; import 'stream_chat.dart'; @@ -79,9 +80,8 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { Widget build(BuildContext context) { final _client = client ?? StreamChat.of(context).client; final user = _client.state.user; - return ValueListenableBuilder( - valueListenable: _client.wsConnectionStatus, - builder: (context, status, child) { + return ConnectionStatusBuilder( + statusBuilder: (context, status) { String statusString = ''; bool showStatus = true; @@ -130,9 +130,8 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { actions: [ StreamNeumorphicButton( child: IconButton( - icon: ValueListenableBuilder( - valueListenable: _client.wsConnectionStatus, - builder: (context, status, child) { + icon: ConnectionStatusBuilder( + statusBuilder: (context, status) { var color; switch (status) { case ConnectionStatus.connected: diff --git a/packages/flutter_widgets/lib/src/connection_status_builder.dart b/packages/flutter_widgets/lib/src/connection_status_builder.dart new file mode 100644 index 00000000..25f9a0b6 --- /dev/null +++ b/packages/flutter_widgets/lib/src/connection_status_builder.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; +import 'stream_chat.dart'; + +class ConnectionStatusBuilder extends StatelessWidget { + /// Creates a new ConnectionStatusBuilder + const ConnectionStatusBuilder({ + Key key, + @required this.statusBuilder, + this.initialStatus = ConnectionStatus.disconnected, + this.connectionStatusStream, + this.errorBuilder, + this.loadingBuilder, + }) : assert(statusBuilder != null), + super(key: key); + + /// The connection status that will be used to create the initial snapshot. + final ConnectionStatus initialStatus; + + /// The asynchronous computation to which this builder is currently connected. + final Stream connectionStatusStream; + + /// The builder that will be used in case of error + final Widget Function(BuildContext context, Object error) errorBuilder; + + /// The builder that will be used in case of loading + final WidgetBuilder loadingBuilder; + + /// The builder that will be used in case of data + final Widget Function(BuildContext context, ConnectionStatus status) + statusBuilder; + + @override + Widget build(BuildContext context) { + final stream = connectionStatusStream ?? + StreamChat.of(context).client.wsConnectionStatusStream; + return StreamBuilder( + initialData: initialStatus, + stream: stream, + builder: (context, snapshot) { + if (snapshot.hasError) { + if (errorBuilder != null) { + return errorBuilder(context, snapshot.error); + } + return Offstage(); + } + if (!snapshot.hasData) { + if (loadingBuilder != null) return loadingBuilder(context); + return Offstage(); + } + return statusBuilder(context, snapshot.data); + }, + ); + } +} diff --git a/packages/flutter_widgets/lib/src/message_list_view.dart b/packages/flutter_widgets/lib/src/message_list_view.dart index 9ce29117..86c1445c 100644 --- a/packages/flutter_widgets/lib/src/message_list_view.dart +++ b/packages/flutter_widgets/lib/src/message_list_view.dart @@ -14,6 +14,7 @@ import 'package:stream_chat_flutter/src/system_message.dart'; import 'package:visibility_detector/visibility_detector.dart'; import '../stream_chat_flutter.dart'; +import 'connection_status_builder.dart'; import 'date_divider.dart'; import 'swipeable.dart'; import 'extension.dart'; @@ -301,197 +302,193 @@ class _MessageListViewState extends State { } _messageListLength = newMessagesListLength; - final _client = StreamChat.of(context).client; return Stack( alignment: Alignment.center, children: [ - ValueListenableBuilder( - valueListenable: _client.wsConnectionStatus, - builder: (context, status, _) { - String statusString = ''; - bool showStatus = true; + ConnectionStatusBuilder( + statusBuilder: (context, status) { + String statusString = ''; + bool showStatus = true; + switch (status) { + case ConnectionStatus.connected: + statusString = 'Connected'; + showStatus = false; + break; + case ConnectionStatus.connecting: + statusString = 'Reconnecting...'; + break; + case ConnectionStatus.disconnected: + statusString = 'Disconnected'; + break; + } - switch (status) { - case ConnectionStatus.connected: - statusString = 'Connected'; - showStatus = false; - break; - case ConnectionStatus.connecting: - statusString = 'Reconnecting...'; - break; - case ConnectionStatus.disconnected: - statusString = 'Disconnected'; - break; - } + return InfoTile( + showMessage: widget.showConnectionStateTile ? showStatus : false, + tileAnchor: Alignment.topCenter, + childAnchor: Alignment.topCenter, + message: statusString, + child: LazyLoadScrollView( + onStartOfPage: () async { + _inBetweenList = false; + if (!_upToDate) { + _topPaginationActive = false; + _bottomPaginationActive = true; + return _paginateData( + streamChannel, + QueryDirection.bottom, + ); + } + }, + onEndOfPage: () async { + _inBetweenList = false; + _topPaginationActive = true; + _bottomPaginationActive = false; + return _paginateData( + streamChannel, + QueryDirection.top, + ); + }, + onInBetweenOfPage: () { + _inBetweenList = true; + }, + child: ScrollablePositionedList.separated( + key: ValueKey(initialIndex + initialAlignment), + itemPositionsListener: _itemPositionListener, + addAutomaticKeepAlives: true, + initialScrollIndex: initialIndex ?? 0, + initialAlignment: initialAlignment ?? 0, + physics: widget.scrollPhysics, + itemScrollController: _scrollController, + reverse: true, + itemCount: + messages.length + 2 + (_isThreadConversation ? 1 : 0), + separatorBuilder: (context, i) { + if (i == messages.length) return Offstage(); + if (i == 0) return SizedBox(height: 30); + if (i == messages.length + 1) { + final replyCount = widget.parentMessage.replyCount; + return Container( + decoration: BoxDecoration( + gradient: + StreamChatTheme.of(context).colorTheme.bgGradient, + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + '$replyCount ${replyCount == 1 ? 'Reply' : 'Replies'}', + textAlign: TextAlign.center, + style: StreamChatTheme.of(context) + .channelTheme + .channelHeaderTheme + .lastMessageAt, + ), + ), + ); + } - return InfoTile( - showMessage: - widget.showConnectionStateTile ? showStatus : false, - tileAnchor: Alignment.topCenter, - childAnchor: Alignment.topCenter, - message: statusString, - child: LazyLoadScrollView( - onStartOfPage: () async { - _inBetweenList = false; - if (!_upToDate) { - _topPaginationActive = false; - _bottomPaginationActive = true; - return _paginateData( + final message = messages[i]; + final nextMessage = messages[i - 1]; + if (!Jiffy(message.createdAt.toLocal()).isSame( + nextMessage.createdAt.toLocal(), + Units.DAY, + )) { + final divider = widget.dateDividerBuilder != null + ? widget.dateDividerBuilder( + nextMessage.createdAt.toLocal(), + ) + : DateDivider( + dateTime: nextMessage.createdAt.toLocal(), + ); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12.0), + child: divider, + ); + } + final timeDiff = + Jiffy(nextMessage.createdAt.toLocal()).diff( + message.createdAt.toLocal(), + Units.MINUTE, + ); + + final isNextUserSame = + message.user.id == nextMessage.user?.id; + final isThread = message.replyCount > 0; + final isDeleted = message.isDeleted; + if (timeDiff >= 1 || + !isNextUserSame || + isThread || + isDeleted) { + return SizedBox(height: 8); + } + return SizedBox(height: 2); + }, + itemBuilder: (context, i) { + if (i == messages.length + 2) { + if (widget.parentMessageBuilder != null) { + return widget.parentMessageBuilder( + context, + widget.parentMessage, + ); + } else { + return buildParentMessage(widget.parentMessage); + } + } + if (i == messages.length + 1) { + return _buildLoadingIndicator( + streamChannel, + QueryDirection.top, + ); + } + if (i == 0) { + return _buildLoadingIndicator( streamChannel, QueryDirection.bottom, ); } - }, - onEndOfPage: () async { - _inBetweenList = false; - _topPaginationActive = true; - _bottomPaginationActive = false; - return _paginateData( - streamChannel, - QueryDirection.top, - ); - }, - onInBetweenOfPage: () { - _inBetweenList = true; - }, - child: ScrollablePositionedList.separated( - key: ValueKey(initialIndex + initialAlignment), - itemPositionsListener: _itemPositionListener, - addAutomaticKeepAlives: true, - initialScrollIndex: initialIndex ?? 0, - initialAlignment: initialAlignment ?? 0, - physics: widget.scrollPhysics, - itemScrollController: _scrollController, - reverse: true, - itemCount: - messages.length + 2 + (_isThreadConversation ? 1 : 0), - separatorBuilder: (context, i) { - if (i == messages.length) return Offstage(); - if (i == 0) return SizedBox(height: 30); - if (i == messages.length + 1) { - final replyCount = widget.parentMessage.replyCount; - return Container( - decoration: BoxDecoration( - gradient: StreamChatTheme.of(context) - .colorTheme - .bgGradient, - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - '$replyCount ${replyCount == 1 ? 'Reply' : 'Replies'}', - textAlign: TextAlign.center, - style: StreamChatTheme.of(context) - .channelTheme - .channelHeaderTheme - .lastMessageAt, - ), - ), - ); - } + final message = messages[i - 1]; - final message = messages[i]; - final nextMessage = messages[i - 1]; - if (!Jiffy(message.createdAt.toLocal()).isSame( - nextMessage.createdAt.toLocal(), - Units.DAY, - )) { - final divider = widget.dateDividerBuilder != null - ? widget.dateDividerBuilder( - nextMessage.createdAt.toLocal(), - ) - : DateDivider( - dateTime: nextMessage.createdAt.toLocal(), - ); - return Padding( - padding: const EdgeInsets.symmetric(vertical: 12.0), - child: divider, - ); - } - final timeDiff = - Jiffy(nextMessage.createdAt.toLocal()).diff( - message.createdAt.toLocal(), - Units.MINUTE, + Widget messageWidget; + + if (i == 1) { + messageWidget = _buildBottomMessage( + context, + message, + messages, + streamChannel, ); - - final isNextUserSame = - message.user.id == nextMessage.user?.id; - final isThread = message.replyCount > 0; - final isDeleted = message.isDeleted; - if (timeDiff >= 1 || - !isNextUserSame || - isThread || - isDeleted) { - return SizedBox(height: 8); - } - return SizedBox(height: 2); - }, - itemBuilder: (context, i) { - if (i == messages.length + 2) { - if (widget.parentMessageBuilder != null) { - return widget.parentMessageBuilder( - context, - widget.parentMessage, - ); - } else { - return buildParentMessage(widget.parentMessage); - } - } - if (i == messages.length + 1) { - return _buildLoadingIndicator( - streamChannel, - QueryDirection.top, - ); - } - if (i == 0) { - return _buildLoadingIndicator( - streamChannel, - QueryDirection.bottom, - ); - } - final message = messages[i - 1]; - - Widget messageWidget; - - if (i == 1) { - messageWidget = _buildBottomMessage( - context, - message, - messages, - streamChannel, - ); - } else if (i == messages.length - 1) { - messageWidget = _buildTopMessage( - context, - message, - messages, - streamChannel, + } else if (i == messages.length - 1) { + messageWidget = _buildTopMessage( + context, + message, + messages, + streamChannel, + ); + } else { + if (widget.messageBuilder != null) { + messageWidget = Builder( + key: ValueKey('MESSAGE-${message.id}'), + builder: (context) => widget.messageBuilder( + context, + MessageDetails( + context, + message, + messages, + i, + ), + messages), ); } else { - if (widget.messageBuilder != null) { - messageWidget = Builder( - key: ValueKey('MESSAGE-${message.id}'), - builder: (context) => widget.messageBuilder( - context, - MessageDetails( - context, - message, - messages, - i, - ), - messages), - ); - } else { - messageWidget = buildMessage(message, messages, i); - } + messageWidget = buildMessage(message, messages, i); } - return messageWidget; - }, - ), + } + return messageWidget; + }, ), - ); - }), + ), + ); + }, + ), if (widget.showScrollToBottom) _buildScrollToBottom(), Positioned( top: 20.0, diff --git a/packages/flutter_widgets/lib/stream_chat_flutter.dart b/packages/flutter_widgets/lib/stream_chat_flutter.dart index 3f52c8c6..fa296075 100644 --- a/packages/flutter_widgets/lib/stream_chat_flutter.dart +++ b/packages/flutter_widgets/lib/stream_chat_flutter.dart @@ -40,4 +40,5 @@ export 'src/channel_file_display_screen.dart'; export 'src/channel_media_display_screen.dart'; export 'src/info_tile.dart'; export 'src/stream_chat.dart'; +export 'src/connection_status_builder.dart'; export 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; diff --git a/packages/flutter_widgets/pubspec.yaml b/packages/flutter_widgets/pubspec.yaml index 93e84f07..9321f992 100644 --- a/packages/flutter_widgets/pubspec.yaml +++ b/packages/flutter_widgets/pubspec.yaml @@ -32,8 +32,6 @@ dependencies: image_picker: ^0.6.7+17 flutter_keyboard_visibility: ^4.0.2 mime: ^0.9.7 - stream_chat: - path: ../dart_client video_compress: ^2.1.1 visibility_detector: ^0.1.5 http_parser: ^3.1.4 diff --git a/packages/stream_chat_flutter_core/pubspec.yaml b/packages/stream_chat_flutter_core/pubspec.yaml index 19dd8eb0..61c3528e 100644 --- a/packages/stream_chat_flutter_core/pubspec.yaml +++ b/packages/stream_chat_flutter_core/pubspec.yaml @@ -10,8 +10,8 @@ environment: flutter: ">=1.17.0" dependencies: - stream_chat: ^0.2.23+3 - rxdart: ^0.24.1 + stream_chat: + path: ../dart_client flutter: sdk: flutter From 4b9a7d68372d272e52e117c306f9631e5e97d818 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 15:22:19 +0530 Subject: [PATCH 23/46] [Core -> LazyLoadScrollView] Remove `isLoading` property Signed-off-by: Sahil Kumar --- .../lib/src/lazy_load_scroll_view.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/stream_chat_flutter_core/lib/src/lazy_load_scroll_view.dart b/packages/stream_chat_flutter_core/lib/src/lazy_load_scroll_view.dart index bc1f4d1b..d74c1d98 100644 --- a/packages/stream_chat_flutter_core/lib/src/lazy_load_scroll_view.dart +++ b/packages/stream_chat_flutter_core/lib/src/lazy_load_scroll_view.dart @@ -27,9 +27,6 @@ class LazyLoadScrollView extends StatefulWidget { /// The offset to take into account when triggering [onEndOfPage]/[onStartOfPage] in pixels final double scrollOffset; - /// Used to determine if loading of new data has finished. You should use set this if you aren't using a FutureBuilder or StreamBuilder - final bool isLoading; - /// Initiates a LazyLoadScrollView widget const LazyLoadScrollView({ Key key, @@ -39,7 +36,6 @@ class LazyLoadScrollView extends StatefulWidget { this.onPageScrollStart, this.onPageScrollEnd, this.onInBetweenOfPage, - this.isLoading = false, this.scrollOffset = 100, }) : assert(child != null), super(key: key); From 5310287fdd2d29943af152b0c7c6585fde044c5f Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 17:23:00 +0530 Subject: [PATCH 24/46] Transfer `showLocalNotification`, `backgroundKeepAlive` from LLC to Core Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/client.dart | 10 --- .../example/lib/advanced_options_page.dart | 3 - .../flutter_widgets/example/lib/main.dart | 3 +- .../example/lib/notifications_service.dart | 46 ++++++------- .../flutter_widgets/lib/src/stream_chat.dart | 14 +++- .../lib/src/stream_chat_core.dart | 66 +++++++------------ .../test/stream_chat_core_test.dart | 28 +++----- 7 files changed, 72 insertions(+), 98 deletions(-) diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index 988f0f8f..381d1cd6 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -79,8 +79,6 @@ class Client { Duration connectTimeout = const Duration(seconds: 6), Duration receiveTimeout = const Duration(seconds: 6), Dio httpClient, - this.showLocalNotification, - this.backgroundKeepAlive = const Duration(minutes: 1), RetryPolicy retryPolicy, }) { _retryPolicy ??= RetryPolicy( @@ -110,14 +108,6 @@ class Client { /// The retry policy options getter RetryPolicy get retryPolicy => _retryPolicy; - /// Method used to show a local notification while the app is in background - /// Switching to another application will not disconnect the client immediately - /// So, use this method to show the notification when receiving a new message via events - final void Function(Message, ChannelModel) showLocalNotification; - - /// The amount of time that will pass before disconnecting the client in the background - final Duration backgroundKeepAlive; - /// This client state ClientState state; diff --git a/packages/flutter_widgets/example/lib/advanced_options_page.dart b/packages/flutter_widgets/example/lib/advanced_options_page.dart index 25cbf51c..0b55212c 100644 --- a/packages/flutter_widgets/example/lib/advanced_options_page.dart +++ b/packages/flutter_widgets/example/lib/advanced_options_page.dart @@ -277,9 +277,6 @@ class _AdvancedOptionsPageState extends State { final client = Client( apiKey, logLevel: Level.INFO, - showLocalNotification: (!kIsWeb && Platform.isAndroid) - ? showLocalNotification - : null, )..chatPersistenceClient = chatPersistentClient; try { diff --git a/packages/flutter_widgets/example/lib/main.dart b/packages/flutter_widgets/example/lib/main.dart index caa11198..a44a8692 100644 --- a/packages/flutter_widgets/example/lib/main.dart +++ b/packages/flutter_widgets/example/lib/main.dart @@ -33,8 +33,6 @@ void main() async { final client = Client( apiKey ?? kDefaultStreamApiKey, logLevel: Level.INFO, - showLocalNotification: - (!kIsWeb && Platform.isAndroid) ? showLocalNotification : null, )..chatPersistenceClient = chatPersistentClient; if (userId != null) { @@ -73,6 +71,7 @@ class MyApp extends StatelessWidget { builder: (context, child) { return StreamChat( client: client, + onBackgroundEventReceived: showLocalNotification, child: Builder( builder: (context) => AnnotatedRegion( child: child, diff --git a/packages/flutter_widgets/example/lib/notifications_service.dart b/packages/flutter_widgets/example/lib/notifications_service.dart index 0eeb9cc0..e74a2a5a 100644 --- a/packages/flutter_widgets/example/lib/notifications_service.dart +++ b/packages/flutter_widgets/example/lib/notifications_service.dart @@ -1,12 +1,14 @@ import 'dart:io'; import 'package:example/main.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_apns/flutter_apns.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -void showLocalNotification(Message message, ChannelModel channel) async { +void showLocalNotification(Event event) async { + if (event.message == null) return; final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); final initializationSettingsAndroid = AndroidInitializationSettings('launch_background'); @@ -17,9 +19,9 @@ void showLocalNotification(Message message, ChannelModel channel) async { ); await flutterLocalNotificationsPlugin.initialize(initializationSettings); await flutterLocalNotificationsPlugin.show( - message.id.hashCode, - '${message.user.name} @ ${channel.name}', - message.text, + event.message.id.hashCode, + event.message.user.name, + event.message.text, NotificationDetails( android: AndroidNotificationDetails( 'message channel', @@ -35,24 +37,24 @@ void showLocalNotification(Message message, ChannelModel channel) async { Future backgroundHandler(Map notification) async { print('new notification ${notification}'); - final messageId = notification['data']['id']; - - final notificationData = await NotificationService.getAndStoreMessage( - messageId: messageId, - storeMessageHandler: (messageResponse) { - return chatPersistentClient.updateChannelState( - ChannelState( - messages: [messageResponse.message], - channel: messageResponse.channel, - ), - ); - }, - ); - - showLocalNotification( - notificationData.message, - notificationData.channel, - ); + // final messageId = notification['data']['id']; + // + // final notificationData = await NotificationService.getAndStoreMessage( + // messageId: messageId, + // storeMessageHandler: (messageResponse) { + // return chatPersistentClient.updateChannelState( + // ChannelState( + // messages: [messageResponse.message], + // channel: messageResponse.channel, + // ), + // ); + // }, + // ); + // + // showLocalNotification( + // notificationData.message, + // notificationData.channel, + // ); } void initNotifications(Client client) { diff --git a/packages/flutter_widgets/lib/src/stream_chat.dart b/packages/flutter_widgets/lib/src/stream_chat.dart index 37a163ec..0ea5efb2 100644 --- a/packages/flutter_widgets/lib/src/stream_chat.dart +++ b/packages/flutter_widgets/lib/src/stream_chat.dart @@ -34,11 +34,21 @@ class StreamChat extends StatefulWidget { final Widget child; final StreamChatThemeData streamChatThemeData; + /// The amount of time that will pass before disconnecting the client in the background + final Duration backgroundKeepAlive; + + /// Handler called whenever the [client] receives a new [Event] while the app + /// is in background. Can be used to display various notifications depending + /// upon the [Event.type] + final EventHandler onBackgroundEventReceived; + StreamChat({ Key key, @required this.client, @required this.child, this.streamChatThemeData, + this.onBackgroundEventReceived, + this.backgroundKeepAlive = const Duration(minutes: 1), }) : super( key: key, ); @@ -82,8 +92,10 @@ class StreamChatState extends State { scaffoldBackgroundColor: streamTheme.colorTheme.white, ), child: StreamChatCore( - child: widget.child, client: client, + child: widget.child, + onBackgroundEventReceived: widget.onBackgroundEventReceived, + backgroundKeepAlive: widget.backgroundKeepAlive, ), ); }, diff --git a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart index 73f5eb61..1d2d4736 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart @@ -4,6 +4,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; +typedef EventHandler = void Function(Event event); + /// Widget used to provide information about the chat to the widget tree /// /// class MyApp extends StatelessWidget { @@ -28,17 +30,26 @@ import 'package:stream_chat/stream_chat.dart'; class StreamChatCore extends StatefulWidget { // ignore: public_member_api_docs final Client client; + // ignore: public_member_api_docs final Widget child; + /// The amount of time that will pass before disconnecting the client in the background + final Duration backgroundKeepAlive; + + /// Handler called whenever the [client] receives a new [Event] while the app + /// is in background. Can be used to display various notifications depending + /// upon the [Event.type] + final EventHandler onBackgroundEventReceived; + // ignore: public_member_api_docs StreamChatCore({ Key key, @required this.client, @required this.child, - }) : super( - key: key, - ); + this.onBackgroundEventReceived, + this.backgroundKeepAlive = const Duration(minutes: 1), + }) : super(key: key); @override StreamChatCoreState createState() => StreamChatCoreState(); @@ -82,56 +93,28 @@ class StreamChatCoreState extends State WidgetsBinding.instance.addObserver(this); } - StreamSubscription _newMessageSubscription; + StreamSubscription _eventSubscription; @override void didChangeAppLifecycleState(AppLifecycleState state) { if (client.state?.user != null) { if (state == AppLifecycleState.paused) { - if (client.showLocalNotification != null) { - _newMessageSubscription = client - .on(EventType.messageNew) - .where((e) => e.user?.id != user.id) - .where((e) => e.message.silent != true) - .where((e) => e.message.shadowed != true) - .listen((event) async { - final channel = client.channel( - event.channelType, - id: event.channelId, - ); - - client.showLocalNotification( - event.message, - ChannelModel( - id: channel.id, - createdAt: channel.createdAt, - extraData: channel.extraData, - type: channel.type, - memberCount: channel.memberCount, - frozen: channel.frozen, - cid: channel.cid, - deletedAt: channel.deletedAt, - config: channel.config, - createdBy: channel.createdBy, - updatedAt: channel.updatedAt, - lastMessageAt: channel.lastMessageAt, - ), - ); - }); - _disconnectTimer = Timer(client.backgroundKeepAlive, () { - client.disconnect(); - }); + if (widget.onBackgroundEventReceived != null) { + _eventSubscription = + client.on().listen(widget.onBackgroundEventReceived); + _disconnectTimer = Timer( + widget.backgroundKeepAlive, + client.disconnect, + ); } else { client.disconnect(); } } else if (state == AppLifecycleState.resumed) { - _newMessageSubscription?.cancel(); + _eventSubscription?.cancel(); if (_disconnectTimer?.isActive == true) { _disconnectTimer.cancel(); } else { - if (client.wsConnectionStatus.value == - ConnectionStatus.disconnected) { - NotificationService.handleIosMessageQueue(client); + if (client.wsConnectionStatus == ConnectionStatus.disconnected) { client.connect(); } } @@ -142,6 +125,7 @@ class StreamChatCoreState extends State @override void dispose() { WidgetsBinding.instance.removeObserver(this); + _eventSubscription?.cancel(); _disconnectTimer?.cancel(); super.dispose(); } diff --git a/packages/stream_chat_flutter_core/test/stream_chat_core_test.dart b/packages/stream_chat_flutter_core/test/stream_chat_core_test.dart index 714375de..a8d7e227 100644 --- a/packages/stream_chat_flutter_core/test/stream_chat_core_test.dart +++ b/packages/stream_chat_flutter_core/test/stream_chat_core_test.dart @@ -9,7 +9,7 @@ import 'package:mockito/mockito.dart'; import 'mocks.dart'; class MockShowLocalNotifications extends Mock { - void call(Message m, ChannelModel cm); + void call(Event event); } void main() { @@ -97,14 +97,8 @@ void main() { ), ); final showLocalNotificationMock = MockShowLocalNotifications().call; - when(client.showLocalNotification) - .thenReturn(showLocalNotificationMock); - when(client.backgroundKeepAlive).thenReturn(Duration( - seconds: 4, - )); final eventStreamController = StreamController(); - when(client.on(EventType.messageNew)) - .thenAnswer((_) => eventStreamController.stream); + when(client.on()).thenAnswer((_) => eventStreamController.stream); when(client.channel('test', id: 'testid')).thenReturn(channel); @@ -113,6 +107,8 @@ void main() { StreamChatCore( key: scKey, client: client, + onBackgroundEventReceived: showLocalNotificationMock, + backgroundKeepAlive: const Duration(seconds: 4), child: Builder( builder: (context) { return Container(); @@ -144,13 +140,8 @@ void main() { ), ); final showLocalNotificationMock = MockShowLocalNotifications().call; - when(client.showLocalNotification).thenReturn(showLocalNotificationMock); - when(client.backgroundKeepAlive).thenReturn(Duration( - seconds: 4, - )); final eventStreamController = StreamController(); - when(client.on(EventType.messageNew)) - .thenAnswer((_) => eventStreamController.stream); + when(client.on()).thenAnswer((_) => eventStreamController.stream); when(client.channel('test', id: 'testid')).thenReturn(channel); @@ -159,6 +150,8 @@ void main() { StreamChatCore( key: scKey, client: client, + onBackgroundEventReceived: showLocalNotificationMock, + backgroundKeepAlive: const Duration(seconds: 4), child: Builder( builder: (context) { return Container(); @@ -178,12 +171,9 @@ void main() { ); eventStreamController.add(event); - await untilCalled(showLocalNotificationMock(any, any)); + await untilCalled(showLocalNotificationMock(event)); - verify(showLocalNotificationMock( - event.message, - any, - )).called(1); + verify(showLocalNotificationMock(event)).called(1); }, ); } From 0013cb98fd6a5a1607f78f25fd8588f2135d4267 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 17:31:43 +0530 Subject: [PATCH 25/46] Ran formatter Signed-off-by: Sahil Kumar --- .../stream_chat_persistence/lib/src/mapper/reaction_mapper.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart index 407816be..8f9b99e7 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart @@ -19,7 +19,7 @@ extension ReactionEntityX on ReactionEntity { /// Useful mapping functions for [Reaction] extension ReactionX on Reaction { - ReactionEntity toEntity() { + ReactionEntity toEntity() { return ReactionEntity( extraData: extraData, type: type, From 1c54b3f36ffcd006bf61d267f34fbcf6a6a0bd08 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 17:32:29 +0530 Subject: [PATCH 26/46] [Persistence] Doc Signed-off-by: Sahil Kumar --- .../stream_chat_persistence/lib/src/mapper/reaction_mapper.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart index 8f9b99e7..d265fcb7 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart @@ -19,6 +19,7 @@ extension ReactionEntityX on ReactionEntity { /// Useful mapping functions for [Reaction] extension ReactionX on Reaction { + /// Maps a [Reaction] into [ReactionEntity] ReactionEntity toEntity() { return ReactionEntity( extraData: extraData, From 5954dfa2b222dbd9d4770ef0a11eff36a3ab77cc Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 17:38:11 +0530 Subject: [PATCH 27/46] [Persistence] Analyzer warning Signed-off-by: Sahil Kumar --- .../lib/src/stream_chat_persistence_client.dart | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index 49a59423..d36ed1b2 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -28,19 +28,6 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { final Logger _logger; final ConnectionMode _connectionMode; - bool get _debugAssertConnected { - assert(() { - if (_db == null) { - throw Exception( - 'A $runtimeType was used after being disconnected.\n' - 'Once you have called disconnect() on a $runtimeType, it can no longer be used.', - ); - } - return true; - }()); - return true; - } - @override Future connect(String userId) async { if (_db != null) { From da8301eceabbf684b6ebce38618af3c38799784a Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 18:18:50 +0530 Subject: [PATCH 28/46] Fix action for non flutter projects Signed-off-by: Sahil Kumar --- .github/workflows/stream_flutter_workflow.yml | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stream_flutter_workflow.yml b/.github/workflows/stream_flutter_workflow.yml index 8ced7815..35b16c59 100644 --- a/.github/workflows/stream_flutter_workflow.yml +++ b/.github/workflows/stream_flutter_workflow.yml @@ -1,4 +1,3 @@ - name: stream_flutter_workflow env: @@ -70,7 +69,25 @@ jobs: find . -maxdepth 12 -name "*.java" -print0 \| xargs -0 java -jar $HOME/google-java-format.jar --replace ./.github/workflows/scripts/validate-formatting.sh - test: + test_dart: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 0 + - name: 'Install Flutter' + run: ./.github/workflows/scripts/install-flutter.sh stable + - name: 'Install Tools' + run: ./.github/workflows/scripts/install-tools.sh + - name: 'Bootstrap Workspace' + run: melos bootstrap + - name: 'Flutter Test' + run: | + melos exec -c 1 --no-flutter --dir-exists=test --ignore="*example*" --ignore="*web*" -- \ + flutter pub run test + + test_flutter: runs-on: ubuntu-latest timeout-minutes: 15 steps: @@ -85,5 +102,5 @@ jobs: run: melos bootstrap - name: 'Flutter Test' run: | - melos exec -c 3 --dir-exists=test --ignore="*example*" --ignore="*web*" -- \ + melos exec -c 3 --flutter --dir-exists=test --ignore="*example*" --ignore="*web*" -- \ flutter test \ No newline at end of file From ab9266bfeb9d2265fc1553b388e37aa1d00e14a4 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 18:37:42 +0530 Subject: [PATCH 29/46] [Action] Increase dart test timeout Signed-off-by: Sahil Kumar --- .github/workflows/stream_flutter_workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stream_flutter_workflow.yml b/.github/workflows/stream_flutter_workflow.yml index 35b16c59..06a8a2ec 100644 --- a/.github/workflows/stream_flutter_workflow.yml +++ b/.github/workflows/stream_flutter_workflow.yml @@ -71,7 +71,7 @@ jobs: test_dart: runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 15 steps: - uses: actions/checkout@v1 with: From e85a4326d682d17523065d967d1873ce8b4642e5 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 19:17:07 +0530 Subject: [PATCH 30/46] [Persistence] Delete members, read data before adding new one Signed-off-by: Sahil Kumar --- .../lib/src/db/chat_persistence_client.dart | 21 ++++++++++++++++++- .../lib/src/dao/member_dao.dart | 12 ++++++++++- .../lib/src/dao/message_dao.dart | 12 +++++------ .../lib/src/dao/reaction_dao.dart | 16 +++++++++++--- .../lib/src/dao/read_dao.dart | 2 +- .../src/stream_chat_persistence_client.dart | 10 +++++++++ 6 files changed, 61 insertions(+), 12 deletions(-) diff --git a/packages/dart_client/lib/src/db/chat_persistence_client.dart b/packages/dart_client/lib/src/db/chat_persistence_client.dart index 19a9164e..070bf37f 100644 --- a/packages/dart_client/lib/src/db/chat_persistence_client.dart +++ b/packages/dart_client/lib/src/db/chat_persistence_client.dart @@ -129,6 +129,12 @@ abstract class ChatPersistenceClient { /// Future updateReactions(List reactions); + /// + Future deleteReactionsByMessageId(List messageIds); + + /// + Future deleteMembersByCids(List cids); + /// Future updateChannelState(ChannelState channelState) { return updateChannelStates([channelState]); @@ -181,13 +187,26 @@ abstract class ChatPersistenceClient { return updateMembers(cid, members.toList(growable: false)); }).toList(growable: false); + final deleteReactions = deleteReactionsByMessageId(channelStates + .expand((it) => it.messages) + .map((m) => m.id) + .toList(growable: false)); + + final deleteMembers = deleteMembersByCids( + channelStates.map((it) => it.channel.cid).toList(growable: false), + ); + + await Future.wait([ + deleteReactions, + deleteMembers, + ]); await Future.wait([ ...updateMessagesFuture, ...updateReadsFuture, ...updateMembersFuture, + updateUsers(users.toList(growable: false)), updateChannels(channels.toList(growable: false)), updateReactions(reactions.toList(growable: false)), - updateUsers(users.toList(growable: false)), ]); } } diff --git a/packages/stream_chat_persistence/lib/src/dao/member_dao.dart b/packages/stream_chat_persistence/lib/src/dao/member_dao.dart index c535af9a..ed30a931 100644 --- a/packages/stream_chat_persistence/lib/src/dao/member_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/member_dao.dart @@ -16,7 +16,7 @@ class MemberDao extends DatabaseAccessor /// Creates a new member dao instance MemberDao(MoorChatDatabase db) : super(db); - /// Get all members where [members.channelCid] matches [cid] + /// Get all members where [Members.channelCid] matches [cid] Future> getMembersByCid(String cid) async { return (select(members).join([ leftOuterJoin(users, members.userId.equalsExp(users.id)), @@ -40,4 +40,14 @@ class MemberDao extends DatabaseAccessor ), ); } + + /// Deletes all the members whose [Members.channelCid] is present in [cids] + Future deleteMemberByCids(List cids) async { + return batch((it) { + it.deleteWhere( + members, + (m) => m.channelCid.isIn(cids), + ); + }); + } } diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart index 57aa055d..8acdbfd4 100644 --- a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -16,7 +16,7 @@ class MessageDao extends DatabaseAccessor final MoorChatDatabase _db; - /// Removes all the messages by matching [messages.id] in [messageIds] + /// Removes all the messages by matching [Messages.id] in [messageIds] /// /// This will automatically delete the following linked records /// 1. Message Reactions @@ -24,7 +24,7 @@ class MessageDao extends DatabaseAccessor return (delete(messages)..where((tbl) => tbl.id.isIn(messageIds))).go(); } - /// Removes all the messages by matching [messages.channelCid] in [cids] + /// Removes all the messages by matching [Messages.channelCid] in [cids] /// /// This will automatically delete the following linked records /// 1. Message Reactions @@ -52,7 +52,7 @@ class MessageDao extends DatabaseAccessor ); } - /// Returns a single message by matching the [messages.id] with [id] + /// Returns a single message by matching the [Messages.id] with [id] Future getMessageById(String id) async { return await (select(messages).join([ leftOuterJoin(users, messages.userId.equalsExp(users.id)), @@ -63,7 +63,7 @@ class MessageDao extends DatabaseAccessor } /// Returns all the messages of a particular thread by matching - /// [messages.channelCid] with [cid] + /// [Messages.channelCid] with [cid] Future> getThreadMessages(String cid) async { return Future.wait(await (select(messages).join([ leftOuterJoin(users, messages.userId.equalsExp(users.id)), @@ -76,7 +76,7 @@ class MessageDao extends DatabaseAccessor } /// Returns all the messages of a particular thread by matching - /// [messages.parentId] with [parentId] + /// [Messages.parentId] with [parentId] Future> getThreadMessagesByParentId( String parentId, { PaginationParams options, @@ -97,7 +97,7 @@ class MessageDao extends DatabaseAccessor } /// Returns all the messages of a channel by matching - /// [messages.channelCid] with [parentId] + /// [Messages.channelCid] with [parentId] Future> getMessagesByCid( String cid, { PaginationParams messagePagination, diff --git a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart index 249bd011..99053fca 100644 --- a/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/reaction_dao.dart @@ -15,7 +15,7 @@ class ReactionDao extends DatabaseAccessor ReactionDao(MoorChatDatabase db) : super(db); /// Returns all the reactions of a particular message by matching - /// [reactions.messageId] with [messageId] + /// [Reactions.messageId] with [messageId] Future> getReactions(String messageId) { return (select(reactions).join([ leftOuterJoin(users, reactions.userId.equalsExp(users.id)), @@ -31,8 +31,8 @@ class ReactionDao extends DatabaseAccessor /// Returns all the reactions of a particular message /// added by a particular user by matching - /// [reactions.messageId] with [messageId] and - /// [reactions.userId] with [userId] + /// [Reactions.messageId] with [messageId] and + /// [Reactions.userId] with [userId] Future> getReactionsByUserId( String messageId, String userId, @@ -51,4 +51,14 @@ class ReactionDao extends DatabaseAccessor ); }); } + + /// Deletes all the reactions whose [Reactions.messageId] is present in [messageIds] + Future deleteReactionsByMessageIds(List messageIds) { + return batch((it) { + it.deleteWhere( + reactions, + (r) => r.messageId.isIn(messageIds), + ); + }); + } } diff --git a/packages/stream_chat_persistence/lib/src/dao/read_dao.dart b/packages/stream_chat_persistence/lib/src/dao/read_dao.dart index 00af6b6d..c78cab07 100644 --- a/packages/stream_chat_persistence/lib/src/dao/read_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/read_dao.dart @@ -13,7 +13,7 @@ class ReadDao extends DatabaseAccessor with _$ReadDaoMixin { /// Creates a new read dao instance ReadDao(MoorChatDatabase db) : super(db); - /// Get all reads where [reads.channelCid] matches [cid] + /// Get all reads where [Reads.channelCid] matches [cid] Future> getReadsByCid(String cid) async { return (select(reads).join([ leftOuterJoin(users, reads.userId.equalsExp(users.id)), diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index d36ed1b2..ebad74f8 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -193,6 +193,16 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { return _db.userDao.updateUsers(users); } + @override + Future deleteReactionsByMessageId(List messageIds) { + return _db.reactionDao.deleteReactionsByMessageIds(messageIds); + } + + @override + Future deleteMembersByCids(List cids) { + return _db.memberDao.deleteMemberByCids(cids); + } + @override Future disconnect({bool flush = false}) async { if (_db != null) { From c0e4b51a3b001380afb558d87b9fe97d65cf91a2 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 20:11:51 +0530 Subject: [PATCH 31/46] Fix action Signed-off-by: Sahil Kumar --- .github/workflows/stream_flutter_workflow.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/stream_flutter_workflow.yml b/.github/workflows/stream_flutter_workflow.yml index 06a8a2ec..240c0310 100644 --- a/.github/workflows/stream_flutter_workflow.yml +++ b/.github/workflows/stream_flutter_workflow.yml @@ -71,7 +71,7 @@ jobs: test_dart: runs-on: ubuntu-latest - timeout-minutes: 15 + timeout-minutes: 5 steps: - uses: actions/checkout@v1 with: @@ -83,9 +83,7 @@ jobs: - name: 'Bootstrap Workspace' run: melos bootstrap - name: 'Flutter Test' - run: | - melos exec -c 1 --no-flutter --dir-exists=test --ignore="*example*" --ignore="*web*" -- \ - flutter pub run test + run: cd packages/dart_client && flutter pub run test test_flutter: runs-on: ubuntu-latest From f69821b813f28d6b89f7bba842090aef7d8ff274 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 20:15:29 +0530 Subject: [PATCH 32/46] [Persistence] Update changelog, pubspec Signed-off-by: Sahil Kumar --- packages/stream_chat_persistence/CHANGELOG.md | 4 ++-- packages/stream_chat_persistence/pubspec.yaml | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md index ac071598..ba22fd4f 100644 --- a/packages/stream_chat_persistence/CHANGELOG.md +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -1,3 +1,3 @@ -## [0.0.1] - TODO: Add release date. +## 1.0.0-rc -* TODO: Describe initial release. +* Initial release \ No newline at end of file diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index a0c97c89..b8e49170 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -1,8 +1,9 @@ name: stream_chat_persistence -description: A new Flutter package. -version: 0.0.1 -author: -homepage: +homepage: https://github.com/GetStream/stream-chat-flutter +description: Official Stream Chat Persistence library. Build your own chat experience using Dart and Flutter. +version: 1.0.0-rc +repository: https://github.com/GetStream/stream-chat-flutter +issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues environment: sdk: ">=2.7.0 <3.0.0" From 74707093b67ff804056193f86a786673a9801bca Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 29 Jan 2021 20:22:04 +0530 Subject: [PATCH 33/46] [Persistence] Update LICENSE Signed-off-by: Sahil Kumar --- packages/stream_chat_persistence/LICENSE | 220 ++++++++++++++++++++++- 1 file changed, 219 insertions(+), 1 deletion(-) diff --git a/packages/stream_chat_persistence/LICENSE b/packages/stream_chat_persistence/LICENSE index ba75c69f..49088d47 100644 --- a/packages/stream_chat_persistence/LICENSE +++ b/packages/stream_chat_persistence/LICENSE @@ -1 +1,219 @@ -TODO: Add your license here. +SOURCE CODE LICENSE AGREEMENT + +IMPORTANT - READ THIS CAREFULLY BEFORE DOWNLOADING, INSTALLING, USING OR +ELECTRONICALLY ACCESSING THIS PROPRIETARY PRODUCT. + +THIS IS A LEGAL AGREEMENT BETWEEN STREAM.IO, INC. (“STREAM.IO”) AND THE +BUSINESS ENTITY OR PERSON FOR WHOM YOU (“YOU”) ARE ACTING (“CUSTOMER”) AS THE +LICENSEE OF THE PROPRIETARY SOFTWARE INTO WHICH THIS AGREEMENT HAS BEEN +INCLUDED (THE “AGREEMENT”). YOU AGREE THAT YOU ARE THE CUSTOMER, OR YOU ARE AN +EMPLOYEE OR AGENT OF CUSTOMER AND ARE ENTERING INTO THIS AGREEMENT FOR LICENSE +OF THE SOFTWARE BY CUSTOMER FOR CUSTOMER’S BUSINESS PURPOSES AS DESCRIBED IN +AND IN ACCORDANCE WITH THIS AGREEMENT. YOU HEREBY AGREE THAT YOU ENTER INTO +THIS AGREEMENT ON BEHALF OF CUSTOMER AND THAT YOU HAVE THE AUTHORITY TO BIND +CUSTOMER TO THIS AGREEMENT. + +STREAM.IO IS WILLING TO LICENSE THE SOFTWARE TO CUSTOMER ONLY ON THE FOLLOWING +CONDITIONS: (1) YOU ARE A CURRENT CUSTOMER OF STREAM.IO; (2) YOU ARE NOT A +COMPETITOR OF STREAM.IO; AND (3) THAT YOU ACCEPT ALL THE TERMS IN THIS +AGREEMENT. BY DOWNLOADING, INSTALLING, CONFIGURING, ACCESSING OR OTHERWISE +USING THE SOFTWARE, INCLUDING ANY UPDATES, UPGRADES, OR NEWER VERSIONS, YOU +REPRESENT, WARRANT AND ACKNOWLEDGE THAT (A) CUSTOMER IS A CURRENT CUSTOMER OF +STREAM.IO; (B) CUSTOMER IS NOT A COMPETITOR OF STREAM.IO; AND THAT (C) YOU HAVE +READ THIS AGREEMENT, UNDERSTAND THIS AGREEMENT, AND THAT CUSTOMER AGREES TO BE +BOUND BY ALL THE TERMS OF THIS AGREEMENT. + +IF YOU DO NOT AGREE TO ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT, +STREAM.IO IS UNWILLING TO LICENSE THE SOFTWARE TO CUSTOMER, AND THEREFORE, DO +NOT COMPLETE THE DOWNLOAD PROCESS, ACCESS OR OTHERWISE USE THE SOFTWARE, AND +CUSTOMER SHOULD IMMEDIATELY RETURN THE SOFTWARE AND CEASE ANY USE OF THE +SOFTWARE. + +1. SOFTWARE. The Stream.io software accompanying this Agreement, may include +Source Code, Executable Object Code, associated media, printed materials and +documentation (collectively, the “Software”). The Software also includes any +updates or upgrades to or new versions of the original Software, if and when +made available to you by Stream.io. “Source Code” means computer programming +code in human readable form that is not suitable for machine execution without +the intervening steps of interpretation or compilation. “Executable Object +Code" means the computer programming code in any other form than Source Code +that is not readily perceivable by humans and suitable for machine execution +without the intervening steps of interpretation or compilation. “Site” means a +Customer location controlled by Customer. “Authorized User” means any employee +or contractor of Customer working at the Site, who has signed a written +confidentiality agreement with Customer or is otherwise bound in writing by +confidentiality and use obligations at least as restrictive as those imposed +under this Agreement. + +2. LICENSE GRANT. Subject to the terms and conditions of this Agreement, in +consideration for the representations, warranties, and covenants made by +Customer in this Agreement, Stream.io grants to Customer, during the term of +this Agreement, a personal, non-exclusive, non-transferable, non-sublicensable +license to: + +a. install and use Software Source Code on password protected computers at a Site, +restricted to Authorized Users; + +b. create derivative works, improvements (whether or not patentable), extensions +and other modifications to the Software Source Code (“Modifications”) to build +unique scalable newsfeeds, activity streams, and in-app messaging via Stream’s +application program interface (“API”); + +c. compile the Software Source Code to create Executable Object Code versions of +the Software Source Code and Modifications to build such newsfeeds, activity +streams, and in-app messaging via the API; + +d. install, execute and use such Executable Object Code versions solely for +Customer’s internal business use (including development of websites through +which data generated by Stream services will be streamed (“Apps”)); + +e. use and distribute such Executable Object Code as part of Customer’s Apps; and + +f. make electronic copies of the Software and Modifications as required for backup +or archival purposes. + +3. RESTRICTIONS. Customer is responsible for all activities that occur in +connection with the Software. Customer will not, and will not attempt to: (a) +sublicense or transfer the Software or any Source Code related to the Software +or any of Customer’s rights under this Agreement, except as otherwise provided +in this Agreement, (b) use the Software Source Code for the benefit of a third +party or to operate a service; (c) allow any third party to access or use the +Software Source Code; (d) sublicense or distribute the Software Source Code or +any Modifications in Source Code or other derivative works based on any part of +the Software Source Code; (e) use the Software in any manner that competes with +Stream.io or its business; or (e) otherwise use the Software in any manner that +exceeds the scope of use permitted in this Agreement. Customer shall use the +Software in compliance with any accompanying documentation any laws applicable +to Customer. + +4. OPEN SOURCE. Customer and its Authorized Users shall not use any software or +software components that are open source in conjunction with the Software +Source Code or any Modifications in Source Code or in any way that could +subject the Software to any open source licenses. + +5. CONTRACTORS. Under the rights granted to Customer under this Agreement, +Customer may permit its employees, contractors, and agencies of Customer to +become Authorized Users to exercise the rights to the Software granted to +Customer in accordance with this Agreement solely on behalf of Customer to +provide services to Customer; provided that Customer shall be liable for the +acts and omissions of all Authorized Users to the extent any of such acts or +omissions, if performed by Customer, would constitute a breach of, or otherwise +give rise to liability to Customer under, this Agreement. Customer shall not +and shall not permit any Authorized User to use the Software except as +expressly permitted in this Agreement. + +6. COMPETITIVE PRODUCT DEVELOPMENT. Customer shall not use the Software in any way +to engage in the development of products or services which could be reasonably +construed to provide a complete or partial functional or commercial alternative +to Stream.io’s products or services (a “Competitive Product”). Customer shall +ensure that there is no direct or indirect use of, or sharing of, Software +source code, or other information based upon or derived from the Software to +develop such products or services. Without derogating from the generality of +the foregoing, development of Competitive Products shall include having direct +or indirect access to, supervising, consulting or assisting in the development +of, or producing any specifications, documentation, object code or source code +for, all or part of a Competitive Product. + +7. LIMITATION ON MODIFICATIONS. Notwithstanding any provision in this Agreement, +Modifications may only be created and used by Customer as permitted by this +Agreement and Modification Source Code may not be distributed to third parties. +Customer will not assert against Stream.io, its affiliates, or their customers, +direct or indirect, agents and contractors, in any way, any patent rights that +Customer may obtain relating to any Modifications for Stream.io, its +affiliates’, or their customers’, direct or indirect, agents’ and contractors’ +manufacture, use, import, offer for sale or sale of any Stream.io products or +services. + +8. DELIVERY AND ACCEPTANCE. The Software will be delivered electronically pursuant +to Stream.io standard download procedures. The Software is deemed accepted upon +delivery. + +9. IMPLEMENTATION AND SUPPORT. Stream.io has no obligation under this Agreement to +provide any support or consultation concerning the Software. + +10. TERM AND TERMINATION. The term of this Agreement begins when the Software is +downloaded or accessed and shall continue until terminated. Either party may +terminate this Agreement upon written notice. This Agreement shall +automatically terminate if Customer is or becomes a competitor of Stream.io or +makes or sells any Competitive Products. Upon termination of this Agreement for +any reason, (a) all rights granted to Customer in this Agreement immediately +cease to exist, (b) Customer must promptly discontinue all use of the Software +and return to Stream.io or destroy all copies of the Software in Customer’s +possession or control. Any continued use of the Software by Customer or attempt +by Customer to exercise any rights under this Agreement after this Agreement +has terminated shall be considered copyright infringement and subject Customer +to applicable remedies for copyright infringement. Sections 2, 5, 6, 8 and 9 +shall survive expiration or termination of this Agreement for any reason. + +11. OWNERSHIP. As between the parties, the Software and all worldwide intellectual +property rights and proprietary rights relating thereto or embodied therein, +are the exclusive property of Stream.io and its suppliers. Stream.io and its +suppliers reserve all rights in and to the Software not expressly granted to +Customer in this Agreement, and no other licenses or rights are granted by +implication, estoppel or otherwise. + +12. WARRANTY DISCLAIMER. USE OF THIS SOFTWARE IS ENTIRELY AT YOURS AND CUSTOMER’S +OWN RISK. THE SOFTWARE IS PROVIDED “AS IS” WITHOUT ANY WARRANTY OF ANY KIND +WHATSOEVER. STREAM.IO DOES NOT MAKE, AND HEREBY DISCLAIMS, ANY WARRANTY OF ANY +KIND, WHETHER EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING WITHOUT +LIMITATION, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, TITLE, NON-INFRINGEMENT OF THIRD-PARTY RIGHTS, RESULTS, EFFORTS, +QUALITY OR QUIET ENJOYMENT. STREAM.IO DOES NOT WARRANT THAT THE SOFTWARE IS +ERROR-FREE, WILL FUNCTION WITHOUT INTERRUPTION, WILL MEET ANY SPECIFIC NEED +THAT CUSTOMER HAS, THAT ALL DEFECTS WILL BE CORRECTED OR THAT IT IS +SUFFICIENTLY DOCUMENTED TO BE USABLE BY CUSTOMER. TO THE EXTENT THAT STREAM.IO +MAY NOT DISCLAIM ANY WARRANTY AS A MATTER OF APPLICABLE LAW, THE SCOPE AND +DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER SUCH LAW. +CUSTOMER ACKNOWLEDGES THAT IT HAS RELIED ON NO WARRANTIES OTHER THAN THE +EXPRESS WARRANTIES IN THIS AGREEMENT. + +13. LIMITATION OF LIABILITY. TO THE FULLEST EXTENT PERMISSIBLE BY LAW, STREAM.IO’S +TOTAL LIABILITY FOR ALL DAMAGES ARISING OUT OF OR RELATED TO THE SOFTWARE OR +THIS AGREEMENT, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, +SHALL NOT EXCEED $100. IN NO EVENT WILL STREAM.IO BE LIABLE FOR ANY INDIRECT, +CONSEQUENTIAL, EXEMPLARY, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES OF ANY KIND +WHATSOEVER, INCLUDING ANY LOST DATA AND LOST PROFITS, ARISING FROM OR RELATING +TO THE SOFTWARE EVEN IF STREAM.IO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. CUSTOMER ACKNOWLEDGES THAT THIS PROVISION REFLECTS THE AGREED UPON +ALLOCATION OF RISK FOR THIS AGREEMENT AND THAT STREAM.IO WOULD NOT ENTER INTO +THIS AGREEMENT WITHOUT THESE LIMITATIONS ON ITS LIABILITY. + +14. General. Customer may not assign or transfer this Agreement, by operation of +law or otherwise, or any of its rights under this Agreement (including the +license rights granted to Customer) to any third party without Stream.io’s +prior written consent, which consent will not be unreasonably withheld or +delayed. Stream.io may assign this Agreement, without consent, including, but +limited to, affiliate or any successor to all or substantially all its business +or assets to which this Agreement relates, whether by merger, sale of assets, +sale of stock, reorganization or otherwise. Any attempted assignment or +transfer in violation of the foregoing will be null and void. Stream.io shall +not be liable hereunder by reason of any failure or delay in the performance of +its obligations hereunder for any cause which is beyond the reasonable control. +All notices, consents, and approvals under this Agreement must be delivered in +writing by courier, by electronic mail, or by certified or registered mail, +(postage prepaid and return receipt requested) to the other party at the +address set forth in the customer agreement between Stream.io and Customer and +will be effective upon receipt or when delivery is refused. This Agreement will +be governed by and interpreted in accordance with the laws of the State of +Colorado, without reference to its choice of laws rules. The United Nations +Convention on Contracts for the International Sale of Goods does not apply to +this Agreement. Any action or proceeding arising from or relating to this +Agreement shall be brought in a federal or state court in Denver, Colorado, and +each party irrevocably submits to the jurisdiction and venue of any such court +in any such action or proceeding. All waivers must be in writing. Any waiver or +failure to enforce any provision of this Agreement on one occasion will not be +deemed a waiver of any other provision or of such provision on any other +occasion. If any provision of this Agreement is unenforceable, such provision +will be changed and interpreted to accomplish the objectives of such provision +to the greatest extent possible under applicable law and the remaining +provisions will continue in full force and effect. Customer shall not violate +any applicable law, rule or regulation, including those regarding the export of +technical data. The headings of Sections of this Agreement are for convenience +and are not to be used in interpreting this Agreement. As used in this +Agreement, the word “including” means “including but not limited to.” This +Agreement (including all exhibits and attachments) constitutes the entire +agreement between the parties regarding the subject hereof and supersedes all +prior or contemporaneous agreements, understandings and communication, whether +written or oral. This Agreement may be amended only by a written document +signed by both parties. The terms of any purchase order or similar document +submitted by Customer to Stream.io will have no effect. From b8e9d8efdc5758314ac287b2b6dca7178b41d4be Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 13:55:29 +0530 Subject: [PATCH 34/46] [Persistence] Add more docs Signed-off-by: Sahil Kumar --- .../lib/src/db/shared/native_db.dart | 16 +++++++++++++--- .../lib/src/db/shared/unsupported_db.dart | 14 ++++++++++---- .../lib/src/db/shared/web_db.dart | 16 ++++++++++++---- .../lib/src/stream_chat_persistence_client.dart | 2 +- packages/stream_chat_persistence/pubspec.yaml | 1 + 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart index 90f19de6..74cf91f8 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart @@ -1,5 +1,3 @@ -//ignore_for_file: public_member_api_docs - import 'dart:io'; import 'dart:isolate'; import 'package:moor/ffi.dart'; @@ -7,10 +5,18 @@ import 'package:moor/isolate.dart'; import 'package:moor/moor.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:stream_chat_persistence/src/stream_chat_persistence_client.dart'; +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import '../moor_chat_database.dart'; +/// A Helper class to construct new instances of [MoorChatDatabase] specifically +/// for native platform applications class SharedDB { + /// Returns a new instance of [VmDatabase] created using [userId] + /// on a regular isolate. + /// + /// Generally used with [ConnectionMode.regular]. static Future constructDatabase( String userId, { bool logStatements = false, @@ -62,7 +68,11 @@ class SharedDB { return (await receivePort.first as MoorIsolate); } - static Future constructOfflineStorage( + /// Returns a new instance of [MoorChatDatabase] using the factory constructor + /// [MoorChatDatabase.connect] created on a background isolate. + /// + /// Generally used with [ConnectionMode.background]. + static Future constructMoorChatDatabase( String userId, { bool logStatements = false, }) async { diff --git a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart index b014c833..303d925f 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart @@ -1,15 +1,21 @@ -//ignore_for_file: public_member_api_docs -//ignore_for_file: always_declare_return_types +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; +/// A Helper class to construct new instances of [MoorChatDatabase] class SharedDB { - static constructDatabase( + /// Returns a new instance of database. + /// + /// Generally used with [ConnectionMode.regular]. + static dynamic constructDatabase( String userId, { bool logStatements = false, }) { throw 'Unsupported Platform'; } - static constructOfflineStorage( + /// Return a new instance of moor chat database. + /// + /// Generally used with [ConnectionMode.background]. + static dynamic constructMoorChatDatabase( String userId, { bool logStatements = false, }) { diff --git a/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart index e30d08ea..6f4360c0 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart @@ -1,11 +1,15 @@ -//ignore_for_file: public_member_api_docs -//ignore_for_file: always_declare_return_types import 'package:moor/moor_web.dart'; +import 'package:stream_chat_persistence/src/stream_chat_persistence_client.dart'; import '../moor_chat_database.dart'; +/// A Helper class to construct new instances of [MoorChatDatabase] specifically +/// for Web applications class SharedDB { - static constructDatabase( + /// Returns a new instance of [WebDatabase] created using [userId]. + /// + /// Generally used with [ConnectionMode.regular]. + static Future constructDatabase( String userId, { bool logStatements = false, }) async { @@ -13,7 +17,11 @@ class SharedDB { return WebDatabase(dbName, logStatements: logStatements); } - static Future constructOfflineStorage( + /// Returns a new instance of [MoorChatDatabase] creating using the + /// default constructor. + /// + /// Generally used with [ConnectionMode.background]. + static Future constructMoorChatDatabase( String userId, { bool logStatements = false, }) async { diff --git a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart index ebad74f8..0962c9ac 100644 --- a/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart +++ b/packages/stream_chat_persistence/lib/src/stream_chat_persistence_client.dart @@ -43,7 +43,7 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { return; case ConnectionMode.background: _logger.info('Connecting on background isolate'); - _db = await SharedDB.constructOfflineStorage(userId); + _db = await SharedDB.constructMoorChatDatabase(userId); return; } } diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index b8e49170..0702431b 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -20,3 +20,4 @@ dev_dependencies: test: ^1.15.7 build_runner: ^1.11.0 moor_generator: ^3.4.1 + pedantic: ^1.9.2 From e68a512a3bee4330ca5c1142d8da1b0553fb8b9d Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 13:58:45 +0530 Subject: [PATCH 35/46] Fix analyzer warnings Signed-off-by: Sahil Kumar --- packages/dart_client/lib/src/client.dart | 11 ++--- packages/dart_client/pubspec.yaml | 2 +- .../example/lib/advanced_options_page.dart | 11 ----- .../example/lib/choose_user_page.dart | 6 --- .../flutter_widgets/example/lib/main.dart | 4 -- .../example/lib/notifications_service.dart | 44 ------------------- packages/flutter_widgets/pubspec.yaml | 3 +- .../stream_chat_flutter_core/pubspec.yaml | 1 + 8 files changed, 9 insertions(+), 73 deletions(-) diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index 381d1cd6..67b3f444 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -8,7 +8,6 @@ import 'package:logging/logging.dart'; import 'package:rxdart/rxdart.dart'; import 'package:stream_chat/src/api/retry_policy.dart'; import 'package:stream_chat/src/event_type.dart'; -import 'package:stream_chat/src/models/channel_model.dart'; import 'package:stream_chat/src/models/own_user.dart'; import 'package:stream_chat/version.dart'; import 'package:uuid/uuid.dart'; @@ -460,10 +459,12 @@ class Client { _connectionStatusHandler = (ConnectionStatus status) async { _wsConnectionStatus = status; - handleEvent(Event( - type: EventType.connectionChanged, - online: status == ConnectionStatus.connected, - )); + handleEvent( + Event( + type: EventType.connectionChanged, + online: status == ConnectionStatus.connected, + ), + ); if (status == ConnectionStatus.connected && state.channels?.isNotEmpty == true) { diff --git a/packages/dart_client/pubspec.yaml b/packages/dart_client/pubspec.yaml index 9cdc130f..e9036a09 100644 --- a/packages/dart_client/pubspec.yaml +++ b/packages/dart_client/pubspec.yaml @@ -17,10 +17,10 @@ dependencies: async: ^2.4.1 rxdart: ^0.24.1 collection: ^1.14.12 - pedantic: ^1.9.2 dev_dependencies: build_runner: ^1.10.0 json_serializable: ^3.3.0 test: ^1.15.7 mockito: ^4.1.1 + pedantic: ^1.9.2 diff --git a/packages/flutter_widgets/example/lib/advanced_options_page.dart b/packages/flutter_widgets/example/lib/advanced_options_page.dart index 0b55212c..35e2af7f 100644 --- a/packages/flutter_widgets/example/lib/advanced_options_page.dart +++ b/packages/flutter_widgets/example/lib/advanced_options_page.dart @@ -1,19 +1,12 @@ -import 'dart:io'; - -import 'package:example/routes/app_routes.dart'; import 'package:example/routes/routes.dart'; import 'package:example/stream_version.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'package:stream_chat_persistence/stream_chat_persistence.dart'; -import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'choose_user_page.dart'; import 'main.dart'; -import 'notifications_service.dart'; class AdvancedOptionsPage extends StatefulWidget { @override @@ -287,10 +280,6 @@ class _AdvancedOptionsPageState extends State { userToken, ); - if (!kIsWeb) { - initNotifications(client); - } - final secureStorage = FlutterSecureStorage(); secureStorage.write( key: kStreamApiKey, diff --git a/packages/flutter_widgets/example/lib/choose_user_page.dart b/packages/flutter_widgets/example/lib/choose_user_page.dart index 8e36e748..02852c64 100644 --- a/packages/flutter_widgets/example/lib/choose_user_page.dart +++ b/packages/flutter_widgets/example/lib/choose_user_page.dart @@ -1,11 +1,9 @@ import 'package:example/stream_version.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -import 'notifications_service.dart'; import 'routes/routes.dart'; const kStreamApiKey = 'STREAM_API_KEY'; @@ -187,10 +185,6 @@ class ChooseUserPage extends StatelessWidget { key: kStreamToken, value: token, ); - - if (!kIsWeb) { - initNotifications(client); - } Navigator.pushNamedAndRemoveUntil( context, Routes.HOME, diff --git a/packages/flutter_widgets/example/lib/main.dart b/packages/flutter_widgets/example/lib/main.dart index a44a8692..93c7b082 100644 --- a/packages/flutter_widgets/example/lib/main.dart +++ b/packages/flutter_widgets/example/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:example/chat_info_screen.dart'; import 'package:example/choose_user_page.dart'; @@ -41,9 +40,6 @@ void main() async { User(id: userId), token, ); - if (!kIsWeb) { - initNotifications(client); - } } runApp(MyApp(client)); diff --git a/packages/flutter_widgets/example/lib/notifications_service.dart b/packages/flutter_widgets/example/lib/notifications_service.dart index e74a2a5a..246923df 100644 --- a/packages/flutter_widgets/example/lib/notifications_service.dart +++ b/packages/flutter_widgets/example/lib/notifications_service.dart @@ -1,8 +1,3 @@ -import 'dart:io'; - -import 'package:example/main.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter_apns/flutter_apns.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -34,42 +29,3 @@ void showLocalNotification(Event event) async { ), ); } - -Future backgroundHandler(Map notification) async { - print('new notification ${notification}'); - // final messageId = notification['data']['id']; - // - // final notificationData = await NotificationService.getAndStoreMessage( - // messageId: messageId, - // storeMessageHandler: (messageResponse) { - // return chatPersistentClient.updateChannelState( - // ChannelState( - // messages: [messageResponse.message], - // channel: messageResponse.channel, - // ), - // ); - // }, - // ); - // - // showLocalNotification( - // notificationData.message, - // notificationData.channel, - // ); -} - -void initNotifications(Client client) { - final connector = createPushConnector(); - connector.configure( - onBackgroundMessage: backgroundHandler, - ); - - connector.requestNotificationPermissions(); - connector.token.addListener(() { - if (connector.token.value != null) { - client.addDevice( - connector.token.value, - Platform.isAndroid ? PushProvider.firebase : PushProvider.apn, - ); - } - }); -} diff --git a/packages/flutter_widgets/pubspec.yaml b/packages/flutter_widgets/pubspec.yaml index 9321f992..af2e39f4 100644 --- a/packages/flutter_widgets/pubspec.yaml +++ b/packages/flutter_widgets/pubspec.yaml @@ -58,8 +58,7 @@ flutter: - animations/ dev_dependencies: - flutter_test: sdk: flutter mockito: ^4.1.3 - pedantic: ^1.9.2 + pedantic: ^1.9.2 \ No newline at end of file diff --git a/packages/stream_chat_flutter_core/pubspec.yaml b/packages/stream_chat_flutter_core/pubspec.yaml index 61c3528e..6dbde76e 100644 --- a/packages/stream_chat_flutter_core/pubspec.yaml +++ b/packages/stream_chat_flutter_core/pubspec.yaml @@ -20,4 +20,5 @@ dev_dependencies: flutter_test: sdk: flutter fake_async: ^1.1.0 + pedantic: ^1.9.2 \ No newline at end of file From e03f50ae5abde62ef201ec07b48e652be43bf26e Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 14:06:30 +0530 Subject: [PATCH 36/46] [StreamChatFlutter -> ConnectionStatusBuilder] Add docs Signed-off-by: Sahil Kumar --- .../flutter_widgets/lib/src/connection_status_builder.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/flutter_widgets/lib/src/connection_status_builder.dart b/packages/flutter_widgets/lib/src/connection_status_builder.dart index 25f9a0b6..ebb12cd5 100644 --- a/packages/flutter_widgets/lib/src/connection_status_builder.dart +++ b/packages/flutter_widgets/lib/src/connection_status_builder.dart @@ -2,6 +2,11 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'stream_chat.dart'; +/// Widget that builds itself based on the latest snapshot of interaction with +/// a [Stream] of type [ConnectionStatus]. +/// +/// The widget will use the closest [Client.wsConnectionStatusStream] in case no +/// stream is provided. class ConnectionStatusBuilder extends StatelessWidget { /// Creates a new ConnectionStatusBuilder const ConnectionStatusBuilder({ From 0d4db879060d5915d30dc0ddf87f691b08d62638 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 1 Feb 2021 09:55:53 +0100 Subject: [PATCH 37/46] check messagePagination nullability --- .../stream_chat_persistence/lib/src/dao/message_dao.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart index 8acdbfd4..97122232 100644 --- a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -112,7 +112,7 @@ class MessageDao extends DatabaseAccessor .map(_messageFromJoinRow) .get()); - if (messagePagination.lessThan != null) { + if (messagePagination?.lessThan != null) { final lessThanIndex = msgList.indexWhere( (m) => m.id == messagePagination.lessThan, ); @@ -120,7 +120,7 @@ class MessageDao extends DatabaseAccessor msgList.removeRange(lessThanIndex, msgList.length); } } - if (messagePagination.greaterThanOrEqual != null) { + if (messagePagination?.greaterThanOrEqual != null) { final greaterThanIndex = msgList.indexWhere( (m) => m.id == messagePagination.greaterThanOrEqual, ); @@ -128,7 +128,7 @@ class MessageDao extends DatabaseAccessor msgList.removeRange(0, greaterThanIndex); } } - if (messagePagination.limit != null) { + if (messagePagination?.limit != null) { return msgList.take(messagePagination.limit).toList(); } return msgList; From dcdaefe76e289c61964930ac6a5a66aafef8d006 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 14:42:34 +0530 Subject: [PATCH 38/46] [StreamChat -> ChatPersistenceClient] Add doc comments Signed-off-by: Sahil Kumar --- .../lib/src/db/chat_persistence_client.dart | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/dart_client/lib/src/db/chat_persistence_client.dart b/packages/dart_client/lib/src/db/chat_persistence_client.dart index 070bf37f..c4ce6cd2 100644 --- a/packages/dart_client/lib/src/db/chat_persistence_client.dart +++ b/packages/dart_client/lib/src/db/chat_persistence_client.dart @@ -8,7 +8,7 @@ import 'package:stream_chat/src/models/reaction.dart'; import 'package:stream_chat/src/models/read.dart'; import 'package:stream_chat/src/models/user.dart'; -/// +/// A simple client used for persisting chat data locally. abstract class ChatPersistenceClient { /// Creates a new connection to the client Future connect(String userId); @@ -38,22 +38,25 @@ abstract class ChatPersistenceClient { /// Get the channel cids saved in the offline storage Future> getChannelCids(); - /// + /// Get stored [ChannelModel]s by providing channel [cid] Future getChannelByCid(String cid); - /// + /// Get stored channel [Member]s by providing channel [cid] Future> getMembersByCid(String cid); - /// + /// Get stored channel [Read]s by providing channel [cid] Future> getReadsByCid(String cid); + /// Get stored [Message]s by providing channel [cid] /// + /// Optionally, you can [messagePagination] + /// for filtering out messages Future> getMessagesByCid( String cid, { PaginationParams messagePagination, }); - /// Get channel data by cid + /// Get [ChannelState] data by providing channel [cid] Future getChannelStateByCid( String cid, { PaginationParams messagePagination, @@ -73,14 +76,18 @@ abstract class ChatPersistenceClient { ); } - /// Get list of channels by filter, sort and paginationParams + /// Get all the stored [ChannelState]s + /// + /// Optionally, pass [filter], [sort], [paginationParams] + /// for filtering out states. Future> getChannelStates({ Map filter, List sort = const [], PaginationParams paginationParams, }); - /// Update list of channel queries + /// Update list of channel queries. + /// /// If [clearQueryCache] is true before the insert /// the list of matching rows will be deleted Future updateChannelQueries( @@ -89,53 +96,57 @@ abstract class ChatPersistenceClient { bool clearQueryCache, ); - /// Remove a message by message id + /// Remove a message by [messageId] Future deleteMessageById(String messageId) { return deleteMessageByIds([messageId]); } - /// Remove a message by message ids + /// Remove a message by [messageIds] Future deleteMessageByIds(List messageIds); - /// Remove a message by channel cid + /// Remove a message by channel [cid] Future deleteMessageByCid(String cid) { return deleteMessageByCids([cid]); } - /// Remove a message by message cids + /// Remove a message by message [cids] Future deleteMessageByCids(List cids); - /// Remove a channel by cid + /// Remove a channel by [cid] Future deleteChannels(List cids); - /// Update messages data from a list + /// Updates the message data of a particular channel [cid] with + /// the new [messages] data Future updateMessages(String cid, List messages); - /// Get the info about channel threads + /// Returns all the threads by parent message of a particular channel by + /// providing channel [cid] Future>> getChannelThreads(String cid); - /// + /// Updates all the channels using the new [channels] data. Future updateChannels(List channels); - /// + /// Updates all the members of a particular channle [cid] + /// with the new [members] data Future updateMembers(String cid, List members); - /// + /// Updates the read data of a particular channel [cid] with + /// the new [reads] data Future updateReads(String cid, List reads); - /// + /// Updates the users data with the new [users] data Future updateUsers(List users); - /// + /// Updates the reactions data with the new [reactions] data Future updateReactions(List reactions); - /// + /// Deletes all the reactions by [messageIds] Future deleteReactionsByMessageId(List messageIds); - /// + /// Deletes all the members by channel [cids] Future deleteMembersByCids(List cids); - /// + /// Update the channel state data using [channelState] Future updateChannelState(ChannelState channelState) { return updateChannelStates([channelState]); } From 206f63ff8419b85429600f21e78dce2032b4ab07 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 14:50:01 +0530 Subject: [PATCH 39/46] [StreamChatCore] Move `EventHandler` into typedef.dart Signed-off-by: Sahil Kumar --- .../stream_chat_flutter_core/lib/src/stream_chat_core.dart | 2 +- packages/stream_chat_flutter_core/lib/src/typedef.dart | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart index e17fe708..78cae0ba 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; -typedef EventHandler = void Function(Event event); +import 'typedef.dart'; /// Widget used to provide information about the chat to the widget tree. /// This Widget is used to react to life cycle changes and system updates. diff --git a/packages/stream_chat_flutter_core/lib/src/typedef.dart b/packages/stream_chat_flutter_core/lib/src/typedef.dart index 3077574e..29fb2d31 100644 --- a/packages/stream_chat_flutter_core/lib/src/typedef.dart +++ b/packages/stream_chat_flutter_core/lib/src/typedef.dart @@ -1,6 +1,10 @@ import 'package:flutter/widgets.dart'; +import 'package:stream_chat/stream_chat.dart'; /// A signature for a callback which exposes an error and returns a function. /// This Callback can be used in cases where an API failure occurs and the widget /// is unable to render data. typedef ErrorBuilder = Widget Function(BuildContext context, Object error); + +/// A Signature for a handler function which will expose a [event]. +typedef EventHandler = void Function(Event event); From e05097a91424f2693b90afee1a90b2c333c710c6 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 14:58:46 +0530 Subject: [PATCH 40/46] fix tests Signed-off-by: Sahil Kumar --- .../stream_chat_flutter_core/lib/stream_chat_flutter_core.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart b/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart index 623c4424..48d31b45 100644 --- a/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart +++ b/packages/stream_chat_flutter_core/lib/stream_chat_flutter_core.dart @@ -10,4 +10,5 @@ export 'src/stream_channel.dart'; export 'src/stream_chat_core.dart'; export 'src/user_list_core.dart'; export 'src/users_bloc.dart'; +export 'src/typedef.dart'; export 'package:stream_chat/stream_chat.dart'; From b791040960039e7f36ad703fdc8e8f0bc472fc74 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 1 Feb 2021 12:17:02 +0100 Subject: [PATCH 41/46] await deleting actions before update --- .../lib/src/db/chat_persistence_client.dart | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/dart_client/lib/src/db/chat_persistence_client.dart b/packages/dart_client/lib/src/db/chat_persistence_client.dart index c4ce6cd2..e240f9e6 100644 --- a/packages/dart_client/lib/src/db/chat_persistence_client.dart +++ b/packages/dart_client/lib/src/db/chat_persistence_client.dart @@ -164,6 +164,20 @@ abstract class ChatPersistenceClient { ]; }).where((it) => it != null); + final deleteReactions = deleteReactionsByMessageId(channelStates + .expand((it) => it.messages) + .map((m) => m.id) + .toList(growable: false)); + + final deleteMembers = deleteMembersByCids( + channelStates.map((it) => it.channel.cid).toList(growable: false), + ); + + await Future.wait([ + deleteReactions, + deleteMembers, + ]); + final users = channelStates .map((cs) => [ cs.channel?.createdBy, @@ -198,19 +212,6 @@ abstract class ChatPersistenceClient { return updateMembers(cid, members.toList(growable: false)); }).toList(growable: false); - final deleteReactions = deleteReactionsByMessageId(channelStates - .expand((it) => it.messages) - .map((m) => m.id) - .toList(growable: false)); - - final deleteMembers = deleteMembersByCids( - channelStates.map((it) => it.channel.cid).toList(growable: false), - ); - - await Future.wait([ - deleteReactions, - deleteMembers, - ]); await Future.wait([ ...updateMessagesFuture, ...updateReadsFuture, From c8319004843adcd3b3ce563dbc9d9a249d164b79 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 18:32:22 +0530 Subject: [PATCH 42/46] [Persistence] Minor refactoring Signed-off-by: Sahil Kumar --- .../lib/src/db/chat_persistence_client.dart | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/dart_client/lib/src/db/chat_persistence_client.dart b/packages/dart_client/lib/src/db/chat_persistence_client.dart index e240f9e6..a2a4d313 100644 --- a/packages/dart_client/lib/src/db/chat_persistence_client.dart +++ b/packages/dart_client/lib/src/db/chat_persistence_client.dart @@ -153,17 +153,6 @@ abstract class ChatPersistenceClient { /// Update list of channel states Future updateChannelStates(List channelStates) async { - final channels = channelStates.map((it) { - return it.channel; - }).where((it) => it != null); - - final reactions = channelStates.expand((it) => it.messages).expand((it) { - return [ - ...it.ownReactions.where((r) => r.userId != null), - ...it.latestReactions.where((r) => r.userId != null) - ]; - }).where((it) => it != null); - final deleteReactions = deleteReactionsByMessageId(channelStates .expand((it) => it.messages) .map((m) => m.id) @@ -178,6 +167,17 @@ abstract class ChatPersistenceClient { deleteMembers, ]); + final channels = channelStates.map((it) { + return it.channel; + }).where((it) => it != null); + + final reactions = channelStates.expand((it) => it.messages).expand((it) { + return [ + ...it.ownReactions.where((r) => r.userId != null), + ...it.latestReactions.where((r) => r.userId != null) + ]; + }).where((it) => it != null); + final users = channelStates .map((cs) => [ cs.channel?.createdBy, From fe45b2ef6e21b8a36934591abf314522137c238b Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 1 Feb 2021 19:11:57 +0530 Subject: [PATCH 43/46] Update README.md Signed-off-by: Sahil Kumar --- packages/flutter_widgets/README.md | 2 +- packages/stream_chat_flutter_core/README.md | 2 +- packages/stream_chat_persistence/README.md | 59 +++++++++++++++++---- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/packages/flutter_widgets/README.md b/packages/flutter_widgets/README.md index 8104e83a..b99a8f29 100644 --- a/packages/flutter_widgets/README.md +++ b/packages/flutter_widgets/README.md @@ -1,7 +1,7 @@ # Official Flutter SDK for [Stream Chat](https://getstream.io/chat/)

- Flutter Chat + Flutter Chat

> The official Flutter components for Stream Chat, a service for diff --git a/packages/stream_chat_flutter_core/README.md b/packages/stream_chat_flutter_core/README.md index a62da863..6fe86329 100644 --- a/packages/stream_chat_flutter_core/README.md +++ b/packages/stream_chat_flutter_core/README.md @@ -1,7 +1,7 @@ # Official Flutter SDK Core for [Stream Chat](https://getstream.io/chat/)

- Flutter Chat + Flutter Chat

> The official Flutter core components for Stream Chat, a service for diff --git a/packages/stream_chat_persistence/README.md b/packages/stream_chat_persistence/README.md index 3e3f0c7c..6d9c21cf 100644 --- a/packages/stream_chat_persistence/README.md +++ b/packages/stream_chat_persistence/README.md @@ -1,14 +1,53 @@ -# stream_chat_persistence +# Official Chat Persistence Client for [Stream Chat](https://getstream.io/chat/) -A new Flutter package. +

+ Flutter Chat +

-## Getting Started +> The official Chat Persistence Client for Stream Chat, a service for +> building chat applications. -This project is a starting point for a Dart -[package](https://flutter.dev/developing-packages/), -a library module containing code that can be shared easily across -multiple Flutter or Dart projects. +[![Pub](https://img.shields.io/pub/v/stream_chat_persistence.svg)](https://pub.dartlang.org/packages/stream_chat_persistence) +![](https://img.shields.io/badge/platform-flutter%20%7C%20flutter%20web-ff69b4.svg?style=flat-square) +[![Gitter](https://badges.gitter.im/GetStream/stream_chat_persistence.svg)](https://gitter.im/GetStream/stream-chat-flutter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +![CI](https://github.com/GetStream/stream-chat-flutter/workflows/CI/badge.svg?branch=master) + -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +This package provides a persistence client for fetching and saving chat data locally. +Stream Chat Persistence uses [Moor](https://github.com/simolus3/moor) as a disk cache. + +## Add dependency +Add this to your package's pubspec.yaml file, use the latest version [![Pub](https://img.shields.io/pub/v/stream_chat_persistence.svg)](https://pub.dartlang.org/packages/stream_chat_persistence) +```yaml +dependencies: + stream_chat_persistence: ^latest_version +``` + +You should then run `flutter packages get` + +## Usage +The usage is pretty simple. +1. Create a new instance of StreamChatPersistenceClient providing `logLevel` and `connectionMode`. +```dart +final chatPersistentClient = StreamChatPersistenceClient( + logLevel: Level.INFO, + connectionMode: ConnectionMode.background, +); +``` +2. Pass the instance to the official Stream chat client. +```dart + final client = Client( + apiKey ?? kDefaultStreamApiKey, + logLevel: Level.INFO, + )..chatPersistenceClient = chatPersistentClient; +``` + +And you are ready to go... + +## Contributing + +We welcome code changes that improve this library or fix a problem, +please make sure to follow all best practices and add tests if applicable before submitting a Pull Request on Github. +We are pleased to merge your code into the official repository. +Make sure to sign our [Contributor License Agreement (CLA)](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) first. +See our license file for more details. From 4e6d64064e6ab9aaff1185a45da8125f0798125b Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 1 Feb 2021 15:13:59 +0100 Subject: [PATCH 44/46] [llc] update changelog and readme --- packages/dart_client/CHANGELOG.md | 9 +++++ packages/dart_client/README.md | 43 +++++++++++++--------- packages/stream_chat_persistence/README.md | 18 +++++++++ 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/packages/dart_client/CHANGELOG.md b/packages/dart_client/CHANGELOG.md index fdaee098..c51f9a5f 100644 --- a/packages/dart_client/CHANGELOG.md +++ b/packages/dart_client/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.1.0-beta + +- 🛑 **BREAKING** Renamed `Client` to less generic `StreamChatClient` +- 🛑 **BREAKING** Segregated the persistence layer into separate package (stream_chat_persistence)[https://pub.dev/packages/stream_chat_persistence] +- 🛑 **BREAKING** Moved `Client.backgroundKeepAlive` to (core package)[https://pub.dev/packages/stream_chat_core] +- 🛑 **BREAKING** Moved `Client.showLocalNotification` to (core package)[https://pub.dev/packages/stream_chat_core] and renamed it to `StreamChatCore.onBackgroundEventReceived` +- Removed `flutter` dependency. This is now a pure Dart package 🥳 +- Minor improvements and bugfixes + ## 0.2.24+2 - Fix reconnection bug while using tokenProvider diff --git a/packages/dart_client/README.md b/packages/dart_client/README.md index 241c2f4e..4d3ca397 100644 --- a/packages/dart_client/README.md +++ b/packages/dart_client/README.md @@ -14,7 +14,7 @@ You can sign up for a Stream account at https://getstream.io/chat/ ```yaml dependencies: - stream_chat: ^0.2.0 + stream_chat: ^1.0.0-beta ``` You should then run `flutter packages get` @@ -57,27 +57,34 @@ final client = Client("stream-chat-api-key", logHandlerFunction: myLogHandlerFun ### Offline storage -By default the library saves information about channels and messages in a SQLite DB. +To add data persistance you can extend the class `ChatPersistenceClient` and pass an instance to the `StreamChatClient`. -Set the property `persistenceEnabled` to false if you don't want to use the offline storage. +```dart +class CustomChatPersistentClient extends ChatPersistenceClient { +... +} -## Flutter Web - -Due to Moor web (for offline storage) you need to include the sql.js library: - -```html - - - - - - - - - +final client = Client( + apiKey ?? kDefaultStreamApiKey, + logLevel: Level.INFO, +)..chatPersistenceClient = CustomChatPersistentClient(); ``` -You can grab the latest version of sql-wasm.js and sql-wasm.wasm [here](https://github.com/sql-js/sql.js/releases) and copy them into your `/web` folder. +We provide an official persistent client in the (stream_chat_persistence)[https://pub.dev/packages/stream_chat_persistence] package. + +```dart +import 'package:stream_chat_persistence/stream_chat_persistence.dart'; + +final chatPersistentClient = StreamChatPersistenceClient( + logLevel: Level.INFO, + connectionMode: ConnectionMode.background, +); + +final client = Client( + apiKey ?? kDefaultStreamApiKey, + logLevel: Level.INFO, +)..chatPersistenceClient = chatPersistentClient; +``` ## Contributing diff --git a/packages/stream_chat_persistence/README.md b/packages/stream_chat_persistence/README.md index 6d9c21cf..d53d51e4 100644 --- a/packages/stream_chat_persistence/README.md +++ b/packages/stream_chat_persistence/README.md @@ -44,6 +44,24 @@ final chatPersistentClient = StreamChatPersistenceClient( And you are ready to go... +## Flutter Web + +Due to Moor web (for offline storage) you need to include the sql.js library: + +```html + + + + + + + + + +``` + +You can grab the latest version of sql-wasm.js and sql-wasm.wasm [here](https://github.com/sql-js/sql.js/releases) and copy them into your `/web` folder. + ## Contributing We welcome code changes that improve this library or fix a problem, From 1751cd6092bc3f96ee0dd74a1159016aa95070d3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 1 Feb 2021 15:15:28 +0100 Subject: [PATCH 45/46] change rc to beta --- packages/dart_client/CHANGELOG.md | 2 +- packages/stream_chat_flutter_core/CHANGELOG.md | 2 +- packages/stream_chat_flutter_core/pubspec.yaml | 2 +- packages/stream_chat_persistence/CHANGELOG.md | 2 +- packages/stream_chat_persistence/pubspec.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/dart_client/CHANGELOG.md b/packages/dart_client/CHANGELOG.md index c51f9a5f..98730359 100644 --- a/packages/dart_client/CHANGELOG.md +++ b/packages/dart_client/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.1.0-beta +## 1.0.0-beta - 🛑 **BREAKING** Renamed `Client` to less generic `StreamChatClient` - 🛑 **BREAKING** Segregated the persistence layer into separate package (stream_chat_persistence)[https://pub.dev/packages/stream_chat_persistence] diff --git a/packages/stream_chat_flutter_core/CHANGELOG.md b/packages/stream_chat_flutter_core/CHANGELOG.md index ec6ae55e..819c0e5a 100644 --- a/packages/stream_chat_flutter_core/CHANGELOG.md +++ b/packages/stream_chat_flutter_core/CHANGELOG.md @@ -1,3 +1,3 @@ -## 1.0.0-rc +## 1.0.0-beta * First release diff --git a/packages/stream_chat_flutter_core/pubspec.yaml b/packages/stream_chat_flutter_core/pubspec.yaml index 6dbde76e..cf7fb31d 100644 --- a/packages/stream_chat_flutter_core/pubspec.yaml +++ b/packages/stream_chat_flutter_core/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter_core homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK Core. Build your own chat experience using Dart and Flutter. -version: 1.0.0-rc +version: 1.0.0-beta repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md index ba22fd4f..72eec406 100644 --- a/packages/stream_chat_persistence/CHANGELOG.md +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -1,3 +1,3 @@ -## 1.0.0-rc +## 1.0.0-beta * Initial release \ No newline at end of file diff --git a/packages/stream_chat_persistence/pubspec.yaml b/packages/stream_chat_persistence/pubspec.yaml index 0702431b..06015495 100644 --- a/packages/stream_chat_persistence/pubspec.yaml +++ b/packages/stream_chat_persistence/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_persistence homepage: https://github.com/GetStream/stream-chat-flutter description: Official Stream Chat Persistence library. Build your own chat experience using Dart and Flutter. -version: 1.0.0-rc +version: 1.0.0-beta repository: https://github.com/GetStream/stream-chat-flutter issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues From 23feabe85ec18dc09eb7feb1ac31325e438b0b03 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 1 Feb 2021 15:30:46 +0100 Subject: [PATCH 46/46] rename Client to StreamChatClient --- melos.yaml | 8 +- packages/dart_client/README.md | 10 +-- packages/dart_client/example/lib/main.dart | 12 +-- packages/dart_client/lib/src/api/channel.dart | 6 +- .../dart_client/lib/src/api/responses.dart | 22 +++--- .../dart_client/lib/src/api/retry_policy.dart | 11 +-- packages/dart_client/lib/src/client.dart | 25 +++--- packages/dart_client/lib/version.dart | 2 +- .../test/src/api/channel_test.dart | 66 ++++++++-------- .../dart_client/test/src/client_test.dart | 78 +++++++++---------- packages/flutter_widgets/README.md | 4 +- .../example/lib/advanced_options_page.dart | 2 +- .../example/lib/custom_message.dart | 4 +- .../example/lib/custom_theme.dart | 4 +- .../lib/customize_channel_preview.dart | 4 +- .../example/lib/customize_message_widget.dart | 4 +- .../flutter_widgets/example/lib/main.dart | 4 +- .../example/lib/multiple_conversation.dart | 4 +- .../example/lib/single_conversation.dart | 12 +-- .../example/lib/split_view.dart | 4 +- .../flutter_widgets/example/lib/threads.dart | 4 +- .../lib/src/channel_header.dart | 6 +- .../lib/src/channel_image.dart | 4 +- .../flutter_widgets/lib/src/channel_info.dart | 3 +- .../lib/src/channel_list_header.dart | 19 ++--- .../lib/src/connection_status_builder.dart | 3 +- .../flutter_widgets/lib/src/stream_chat.dart | 8 +- packages/flutter_widgets/test/src/mocks.dart | 2 +- .../example/lib/main.dart | 12 +-- .../lib/src/message_search_bloc.dart | 4 +- .../lib/src/stream_chat_core.dart | 6 +- .../stream_chat_flutter_core/test/mocks.dart | 2 +- packages/stream_chat_persistence/README.md | 2 +- 33 files changed, 185 insertions(+), 176 deletions(-) diff --git a/melos.yaml b/melos.yaml index 7e02909f..6a6c74dc 100644 --- a/melos.yaml +++ b/melos.yaml @@ -33,8 +33,12 @@ scripts: flutter build macos - test: > - melos exec -c 1 --fail-fast --dir-exists=test --ignore="*example*" --ignore="*web*" -- \ + test:dart: > + melos exec -c 1 --fail-fast --no-flutter --dir-exists=test --ignore="*example*" --ignore="*web*" -- \ + flutter pub run test + + test:flutter: > + melos exec -c 1 --fail-fast --flutter --dir-exists=test --ignore="*example*" --ignore="*web*" -- \ flutter test test:web: > diff --git a/packages/dart_client/README.md b/packages/dart_client/README.md index 4d3ca397..e0ed18bf 100644 --- a/packages/dart_client/README.md +++ b/packages/dart_client/README.md @@ -28,7 +28,7 @@ There is a detailed Flutter example project in the `example` folder. You can dir First you need to instantiate a chat client. The Chat client will manage API call, event handling and manage the websocket connection to Stream Chat servers. You should only create the client once and re-use it across your application. ```dart -final client = Client("stream-chat-api-key"); +final client = StreamChatClient("stream-chat-api-key"); ``` ### Logging @@ -40,7 +40,7 @@ By default the Chat Client will write all messages with level Warn or Error to s During development you might want to enable more logging information, you can change the default log level when constructing the client. ```dart -final client = Client("stream-chat-api-key", logLevel: Level.INFO); +final client = StreamChatClient("stream-chat-api-key", logLevel: Level.INFO); ``` #### Custom Logger @@ -52,7 +52,7 @@ myLogHandlerFunction = (LogRecord record) { // do something with the record (ie. send it to Sentry or Fabric) } -final client = Client("stream-chat-api-key", logHandlerFunction: myLogHandlerFunction); +final client = StreamChatClient("stream-chat-api-key", logHandlerFunction: myLogHandlerFunction); ``` ### Offline storage @@ -64,7 +64,7 @@ class CustomChatPersistentClient extends ChatPersistenceClient { ... } -final client = Client( +final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, logLevel: Level.INFO, )..chatPersistenceClient = CustomChatPersistentClient(); @@ -80,7 +80,7 @@ final chatPersistentClient = StreamChatPersistenceClient( connectionMode: ConnectionMode.background, ); -final client = Client( +final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, logLevel: Level.INFO, )..chatPersistenceClient = chatPersistentClient; diff --git a/packages/dart_client/example/lib/main.dart b/packages/dart_client/example/lib/main.dart index ed21df76..769e6d44 100644 --- a/packages/dart_client/example/lib/main.dart +++ b/packages/dart_client/example/lib/main.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; Future main() async { - /// Create a new instance of [Client] passing the apikey obtained from your + /// Create a new instance of [StreamChatClient] passing the apikey obtained from your /// project dashboard. - final client = Client('b67pax5b2wdq'); + final client = StreamChatClient('b67pax5b2wdq'); /// Set the current user. In a production scenario, this should be done using /// a backend to generate a user token using our server SDK. @@ -48,9 +48,9 @@ class StreamExample extends StatelessWidget { @required this.channel, }) : super(key: key); - /// Instance of [Client] we created earlier. This contains information about + /// Instance of [StreamChatClient] we created earlier. This contains information about /// our application and connection state. - final Client client; + final StreamChatClient client; /// The channel we'd like to observe and participate. final Channel channel; @@ -242,7 +242,7 @@ class _MessageViewState extends State { } } -/// Helper extension for quickly retrieving the current user id from a [Client]. -extension on Client { +/// Helper extension for quickly retrieving the current user id from a [StreamChatClient]. +extension on StreamChatClient { String get uid => state.user.id; } diff --git a/packages/dart_client/lib/src/api/channel.dart b/packages/dart_client/lib/src/api/channel.dart index 45dd5da8..449a5267 100644 --- a/packages/dart_client/lib/src/api/channel.dart +++ b/packages/dart_client/lib/src/api/channel.dart @@ -160,8 +160,8 @@ class Channel { state?.channelStateStream?.map((cs) => cs.channel?.extraData); /// The main Stream chat client - Client get client => _client; - final Client _client; + StreamChatClient get client => _client; + final StreamChatClient _client; String get _channelURL => '/channels/$type/$id'; @@ -722,7 +722,7 @@ class Channel { }); } - /// Hides the channel from [Client.queryChannels] for the user until a message is added + /// 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 { _checkInitialized(); diff --git a/packages/dart_client/lib/src/api/responses.dart b/packages/dart_client/lib/src/api/responses.dart index 919a875b..e27ac2c9 100644 --- a/packages/dart_client/lib/src/api/responses.dart +++ b/packages/dart_client/lib/src/api/responses.dart @@ -17,7 +17,7 @@ class _BaseResponse { String duration; } -/// Model response for [Client.resync] api call +/// Model response for [StreamChatClient.resync] api call @JsonSerializable(createToJson: false) class SyncResponse extends _BaseResponse { /// The list of events @@ -28,7 +28,7 @@ class SyncResponse extends _BaseResponse { _$SyncResponseFromJson(json); } -/// Model response for [Client.queryChannels] api call +/// Model response for [StreamChatClient.queryChannels] api call @JsonSerializable(createToJson: false) class QueryChannelsResponse extends _BaseResponse { /// List of channels state returned by the query @@ -39,7 +39,7 @@ class QueryChannelsResponse extends _BaseResponse { _$QueryChannelsResponseFromJson(json); } -/// Model response for [Client.queryChannels] api call +/// Model response for [StreamChatClient.queryChannels] api call @JsonSerializable(createToJson: false) class TranslateMessageResponse extends _BaseResponse { /// List of channels state returned by the query @@ -50,7 +50,7 @@ class TranslateMessageResponse extends _BaseResponse { _$TranslateMessageResponseFromJson(json); } -/// Model response for [Client.queryChannels] api call +/// Model response for [StreamChatClient.queryChannels] api call @JsonSerializable(createToJson: false) class QueryMembersResponse extends _BaseResponse { /// List of channels state returned by the query @@ -61,7 +61,7 @@ class QueryMembersResponse extends _BaseResponse { _$QueryMembersResponseFromJson(json); } -/// Model response for [Client.queryUsers] api call +/// Model response for [StreamChatClient.queryUsers] api call @JsonSerializable(createToJson: false) class QueryUsersResponse extends _BaseResponse { /// List of users returned by the query @@ -94,7 +94,7 @@ class QueryRepliesResponse extends _BaseResponse { _$QueryRepliesResponseFromJson(json); } -/// Model response for [Client.getDevices] api call +/// Model response for [StreamChatClient.getDevices] api call @JsonSerializable(createToJson: false) class ListDevicesResponse extends _BaseResponse { /// List of user devices @@ -141,7 +141,7 @@ class SendReactionResponse extends _BaseResponse { _$SendReactionResponseFromJson(json); } -/// Model response for [Client.setGuestUser] api call +/// Model response for [StreamChatClient.setGuestUser] api call @JsonSerializable(createToJson: false) class SetGuestUserResponse extends _BaseResponse { /// Guest user access token @@ -155,7 +155,7 @@ class SetGuestUserResponse extends _BaseResponse { _$SetGuestUserResponseFromJson(json); } -/// Model response for [Client.updateUser] api call +/// Model response for [StreamChatClient.updateUser] api call @JsonSerializable(createToJson: false) class UpdateUsersResponse extends _BaseResponse { /// Updated users @@ -166,7 +166,7 @@ class UpdateUsersResponse extends _BaseResponse { _$UpdateUsersResponseFromJson(json); } -/// Model response for [Client.updateMessage] api call +/// Model response for [StreamChatClient.updateMessage] api call @JsonSerializable(createToJson: false) class UpdateMessageResponse extends _BaseResponse { /// Message returned by the api call @@ -188,7 +188,7 @@ class SendMessageResponse extends _BaseResponse { _$SendMessageResponseFromJson(json); } -/// Model response for [Client.getMessage] api call +/// Model response for [StreamChatClient.getMessage] api call @JsonSerializable(createToJson: false) class GetMessageResponse extends _BaseResponse { /// Message returned by the api call @@ -208,7 +208,7 @@ class GetMessageResponse extends _BaseResponse { } } -/// Model response for [Client.search] api call +/// Model response for [StreamChatClient.search] api call @JsonSerializable(createToJson: false) class SearchMessagesResponse extends _BaseResponse { /// List of messages returned by the api call diff --git a/packages/dart_client/lib/src/api/retry_policy.dart b/packages/dart_client/lib/src/api/retry_policy.dart index 270d558c..2c59ec48 100644 --- a/packages/dart_client/lib/src/api/retry_policy.dart +++ b/packages/dart_client/lib/src/api/retry_policy.dart @@ -15,17 +15,18 @@ class RetryPolicy { int attempt = 0; /// This function evaluates if we should retry the failure - final bool Function(Client client, int attempt, ApiError apiError) + final bool Function(StreamChatClient client, int attempt, ApiError apiError) shouldRetry; /// In the case that we want to retry a failed request the retryTimeout method is called to determine the timeout - final Duration Function(Client client, int attempt, ApiError apiError) - retryTimeout; + final Duration Function( + StreamChatClient client, int attempt, ApiError apiError) retryTimeout; /// Creates a copy of [RetryPolicy] with specified attributes overridden. RetryPolicy copyWith({ - bool Function(Client client, int attempt, ApiError apiError) shouldRetry, - Duration Function(Client client, int attempt, ApiError apiError) + bool Function(StreamChatClient client, int attempt, ApiError apiError) + shouldRetry, + Duration Function(StreamChatClient client, int attempt, ApiError apiError) retryTimeout, int attempt, }) => diff --git a/packages/dart_client/lib/src/client.dart b/packages/dart_client/lib/src/client.dart index 67b3f444..7f9f560a 100644 --- a/packages/dart_client/lib/src/client.dart +++ b/packages/dart_client/lib/src/client.dart @@ -3,15 +3,15 @@ import 'dart:convert'; import 'dart:io'; import 'package:dio/dio.dart'; -import 'package:meta/meta.dart'; import 'package:logging/logging.dart'; +import 'package:meta/meta.dart'; +import 'package:pedantic/pedantic.dart' show unawaited; import 'package:rxdart/rxdart.dart'; import 'package:stream_chat/src/api/retry_policy.dart'; import 'package:stream_chat/src/event_type.dart'; import 'package:stream_chat/src/models/own_user.dart'; import 'package:stream_chat/version.dart'; import 'package:uuid/uuid.dart'; -import 'package:pedantic/pedantic.dart' show unawaited; import 'api/channel.dart'; import 'api/connection_status.dart'; @@ -64,12 +64,12 @@ extension on PushProvider { /// websocket connection to Stream Chat servers. /// /// ```dart -/// final client = Client("stream-chat-api-key"); +/// final client = StreamChatClient("stream-chat-api-key"); /// ``` -class Client { +class StreamChatClient { /// Create a client instance with default options. /// You should only create the client once and re-use it across your application. - Client( + StreamChatClient( this.apiKey, { this.tokenProvider, this.baseURL = _defaultBaseURL, @@ -81,9 +81,10 @@ class Client { RetryPolicy retryPolicy, }) { _retryPolicy ??= RetryPolicy( - retryTimeout: (Client client, int attempt, ApiError error) => + retryTimeout: (StreamChatClient client, int attempt, ApiError error) => Duration(seconds: 1 * attempt), - shouldRetry: (Client client, int attempt, ApiError error) => attempt < 5, + shouldRetry: (StreamChatClient client, int attempt, ApiError error) => + attempt < 5, ); state = ClientState(this); @@ -94,7 +95,7 @@ class Client { logger.info('instantiating new client'); } - /// Client chat persistence client + /// Chat persistence client ChatPersistenceClient chatPersistenceClient; /// Whether the chat persistence is available or not @@ -110,11 +111,11 @@ class Client { /// This client state ClientState state; - /// By default the Chat Client will write all messages with level Warn or Error to stdout. + /// By default the Chat client will write all messages with level Warn or Error to stdout. /// During development you might want to enable more logging information, you can change the default log level when constructing the client. /// /// ```dart - /// final client = Client("stream-chat-api-key", logLevel: Level.INFO); + /// final client = StreamChatClient("stream-chat-api-key", logLevel: Level.INFO); /// ``` final Level logLevel; @@ -133,7 +134,7 @@ class Client { /// // do something with the record (ie. send it to Sentry or Fabric) /// } /// - /// final client = Client("stream-chat-api-key", logHandlerFunction: myLogHandlerFunction); + /// final client = StreamChatClient("stream-chat-api-key", logHandlerFunction: myLogHandlerFunction); ///``` LogHandlerFunction logHandlerFunction; @@ -1337,7 +1338,7 @@ class ClientState { })); } - final Client _client; + final StreamChatClient _client; /// Update user information set user(OwnUser user) { diff --git a/packages/dart_client/lib/version.dart b/packages/dart_client/lib/version.dart index 1d13b723..3f084128 100644 --- a/packages/dart_client/lib/version.dart +++ b/packages/dart_client/lib/version.dart @@ -1,5 +1,5 @@ import 'package:stream_chat/src/client.dart'; /// Current package version -/// Used in [Client] to build the `x-stream-client` header +/// Used in [StreamChatClient] to build the `x-stream-client` header const PACKAGE_VERSION = '0.2.24+2'; diff --git a/packages/dart_client/test/src/api/channel_test.dart b/packages/dart_client/test/src/api/channel_test.dart index 3897eb04..4b274a94 100644 --- a/packages/dart_client/test/src/api/channel_test.dart +++ b/packages/dart_client/test/src/api/channel_test.dart @@ -1,6 +1,5 @@ import 'package:dio/dio.dart'; import 'package:dio/native_imp.dart'; -import 'package:test/test.dart'; import 'package:mockito/mockito.dart'; import 'package:stream_chat/src/api/requests.dart'; import 'package:stream_chat/src/client.dart'; @@ -8,6 +7,7 @@ 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:test/test.dart'; class MockDio extends Mock implements DioForNative {} @@ -22,7 +22,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -51,7 +51,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -83,7 +83,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -108,7 +108,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -149,7 +149,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -173,7 +173,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -198,7 +198,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -223,7 +223,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -247,7 +247,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -272,7 +272,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -306,7 +306,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -340,7 +340,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -375,7 +375,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -414,7 +414,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -448,7 +448,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -475,7 +475,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -501,7 +501,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -527,7 +527,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -845,7 +845,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1159,7 +1159,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1474,7 +1474,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1789,7 +1789,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1815,7 +1815,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1842,7 +1842,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1863,7 +1863,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1885,7 +1885,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1910,7 +1910,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1935,7 +1935,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1961,7 +1961,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -1993,7 +1993,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -2024,7 +2024,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', @@ -2064,7 +2064,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, tokenProvider: (_) async => '', diff --git a/packages/dart_client/test/src/client_test.dart b/packages/dart_client/test/src/client_test.dart index 299ccecb..a1fa2175 100644 --- a/packages/dart_client/test/src/client_test.dart +++ b/packages/dart_client/test/src/client_test.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:dio/native_imp.dart'; -import 'package:test/test.dart'; import 'package:logging/logging.dart'; import 'package:mockito/mockito.dart'; import 'package:stream_chat/src/api/requests.dart'; @@ -11,6 +10,7 @@ import 'package:stream_chat/src/client.dart'; import 'package:stream_chat/src/exceptions.dart'; import 'package:stream_chat/src/models/message.dart'; import 'package:stream_chat/src/models/user.dart'; +import 'package:test/test.dart'; class MockDio extends Mock implements DioForNative {} @@ -41,7 +41,7 @@ void main() { }); test('should create the object correctly', () { - final client = Client('api-key'); + final client = StreamChatClient('api-key'); expect(client.baseURL, 'chat-us-east-1.stream-io-api.com'); expect(client.apiKey, 'api-key'); @@ -55,7 +55,7 @@ void main() { print(record.message); }; - final client = Client( + final client = StreamChatClient( 'api-key', connectTimeout: Duration(seconds: 10), receiveTimeout: Duration(seconds: 12), @@ -78,7 +78,7 @@ void main() { })); test('Channel', () { - final client = Client('test'); + final client = StreamChatClient('test'); final Map data = {'test': 1}; final channelClient = client.channel('type', id: 'id', extraData: data); expect(channelClient.type, 'type'); @@ -93,7 +93,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -124,7 +124,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -175,7 +175,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -203,7 +203,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -247,7 +247,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -273,7 +273,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -292,7 +292,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -309,7 +309,7 @@ void main() { }); test('devToken', () { - final client = Client('api-key'); + final client = StreamChatClient('api-key'); final token = client.devToken('test'); expect( @@ -325,7 +325,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -353,7 +353,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -396,7 +396,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -417,7 +417,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -432,7 +432,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -453,7 +453,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -478,7 +478,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -507,7 +507,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -528,7 +528,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -550,7 +550,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -571,7 +571,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -594,7 +594,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -615,7 +615,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -636,7 +636,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -663,7 +663,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -684,7 +684,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -705,7 +705,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -727,7 +727,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -752,7 +752,7 @@ void main() { final mockHttpClientAdapter = MockHttpClientAdapter(); dioHttp.httpClientAdapter = mockHttpClientAdapter; - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: dioHttp, ); @@ -771,7 +771,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -794,7 +794,7 @@ void main() { final mockHttpClientAdapter = MockHttpClientAdapter(); dioHttp.httpClientAdapter = mockHttpClientAdapter; - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: dioHttp, ); @@ -813,7 +813,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -836,7 +836,7 @@ void main() { final mockHttpClientAdapter = MockHttpClientAdapter(); dioHttp.httpClientAdapter = mockHttpClientAdapter; - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: dioHttp, ); @@ -855,7 +855,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -879,7 +879,7 @@ void main() { final mockHttpClientAdapter = MockHttpClientAdapter(); dioHttp.httpClientAdapter = mockHttpClientAdapter; - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: dioHttp, ); @@ -898,7 +898,7 @@ void main() { when(mockDio.options).thenReturn(BaseOptions()); when(mockDio.interceptors).thenReturn(Interceptors()); - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: mockDio, ); @@ -923,7 +923,7 @@ void main() { final mockHttpClientAdapter = MockHttpClientAdapter(); dioHttp.httpClientAdapter = mockHttpClientAdapter; - final client = Client( + final client = StreamChatClient( 'api-key', httpClient: dioHttp, ); diff --git a/packages/flutter_widgets/README.md b/packages/flutter_widgets/README.md index b99a8f29..3504c78a 100644 --- a/packages/flutter_widgets/README.md +++ b/packages/flutter_widgets/README.md @@ -91,7 +91,7 @@ Out of the box, all chat widgets use their default styling, and there are two wa 1. Initialize the `StreamChatTheme` from your existing `MaterialApp` style ```dart class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); @@ -117,7 +117,7 @@ Out of the box, all chat widgets use their default styling, and there are two wa 2. Construct a custom theme and provide all the customizations needed ```dart class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/advanced_options_page.dart b/packages/flutter_widgets/example/lib/advanced_options_page.dart index 35e2af7f..ee505148 100644 --- a/packages/flutter_widgets/example/lib/advanced_options_page.dart +++ b/packages/flutter_widgets/example/lib/advanced_options_page.dart @@ -267,7 +267,7 @@ class _AdvancedOptionsPageState extends State { ), ); - final client = Client( + final client = StreamChatClient( apiKey, logLevel: Level.INFO, )..chatPersistenceClient = chatPersistentClient; diff --git a/packages/flutter_widgets/example/lib/custom_message.dart b/packages/flutter_widgets/example/lib/custom_message.dart index 5da4541a..e2756430 100644 --- a/packages/flutter_widgets/example/lib/custom_message.dart +++ b/packages/flutter_widgets/example/lib/custom_message.dart @@ -15,7 +15,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// you can use [StreamChat.of], [StreamChannel.of] and [StreamChatTheme.of] to use the API client directly /// or to retrieve outer scope needed such as messages from the [Channel.state]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -29,7 +29,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/custom_theme.dart b/packages/flutter_widgets/example/lib/custom_theme.dart index 817d2e67..a7ad5ba0 100644 --- a/packages/flutter_widgets/example/lib/custom_theme.dart +++ b/packages/flutter_widgets/example/lib/custom_theme.dart @@ -19,7 +19,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// We also change the message color posted by the current user. /// You can perform these more granular style changes using [StreamChatTheme.copyWith]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -33,7 +33,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/customize_channel_preview.dart b/packages/flutter_widgets/example/lib/customize_channel_preview.dart index 9b7deb64..2f28fa80 100644 --- a/packages/flutter_widgets/example/lib/customize_channel_preview.dart +++ b/packages/flutter_widgets/example/lib/customize_channel_preview.dart @@ -20,7 +20,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// - We retrieve the count of unread messages from [Channel.state] void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -34,7 +34,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/customize_message_widget.dart b/packages/flutter_widgets/example/lib/customize_message_widget.dart index 14233dd7..d19d6023 100644 --- a/packages/flutter_widgets/example/lib/customize_message_widget.dart +++ b/packages/flutter_widgets/example/lib/customize_message_widget.dart @@ -15,7 +15,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// you can use [StreamChat.of], [StreamChannel.of] and [StreamChatTheme.of] to use the API client directly /// or to retrieve outer scope needed such as messages from the [Channel.state]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -29,7 +29,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/main.dart b/packages/flutter_widgets/example/lib/main.dart index 93c7b082..775b1d6e 100644 --- a/packages/flutter_widgets/example/lib/main.dart +++ b/packages/flutter_widgets/example/lib/main.dart @@ -29,7 +29,7 @@ void main() async { final apiKey = await secureStorage.read(key: kStreamApiKey); final userId = await secureStorage.read(key: kStreamUserId); - final client = Client( + final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, logLevel: Level.INFO, )..chatPersistenceClient = chatPersistentClient; @@ -46,7 +46,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/multiple_conversation.dart b/packages/flutter_widgets/example/lib/multiple_conversation.dart index b5fdd5af..f810231c 100644 --- a/packages/flutter_widgets/example/lib/multiple_conversation.dart +++ b/packages/flutter_widgets/example/lib/multiple_conversation.dart @@ -19,7 +19,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// In this case we are showing the list of channels the current user is a member and we order them based on the time they had a new message. /// [ChannelListView] handles pagination and updates automatically out of the box when new channels are created or when a new message is added to a channel. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -33,7 +33,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/single_conversation.dart b/packages/flutter_widgets/example/lib/single_conversation.dart index 2093d38a..66a1091c 100644 --- a/packages/flutter_widgets/example/lib/single_conversation.dart +++ b/packages/flutter_widgets/example/lib/single_conversation.dart @@ -5,8 +5,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// There are three important things to notice that are common to all Flutter application using StreamChat: /// -/// 1. The Dart API [Client] is initialized with your API Key -/// 2. The current user is set by calling [Client.setUser] +/// 1. The Dart API [StreamChatClient] is initialized with your API Key +/// 2. The current user is set by calling [StreamChatClient.setUser] /// 3. The client is then passed to the top-level [StreamChat] widget /// [StreamChat] is an inherited widget and must be the parent of all Chat related widgets. /// @@ -15,9 +15,9 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// Let's have a look at what we've built: /// -/// - We set up the Chat [Client] with the API key +/// - We set up the Chat [StreamChatClient] with the API key /// -/// - We set the the current user for Chat with [Client.setUser] and a pre-generated user token +/// - We set the the current user for Chat with [StreamChatClient.setUser] and a pre-generated user token /// /// - We make [StreamChat] the root Widget of our application /// @@ -25,7 +25,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// If you now run the simulator you will see a single channel UI. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -44,7 +44,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; final Channel channel; MyApp(this.client, this.channel); diff --git a/packages/flutter_widgets/example/lib/split_view.dart b/packages/flutter_widgets/example/lib/split_view.dart index f99e69fc..08324759 100644 --- a/packages/flutter_widgets/example/lib/split_view.dart +++ b/packages/flutter_widgets/example/lib/split_view.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -16,7 +16,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/example/lib/threads.dart b/packages/flutter_widgets/example/lib/threads.dart index f89e6fce..6a3c7766 100644 --- a/packages/flutter_widgets/example/lib/threads.dart +++ b/packages/flutter_widgets/example/lib/threads.dart @@ -10,7 +10,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// Now we can open threads and create new ones as well, if you long press a message you can tap on Reply and it will open the same [ThreadPage]. void main() async { - final client = Client( + final client = StreamChatClient( 's2dxdhpxd94g', logLevel: Level.INFO, ); @@ -24,7 +24,7 @@ void main() async { } class MyApp extends StatelessWidget { - final Client client; + final StreamChatClient client; MyApp(this.client); diff --git a/packages/flutter_widgets/lib/src/channel_header.dart b/packages/flutter_widgets/lib/src/channel_header.dart index 954734f9..27194627 100644 --- a/packages/flutter_widgets/lib/src/channel_header.dart +++ b/packages/flutter_widgets/lib/src/channel_header.dart @@ -1,13 +1,13 @@ import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter/src/back_button.dart'; import 'package:stream_chat_flutter/src/channel_info.dart'; import 'package:stream_chat_flutter/src/channel_name.dart'; import 'package:stream_chat_flutter/src/info_tile.dart'; import 'package:stream_chat_flutter/src/stream_chat_theme.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; -import '../stream_chat_flutter.dart'; import './channel_name.dart'; +import '../stream_chat_flutter.dart'; import 'channel_image.dart'; import 'connection_status_builder.dart'; @@ -18,7 +18,7 @@ import 'connection_status_builder.dart'; /// /// ```dart /// class MyApp extends StatelessWidget { -/// final Client client; +/// final StreamChatClient client; /// final Channel channel; /// /// MyApp(this.client, this.channel); diff --git a/packages/flutter_widgets/lib/src/channel_image.dart b/packages/flutter_widgets/lib/src/channel_image.dart index 18d67dfb..649a5880 100644 --- a/packages/flutter_widgets/lib/src/channel_image.dart +++ b/packages/flutter_widgets/lib/src/channel_image.dart @@ -1,8 +1,8 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter/src/group_image.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_image.png) /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/channel_image_paint.png) @@ -11,7 +11,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// ```dart /// class MyApp extends StatelessWidget { -/// final Client client; +/// final StreamChatClient client; /// final Channel channel; /// /// MyApp(this.client, this.channel); diff --git a/packages/flutter_widgets/lib/src/channel_info.dart b/packages/flutter_widgets/lib/src/channel_info.dart index 88739bb3..4244c910 100644 --- a/packages/flutter_widgets/lib/src/channel_info.dart +++ b/packages/flutter_widgets/lib/src/channel_info.dart @@ -111,7 +111,8 @@ class ChannelInfo extends StatelessWidget { ); } - Widget _buildDisconnectedTitleState(BuildContext context, Client client) { + Widget _buildDisconnectedTitleState( + BuildContext context, StreamChatClient client) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/packages/flutter_widgets/lib/src/channel_list_header.dart b/packages/flutter_widgets/lib/src/channel_list_header.dart index 29126402..045d24d5 100644 --- a/packages/flutter_widgets/lib/src/channel_list_header.dart +++ b/packages/flutter_widgets/lib/src/channel_list_header.dart @@ -2,9 +2,9 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter/src/stream_neumorphic_button.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'connection_status_builder.dart'; import 'info_tile.dart'; @@ -13,15 +13,15 @@ import 'stream_chat.dart'; typedef _TitleBuilder = Widget Function( BuildContext context, ConnectionStatus status, - Client client, + StreamChatClient client, ); /// -/// It shows the current [Client] status. +/// It shows the current [StreamChatClient] status. /// /// ```dart /// class MyApp extends StatelessWidget { -/// final Client client; +/// final StreamChatClient client; /// /// MyApp(this.client); /// @@ -42,8 +42,8 @@ typedef _TitleBuilder = Widget Function( /// Usually you would use this widget as an [AppBar] inside a [Scaffold]. /// However you can also use it as a normal widget. /// -/// The widget by default uses the inherited [Client] to fetch information about the status. -/// However you can also pass your own [Client] if you don't have it in the widget tree. +/// The widget by default uses the inherited [StreamChatClient] to fetch information about the status. +/// However you can also pass your own [StreamChatClient] if you don't have it in the widget tree. /// /// The widget components render the ui based on the first ancestor of type [StreamChatTheme] and on its [ChannelTheme.channelHeaderTheme] property. /// Modify it to change the widget appearance. @@ -59,8 +59,8 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { this.preNavigationCallback, }) : super(key: key); - /// Pass this if you don't have a [Client] in your widget tree. - final Client client; + /// Pass this if you don't have a [StreamChatClient] in your widget tree. + final StreamChatClient client; /// Use this to build your own title as per different [ConnectionStatus] final _TitleBuilder titleBuilder; @@ -215,7 +215,8 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { ); } - Widget _buildDisconnectedTitleState(BuildContext context, Client client) { + Widget _buildDisconnectedTitleState( + BuildContext context, StreamChatClient client) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/packages/flutter_widgets/lib/src/connection_status_builder.dart b/packages/flutter_widgets/lib/src/connection_status_builder.dart index ebb12cd5..01632b1b 100644 --- a/packages/flutter_widgets/lib/src/connection_status_builder.dart +++ b/packages/flutter_widgets/lib/src/connection_status_builder.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; + import 'stream_chat.dart'; /// Widget that builds itself based on the latest snapshot of interaction with /// a [Stream] of type [ConnectionStatus]. /// -/// The widget will use the closest [Client.wsConnectionStatusStream] in case no +/// The widget will use the closest [StreamChatClient.wsConnectionStatusStream] in case no /// stream is provided. class ConnectionStatusBuilder extends StatelessWidget { /// Creates a new ConnectionStatusBuilder diff --git a/packages/flutter_widgets/lib/src/stream_chat.dart b/packages/flutter_widgets/lib/src/stream_chat.dart index 0ea5efb2..f093a81a 100644 --- a/packages/flutter_widgets/lib/src/stream_chat.dart +++ b/packages/flutter_widgets/lib/src/stream_chat.dart @@ -4,14 +4,14 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_app_badger/flutter_app_badger.dart'; import 'package:flutter_portal/flutter_portal.dart'; -import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter/src/stream_chat_theme.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; /// Widget used to provide information about the chat to the widget tree /// /// class MyApp extends StatelessWidget { -/// final Client client; +/// final StreamChatClient client; /// /// MyApp(this.client); /// @@ -30,7 +30,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// /// Use [StreamChat.of] to get the current [StreamChatState] instance. class StreamChat extends StatefulWidget { - final Client client; + final StreamChatClient client; final Widget child; final StreamChatThemeData streamChatThemeData; @@ -73,7 +73,7 @@ class StreamChat extends StatefulWidget { /// The current state of the StreamChat widget class StreamChatState extends State { - Client get client => widget.client; + StreamChatClient get client => widget.client; @override Widget build(BuildContext context) { diff --git a/packages/flutter_widgets/test/src/mocks.dart b/packages/flutter_widgets/test/src/mocks.dart index 25b438d6..0abbf3ca 100644 --- a/packages/flutter_widgets/test/src/mocks.dart +++ b/packages/flutter_widgets/test/src/mocks.dart @@ -1,7 +1,7 @@ import 'package:mockito/mockito.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; -class MockClient extends Mock implements Client {} +class MockClient extends Mock implements StreamChatClient {} class MockClientState extends Mock implements ClientState {} diff --git a/packages/stream_chat_flutter_core/example/lib/main.dart b/packages/stream_chat_flutter_core/example/lib/main.dart index 845510f2..9199ed15 100644 --- a/packages/stream_chat_flutter_core/example/lib/main.dart +++ b/packages/stream_chat_flutter_core/example/lib/main.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; Future main() async { - /// Create a new instance of [Client] passing the apikey obtained from your + /// Create a new instance of [StreamChatClient] passing the apikey obtained from your /// project dashboard. - final client = Client('b67pax5b2wdq'); + final client = StreamChatClient('b67pax5b2wdq'); /// Set the current user. In a production scenario, this should be done using /// a backend to generate a user token using our server SDK. @@ -43,10 +43,10 @@ class StreamExample extends StatelessWidget { }) : super(key: key); /// Instance of Stream Client. - /// Stream's [Client] can be used to connect to our servers and set the default + /// Stream's [StreamChatClient] can be used to connect to our servers and set the default /// user for the application. Performing these actions trigger a websocket connection /// allowing for real-time updates. - final Client client; + final StreamChatClient client; @override Widget build(BuildContext context) { @@ -287,8 +287,8 @@ class _MessageScreenState extends State { } /// Extensions can be used to add functionality to the SDK. In the examples -/// below, we add two simple extensions to the [Client] and [Channel]. -extension on Client { +/// below, we add two simple extensions to the [StreamChatClient] and [Channel]. +extension on StreamChatClient { /// Fetches the current user id. String get uid => state.user.id; } diff --git a/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart b/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart index 6458bebf..9839994f 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_search_bloc.dart @@ -59,7 +59,7 @@ class MessageSearchBlocState extends State Stream get queryMessagesLoading => _queryMessagesLoadingController.stream; - /// Calls [Client.search] updating [messageResponses] stream + /// Calls [StreamChatClient.search] updating [messageResponses] stream Future search({ Map filter, Map messageFilter, @@ -82,7 +82,7 @@ class MessageSearchBlocState extends State } } - /// Calls [Client.search] updating [queryMessagesLoading] stream + /// Calls [StreamChatClient.search] updating [queryMessagesLoading] stream Future loadMore({ Map filter, Map messageFilter, diff --git a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart index 78cae0ba..8a8d0185 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart @@ -15,7 +15,7 @@ import 'typedef.dart'; /// /// ```dart /// class MyApp extends StatelessWidget { -/// final Client client; +/// final StreamChatClient client; /// /// MyApp(this.client); /// @@ -50,7 +50,7 @@ class StreamChatCore extends StatefulWidget { /// Instance of Stream Chat Client containing information about the current /// application. - final Client client; + final StreamChatClient client; /// Widget descendant. final Widget child; @@ -85,7 +85,7 @@ class StreamChatCore extends StatefulWidget { class StreamChatCoreState extends State with WidgetsBindingObserver { /// Initialized client used throughout the application. - Client get client => widget.client; + StreamChatClient get client => widget.client; Timer _disconnectTimer; diff --git a/packages/stream_chat_flutter_core/test/mocks.dart b/packages/stream_chat_flutter_core/test/mocks.dart index 37fa5530..c23a4be4 100644 --- a/packages/stream_chat_flutter_core/test/mocks.dart +++ b/packages/stream_chat_flutter_core/test/mocks.dart @@ -1,7 +1,7 @@ import 'package:mockito/mockito.dart'; import 'package:stream_chat/stream_chat.dart'; -class MockClient extends Mock implements Client {} +class MockClient extends Mock implements StreamChatClient {} class MockClientState extends Mock implements ClientState {} diff --git a/packages/stream_chat_persistence/README.md b/packages/stream_chat_persistence/README.md index d53d51e4..77b2eea5 100644 --- a/packages/stream_chat_persistence/README.md +++ b/packages/stream_chat_persistence/README.md @@ -36,7 +36,7 @@ final chatPersistentClient = StreamChatPersistenceClient( ``` 2. Pass the instance to the official Stream chat client. ```dart - final client = Client( + final client = StreamChatClient( apiKey ?? kDefaultStreamApiKey, logLevel: Level.INFO, )..chatPersistenceClient = chatPersistentClient;