From 207a5b51d22dc8cbb719b22b65555c7d18aae10f Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 12:24:00 +0200 Subject: [PATCH 01/26] feat(llc): add support for sharing live and static locations --- melos.yaml | 5 + .../stream_chat/lib/src/client/channel.dart | 423 ++++++++++++++---- .../stream_chat/lib/src/client/client.dart | 178 ++++++++ .../lib/src/client/event_resolvers.dart | 114 ++++- .../lib/src/core/api/responses.dart | 12 + .../lib/src/core/api/responses.g.dart | 8 + .../lib/src/core/api/user_api.dart | 32 ++ .../lib/src/core/models/channel_config.dart | 4 + .../lib/src/core/models/channel_config.g.dart | 2 + .../lib/src/core/models/channel_model.dart | 3 + .../lib/src/core/models/channel_state.dart | 7 + .../lib/src/core/models/channel_state.g.dart | 5 + .../lib/src/core/models/location.dart | 156 +++++++ .../lib/src/core/models/location.g.dart | 38 ++ .../src/core/models/location_coordinates.dart | 33 ++ .../lib/src/core/models/message.dart | 16 +- .../lib/src/core/models/message.g.dart | 5 +- packages/stream_chat/lib/src/event_type.dart | 12 + packages/stream_chat/lib/stream_chat.dart | 2 + .../android/app/src/main/AndroidManifest.xml | 7 + .../ios/Runner.xcodeproj/project.pbxproj | 2 + sample_app/ios/Runner/Info.plist | 19 +- sample_app/lib/pages/channel_list_page.dart | 10 +- sample_app/lib/pages/channel_page.dart | 85 +++- sample_app/lib/pages/thread_page.dart | 18 + sample_app/lib/utils/app_config.dart | 6 +- sample_app/lib/utils/location_provider.dart | 96 ++++ .../lib/utils/shared_location_service.dart | 91 ++++ sample_app/lib/widgets/channel_list.dart | 110 ++++- .../widgets/location/location_attachment.dart | 235 ++++++++++ .../location/location_detail_dialog.dart | 319 +++++++++++++ .../location/location_picker_dialog.dart | 362 +++++++++++++++ .../location/location_picker_option.dart | 73 +++ .../location/location_user_marker.dart | 56 +++ sample_app/lib/widgets/simple_map_view.dart | 153 +++++++ .../macos/Flutter/Flutter-Debug.xcconfig | 2 - .../macos/Flutter/Flutter-Release.xcconfig | 2 - .../macos/Runner/DebugProfile.entitlements | 2 + sample_app/macos/Runner/Info.plist | 2 + sample_app/macos/Runner/Release.entitlements | 2 + sample_app/pubspec.yaml | 6 + 41 files changed, 2608 insertions(+), 105 deletions(-) create mode 100644 packages/stream_chat/lib/src/core/models/location.dart create mode 100644 packages/stream_chat/lib/src/core/models/location.g.dart create mode 100644 packages/stream_chat/lib/src/core/models/location_coordinates.dart create mode 100644 sample_app/lib/utils/location_provider.dart create mode 100644 sample_app/lib/utils/shared_location_service.dart create mode 100644 sample_app/lib/widgets/location/location_attachment.dart create mode 100644 sample_app/lib/widgets/location/location_detail_dialog.dart create mode 100644 sample_app/lib/widgets/location/location_picker_dialog.dart create mode 100644 sample_app/lib/widgets/location/location_picker_option.dart create mode 100644 sample_app/lib/widgets/location/location_user_marker.dart create mode 100644 sample_app/lib/widgets/simple_map_view.dart delete mode 100644 sample_app/macos/Flutter/Flutter-Debug.xcconfig delete mode 100644 sample_app/macos/Flutter/Flutter-Release.xcconfig diff --git a/melos.yaml b/melos.yaml index b3abdab213..20e1942f9a 100644 --- a/melos.yaml +++ b/melos.yaml @@ -25,6 +25,7 @@ command: # List of all the dependencies used in the project. dependencies: async: ^2.11.0 + avatar_glow: ^3.0.0 cached_network_image: ^3.3.1 chewie: ^1.8.1 collection: ^1.17.2 @@ -44,6 +45,8 @@ command: file_selector: ^1.0.3 flutter_app_badger: ^1.5.0 flutter_local_notifications: ^18.0.1 + flutter_map: ^8.1.1 + flutter_map_animations: ^0.9.0 flutter_markdown: ^0.7.2+1 flutter_portal: ^1.1.4 flutter_secure_storage: ^9.2.2 @@ -51,6 +54,7 @@ command: flutter_svg: ^2.0.10+1 freezed_annotation: ">=2.4.1 <4.0.0" gal: ^2.3.1 + geolocator: ^13.0.0 get_thumbnail_video: ^0.7.3 go_router: ^14.6.2 http_parser: ^4.0.2 @@ -60,6 +64,7 @@ command: jose: ^0.3.4 json_annotation: ^4.9.0 just_audio: ">=0.9.38 <0.11.0" + latlong2: ^0.9.1 logging: ^1.2.0 lottie: ^3.1.2 media_kit: ^1.1.10+1 diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 009047def6..c3aa702ee0 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1088,6 +1088,68 @@ class Channel { return _client.deleteDraft(id!, type, parentId: parentId); } + /// Sends a static location to this channel. + /// + /// Optionally, provide a [messageText] and [extraData] to send along with + /// the location. + Future sendStaticLocation({ + String? messageText, + required String createdByDeviceId, + required LocationCoordinates location, + Map extraData = const {}, + }) { + final message = Message( + text: messageText, + extraData: extraData, + ); + + final currentUserId = _client.state.currentUser?.id; + final locationMessage = message.copyWith( + sharedLocation: Location( + channelCid: cid, + userId: currentUserId, + messageId: message.id, + latitude: location.latitude, + longitude: location.longitude, + createdByDeviceId: createdByDeviceId, + ), + ); + + return sendMessage(locationMessage); + } + + /// Sends a live location sharing message to this channel. + /// + /// Optionally, provide a [messageText] and [extraData] to send along with + /// the location. + Future startLiveLocationSharing({ + String? messageText, + required DateTime endSharingAt, + required String createdByDeviceId, + required LocationCoordinates location, + Map extraData = const {}, + }) { + final message = Message( + text: messageText, + extraData: extraData, + ); + + final currentUserId = _client.state.currentUser?.id; + final locationMessage = message.copyWith( + sharedLocation: Location( + channelCid: cid, + userId: currentUserId, + messageId: message.id, + endAt: endSharingAt, + latitude: location.latitude, + longitude: location.longitude, + createdByDeviceId: createdByDeviceId, + ), + ); + + return sendMessage(locationMessage); + } + /// Send a file to this channel. Future sendFile( AttachmentFile file, { @@ -1186,7 +1248,7 @@ class Channel { /// Optionally provide a [messageText] to send a message along with the poll. Future sendPoll( Poll poll, { - String messageText = '', + String? messageText, }) async { _checkInitialized(); final res = await _pollLock.synchronized(() => _client.createPoll(poll)); @@ -2115,12 +2177,16 @@ class ChannelClientState { /* End of draft events */ - _listenReactions(); + _listenReactionNew(); + + _listenReactionUpdated(); _listenReactionDeleted(); /* Start of poll events */ + _listenPollCreated(); + _listenPollUpdated(); _listenPollClosed(); @@ -2167,10 +2233,22 @@ class ChannelClientState { /* End of reminder events */ + /* Start of location events */ + + _listenLocationShared(); + + _listenLocationUpdated(); + + _listenLocationExpired(); + + /* End of location events */ + _startCleaningStaleTypingEvents(); _startCleaningStalePinnedMessages(); + _startCleaningExpiredLocations(); + _channel._client.chatPersistenceClient ?.getChannelThreads(_channel.cid!) .then((threads) { @@ -2449,6 +2527,17 @@ class ChannelClientState { return threadMessage; } + void _listenPollCreated() { + _subscriptions.add( + _channel.on(EventType.pollCreated).listen((event) { + final message = event.message; + if (message == null || message.poll == null) return; + + return addNewMessage(message); + }), + ); + } + void _listenPollUpdated() { _subscriptions.add(_channel.on(EventType.pollUpdated).listen((event) { final eventPoll = event.poll; @@ -2711,58 +2800,144 @@ class ChannelClientState { } } + Message? _findLocationMessage(String id) { + final message = messages.firstWhereOrNull((it) { + return it.sharedLocation?.messageId == id; + }); + + if (message != null) return message; + + final threadMessage = threads.values.flattened.firstWhereOrNull((it) { + return it.sharedLocation?.messageId == id; + }); + + return threadMessage; + } + + void _listenLocationShared() { + _subscriptions.add( + _channel.on(EventType.locationShared).listen((event) { + final message = event.message; + if (message == null || message.sharedLocation == null) return; + + return addNewMessage(message); + }), + ); + } + + void _listenLocationUpdated() { + _subscriptions.add( + _channel.on(EventType.locationUpdated).listen((event) { + final location = event.message?.sharedLocation; + if (location == null) return; + + final messageId = location.messageId; + if (messageId == null) return; + + final oldMessage = _findLocationMessage(messageId); + if (oldMessage == null) return; + + final updatedMessage = oldMessage.copyWith(sharedLocation: location); + return updateMessage(updatedMessage); + }), + ); + } + + void _listenLocationExpired() { + _subscriptions.add( + _channel.on(EventType.locationExpired).listen((event) { + final location = event.message?.sharedLocation; + if (location == null) return; + + final messageId = location.messageId; + if (messageId == null) return; + + final oldMessage = _findLocationMessage(messageId); + if (oldMessage == null) return; + + final updatedMessage = oldMessage.copyWith(sharedLocation: location); + return updateMessage(updatedMessage); + }), + ); + } + void _listenReactionDeleted() { - _subscriptions.add(_channel.on(EventType.reactionDeleted).listen((event) { - final oldMessage = - messages.firstWhereOrNull((it) => it.id == event.message?.id) ?? - threads[event.message?.parentId] - ?.firstWhereOrNull((e) => e.id == event.message?.id); - final reaction = event.reaction; - final ownReactions = oldMessage?.ownReactions - ?.whereNot((it) => - it.type == reaction?.type && - it.score == reaction?.score && - it.messageId == reaction?.messageId && - it.userId == reaction?.userId && - it.extraData == reaction?.extraData) - .toList(growable: false); - final message = event.message!.copyWith( - ownReactions: ownReactions, - ); - updateMessage(message); - })); + _subscriptions.add( + _channel.on(EventType.reactionDeleted).listen((event) { + final eventMessage = event.message; + if (eventMessage == null) return; + + final reaction = event.reaction; + if (reaction == null) return; + + final messageId = eventMessage.id; + final parentId = eventMessage.parentId; + + for (final message in [...messages, ...?threads[parentId]]) { + if (message.id == messageId) { + final updatedOwnReactions = message.ownReactions?.where((it) { + return it.userId != reaction.userId || it.type != reaction.type; + }); + + return updateMessage( + eventMessage.copyWith( + ownReactions: updatedOwnReactions?.toList(), + ), + ); + } + } + }), + ); } - void _listenReactions() { + void _listenReactionNew() { _subscriptions.add(_channel.on(EventType.reactionNew).listen((event) { - final oldMessage = - messages.firstWhereOrNull((it) => it.id == event.message?.id) ?? - threads[event.message?.parentId] - ?.firstWhereOrNull((e) => e.id == event.message?.id); - final message = event.message!.copyWith( - ownReactions: oldMessage?.ownReactions, - ); - updateMessage(message); + final eventMessage = event.message; + if (eventMessage == null) return; + + final messageId = eventMessage.id; + final parentId = eventMessage.parentId; + + for (final message in [...messages, ...?threads[parentId]]) { + if (message.id == messageId) { + return updateMessage( + eventMessage.copyWith( + ownReactions: message.ownReactions, + ), + ); + } + } })); } + void _listenReactionUpdated() { + _subscriptions.add( + _channel.on(EventType.reactionUpdated).listen((event) { + final eventMessage = event.message; + if (eventMessage == null) return; + + final messageId = eventMessage.id; + final parentId = eventMessage.parentId; + + for (final message in [...messages, ...?threads[parentId]]) { + if (message.id == messageId) { + return updateMessage( + eventMessage.copyWith( + ownReactions: message.ownReactions, + ), + ); + } + } + }), + ); + } + void _listenMessageUpdated() { - _subscriptions.add(_channel - .on( - EventType.messageUpdated, - EventType.reactionUpdated, - ) - .listen((event) { - final oldMessage = - messages.firstWhereOrNull((it) => it.id == event.message?.id) ?? - threads[event.message?.parentId] - ?.firstWhereOrNull((e) => e.id == event.message?.id); - final message = event.message!.copyWith( - poll: oldMessage?.poll, - pollId: oldMessage?.pollId, - ownReactions: oldMessage?.ownReactions, - ); - updateMessage(message); + _subscriptions.add(_channel.on(EventType.messageUpdated).listen((event) { + final message = event.message; + if (message == null) return; + + return updateMessage(message); })); } @@ -2771,7 +2946,7 @@ class ChannelClientState { final message = event.message!; final hardDelete = event.hardDelete ?? false; - deleteMessage(message, hardDelete: hardDelete); + return deleteMessage(message, hardDelete: hardDelete); })); } @@ -2785,19 +2960,22 @@ class ChannelClientState { final message = event.message; if (message == null) return; - final isThreadMessage = message.parentId != null; - final isShownInChannel = message.showInChannel == true; - final isThreadOnlyMessage = isThreadMessage && !isShownInChannel; + return addNewMessage(message); + })); + } - // Only add the message if the channel is upToDate or if the message is - // a thread-only message. - if (isUpToDate || isThreadOnlyMessage) { - updateMessage(message); - } + /// Adds a new message to the channel state and updates the unread count. + void addNewMessage(Message message) { + final isThreadMessage = message.parentId != null; + final isShownInChannel = message.showInChannel == true; + final isThreadOnlyMessage = isThreadMessage && !isShownInChannel; - // Otherwise, check if we can count the message as unread. - if (_countMessageAsUnread(message)) unreadCount += 1; - })); + // Only add the message if the channel is upToDate or if the message is + // a thread-only message. + if (isUpToDate || isThreadOnlyMessage) updateMessage(message); + + // Otherwise, check if we can count the message as unread. + if (_countMessageAsUnread(message)) unreadCount += 1; } // Logic taken from the backend SDK @@ -2932,6 +3110,9 @@ class ChannelClientState { // Handle updates to pinned messages. final newPinnedMessages = _updatePinnedMessages(message); + // Handle updates to the active live locations. + final newActiveLiveLocations = _updateActiveLiveLocations(message); + // Calculate the new last message at time. var lastMessageAt = _channelState.channel?.lastMessageAt; lastMessageAt ??= message.createdAt; @@ -2943,6 +3124,7 @@ class ChannelClientState { _channelState = _channelState.copyWith( messages: newMessages.sorted(_sortByCreatedAt), pinnedMessages: newPinnedMessages, + activeLiveLocations: newActiveLiveLocations, channel: _channelState.channel?.copyWith( lastMessageAt: lastMessageAt, ), @@ -2968,27 +3150,58 @@ class ChannelClientState { /// Updates the list of pinned messages based on the current message's /// pinned status. List _updatePinnedMessages(Message message) { - final newPinnedMessages = [...pinnedMessages]; - final oldPinnedIndex = - newPinnedMessages.indexWhere((m) => m.id == message.id); - - if (message.pinned) { - // If the message is pinned, add or update it in the list of pinned - // messages. - if (oldPinnedIndex != -1) { - newPinnedMessages[oldPinnedIndex] = message; - } else { - newPinnedMessages.add(message); - } - } else { - // If the message is not pinned, remove it from the list of pinned - // messages. - newPinnedMessages.removeWhere((m) => m.id == message.id); + final existingPinnedMessages = [...pinnedMessages]; + + // If the message is pinned and not yet deleted, + // merge it into the existing pinned messages. + if (message.pinned && !message.isDeleted) { + final newPinnedMessages = [ + ...existingPinnedMessages.merge( + [message], + key: (it) => it.id, + update: (old, updated) => updated, + ), + ]; + + return newPinnedMessages; } + // Otherwise, remove the message from the pinned messages. + final newPinnedMessages = [ + ...existingPinnedMessages.where((m) => m.id != message.id), + ]; + return newPinnedMessages; } + List _updateActiveLiveLocations(Message message) { + final existingLocations = [...activeLiveLocations]; + + final location = message.sharedLocation; + if (location == null) return existingLocations; + + // If the location is live and active and not yet deleted, + // merge it into the existing active live locations. + if (location.isLive && location.isActive && !message.isDeleted) { + final newActiveLiveLocations = [ + ...existingLocations.merge( + [location], + key: (it) => (it.userId, it.channelCid, it.createdByDeviceId), + update: (old, updated) => updated, + ), + ]; + + return [...newActiveLiveLocations.where((it) => it.isActive)]; + } + + // Otherwise, remove the location from the active live locations. + final newActiveLiveLocations = [ + ...existingLocations.where((it) => it.messageId != location.messageId), + ]; + + return [...newActiveLiveLocations.where((it) => it.isActive)]; + } + /// Remove a [message] from this [channelState]. void removeMessage(Message message) async { await _channel._client.chatPersistenceClient?.deleteMessageById(message.id); @@ -3027,8 +3240,16 @@ class ChannelClientState { ); }).toList(); + // If the message is pinned, remove it from the pinned messages. + final updatedPinnedMessages = _updatePinnedMessages(message); + + // If the message is a live location, update the active live locations. + final updatedActiveLiveLocations = _updateActiveLiveLocations(message); + _channelState = _channelState.copyWith( - messages: updatedMessages, + messages: updatedMessages.sorted(_sortByCreatedAt), + pinnedMessages: updatedPinnedMessages, + activeLiveLocations: updatedActiveLiveLocations, ); } @@ -3144,6 +3365,16 @@ class ChannelClientState { (watchers, users) => [...?watchers?.map((e) => users[e.id] ?? e)], ).distinct(const ListEquality().equals); + /// Channel active live locations. + List get activeLiveLocations { + return _channelState.activeLiveLocations ?? []; + } + + /// Channel active live locations as a stream. + Stream> get activeLiveLocationsStream => channelStateStream + .map((cs) => cs.activeLiveLocations ?? []) + .distinct(const ListEquality().equals); + /// Channel draft. Draft? get draft => _channelState.draft; @@ -3478,6 +3709,42 @@ class ChannelClientState { ); } + Timer? _staleLiveLocationsCleanerTimer; + void _startCleaningExpiredLocations() { + _staleLiveLocationsCleanerTimer?.cancel(); + _staleLiveLocationsCleanerTimer = Timer.periodic( + const Duration(seconds: 1), + (_) { + final currentUserId = _channel._client.state.currentUser?.id; + if (currentUserId == null) return; + + final expired = activeLiveLocations.where((it) => it.isExpired); + if (expired.isEmpty) return; + + for (final sharedLocation in expired) { + // Skip if the location is shared by the current user, + // as we are already handling them in the client. + if (sharedLocation.userId == currentUserId) continue; + + final lastUpdatedAt = DateTime.timestamp(); + final locationExpiredEvent = Event( + type: EventType.locationExpired, + cid: sharedLocation.channelCid, + message: Message( + id: sharedLocation.messageId, + updatedAt: lastUpdatedAt, + sharedLocation: sharedLocation.copyWith( + updatedAt: lastUpdatedAt, + ), + ), + ); + + _channel._client.handleEvent(locationExpiredEvent); + } + }, + ); + } + /// Call this method to dispose this object. void dispose() { _debouncedUpdatePersistenceChannelState.cancel(); @@ -3488,6 +3755,7 @@ class ChannelClientState { _threadsController.close(); _staleTypingEventsCleanerTimer?.cancel(); _stalePinnedMessagesCleanerTimer?.cancel(); + _staleLiveLocationsCleanerTimer?.cancel(); _typingEventsController.close(); } } @@ -3679,4 +3947,9 @@ extension ChannelCapabilityCheck on Channel { bool get canQueryPollVotes { return ownCapabilities.contains(ChannelCapability.queryPollVotes); } + + /// True, if the current user can share location in the channel. + bool get canShareLocation { + return ownCapabilities.contains(ChannelCapability.shareLocation); + } } diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index a55530ef8a..4bb038c792 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -25,6 +25,8 @@ import 'package:stream_chat/src/core/models/draft.dart'; import 'package:stream_chat/src/core/models/draft_message.dart'; import 'package:stream_chat/src/core/models/event.dart'; import 'package:stream_chat/src/core/models/filter.dart'; +import 'package:stream_chat/src/core/models/location.dart'; +import 'package:stream_chat/src/core/models/location_coordinates.dart'; import 'package:stream_chat/src/core/models/member.dart'; import 'package:stream_chat/src/core/models/message.dart'; import 'package:stream_chat/src/core/models/message_reminder.dart'; @@ -35,6 +37,7 @@ import 'package:stream_chat/src/core/models/poll_vote.dart'; import 'package:stream_chat/src/core/models/thread.dart'; import 'package:stream_chat/src/core/models/user.dart'; import 'package:stream_chat/src/core/util/event_controller.dart'; +import 'package:stream_chat/src/core/util/extension.dart'; import 'package:stream_chat/src/core/util/utils.dart'; import 'package:stream_chat/src/db/chat_persistence_client.dart'; import 'package:stream_chat/src/event_type.dart'; @@ -229,8 +232,12 @@ class StreamChatClient { Stream get eventStream => _eventController.stream; late final _eventController = EventController( resolvers: [ + event_resolvers.pollCreatedResolver, event_resolvers.pollAnswerCastedResolver, event_resolvers.pollAnswerRemovedResolver, + event_resolvers.locationSharedResolver, + event_resolvers.locationUpdatedResolver, + event_resolvers.locationExpiredResolver, ], ); @@ -1771,6 +1778,51 @@ class StreamChatClient { pagination: pagination, ); + /// Retrieves all the active live locations of the current user. + Future getActiveLiveLocations() async { + try { + final response = await _chatApi.user.getActiveLiveLocations(); + + // Update the active live locations in the state. + final activeLiveLocations = response.activeLiveLocations; + state.activeLiveLocations = activeLiveLocations; + + return response; + } catch (e, stk) { + logger.severe('Error getting active live locations', e, stk); + rethrow; + } + } + + /// Updates an existing live location created by the current user. + Future updateLiveLocation({ + required String messageId, + required String createdByDeviceId, + LocationCoordinates? location, + DateTime? endAt, + }) { + return _chatApi.user.updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + location: location, + endAt: endAt, + ); + } + + /// Expire an existing live location created by the current user. + Future stopLiveLocation({ + required String messageId, + required String createdByDeviceId, + }) { + return updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + // Passing the current time as endAt will mark the location as expired + // and make it inactive. + endAt: DateTime.timestamp(), + ); + } + /// Enables slow mode Future enableSlowdown( String channelId, @@ -2087,6 +2139,14 @@ class ClientState { _listenUserUpdated(); _listenAllChannelsRead(); + + _listenLocationShared(); + + _listenLocationUpdated(); + + _listenLocationExpired(); + + _startCleaningExpiredLocations(); } /// Stops listening to the client events. @@ -2174,6 +2234,103 @@ class ClientState { ); } + void _listenLocationShared() { + _eventsSubscription?.add( + _client.on(EventType.locationShared).listen((event) { + final location = event.message?.sharedLocation; + if (location == null || location.isStatic) return; + + final currentUserId = currentUser?.id; + if (currentUserId == null) return; + if (location.userId != currentUserId) return; + + final newActiveLiveLocations = [ + ...activeLiveLocations.merge( + [location], + key: (it) => (it.userId, it.channelCid, it.createdByDeviceId), + update: (original, updated) => updated, + ), + ]; + + activeLiveLocations = newActiveLiveLocations; + }), + ); + } + + void _listenLocationUpdated() { + _eventsSubscription?.add( + _client.on(EventType.locationUpdated).listen((event) { + final location = event.message?.sharedLocation; + if (location == null || location.isStatic) return; + + final currentUserId = currentUser?.id; + if (currentUserId == null) return; + if (location.userId != currentUserId) return; + + final newActiveLiveLocations = [ + ...activeLiveLocations.merge( + [location], + key: (it) => (it.userId, it.channelCid, it.createdByDeviceId), + update: (original, updated) => updated, + ), + ]; + + activeLiveLocations = newActiveLiveLocations; + }), + ); + } + + void _listenLocationExpired() { + _eventsSubscription?.add( + _client.on(EventType.locationExpired).listen((event) { + final location = event.message?.sharedLocation; + if (location == null || location.isStatic) return; + + final currentUserId = currentUser?.id; + if (currentUserId == null) return; + if (location.userId != currentUserId) return; + + final newActiveLiveLocations = [ + ...activeLiveLocations.where( + (it) => it.messageId != location.messageId, + ) + ]; + + activeLiveLocations = newActiveLiveLocations; + }), + ); + } + + Timer? _staleLiveLocationsCleanerTimer; + void _startCleaningExpiredLocations() { + _staleLiveLocationsCleanerTimer?.cancel(); + _staleLiveLocationsCleanerTimer = Timer.periodic( + const Duration(seconds: 1), + (_) { + final expired = activeLiveLocations.where((it) => it.isExpired); + if (expired.isEmpty) return; + + for (final sharedLocation in expired) { + final lastUpdatedAt = DateTime.timestamp(); + + final locationExpiredEvent = Event( + type: EventType.locationExpired, + cid: sharedLocation.channelCid, + message: Message( + id: sharedLocation.messageId, + updatedAt: lastUpdatedAt, + sharedLocation: sharedLocation.copyWith( + updatedAt: lastUpdatedAt, + ), + ), + ); + + _client.handleEvent(locationExpiredEvent); + } + }, + ); + } + final StreamChatClient _client; /// Sets the user currently interacting with the client @@ -2208,6 +2365,23 @@ class ClientState { /// The current user as a stream Stream> get usersStream => _usersController.stream; + /// The current active live locations shared by the user. + List get activeLiveLocations { + return _activeLiveLocationsController.value; + } + + /// The current active live locations shared by the user as a stream. + Stream> get activeLiveLocationsStream { + return _activeLiveLocationsController.stream; + } + + /// Sets the active live locations. + set activeLiveLocations(List locations) { + // For safe-keeping, we filter out any inactive locations before update. + final activeLocations = [...locations.where((it) => it.isActive)]; + _activeLiveLocationsController.add(activeLocations); + } + /// The current unread channels count int get unreadChannels => _unreadChannelsController.value; @@ -2280,14 +2454,18 @@ class ClientState { final _unreadChannelsController = BehaviorSubject.seeded(0); final _unreadThreadsController = BehaviorSubject.seeded(0); final _totalUnreadCountController = BehaviorSubject.seeded(0); + final _activeLiveLocationsController = BehaviorSubject.seeded([]); /// Call this method to dispose this object void dispose() { cancelEventSubscription(); _currentUserController.close(); + _usersController.close(); _unreadChannelsController.close(); _unreadThreadsController.close(); _totalUnreadCountController.close(); + _activeLiveLocationsController.close(); + _staleLiveLocationsCleanerTimer?.cancel(); final channels = [...this.channels.keys]; for (final channel in channels) { diff --git a/packages/stream_chat/lib/src/client/event_resolvers.dart b/packages/stream_chat/lib/src/client/event_resolvers.dart index fc2117fb58..6f462f6260 100644 --- a/packages/stream_chat/lib/src/client/event_resolvers.dart +++ b/packages/stream_chat/lib/src/client/event_resolvers.dart @@ -1,6 +1,27 @@ import 'package:stream_chat/src/core/models/event.dart'; import 'package:stream_chat/src/event_type.dart'; +/// Resolves message new events into more specific `pollCreated` events +/// for easier downstream state handling. +/// +/// Applies when: +/// - `event.type` is `messageNew` or `notification.message_new, and +/// - `event.poll` is not null +/// +/// Returns a modified event with type `pollCreated`, +/// or `null` if not applicable. +Event? pollCreatedResolver(Event event) { + final validTypes = {EventType.messageNew, EventType.notificationMessageNew}; + if (!validTypes.contains(event.type)) return null; + + final poll = event.poll; + if (poll == null) return null; + + // If the event is a message new or notification message new and + // it contains a poll, we can resolve it to a poll created event. + return event.copyWith(type: EventType.pollCreated); +} + /// Resolves casted or changed poll vote events into more specific /// `pollAnswerCasted` events for easier downstream state handling. /// @@ -11,12 +32,15 @@ import 'package:stream_chat/src/event_type.dart'; /// Returns a modified event with type `pollAnswerCasted`, /// or `null` if not applicable. Event? pollAnswerCastedResolver(Event event) { - return switch (event.type) { - EventType.pollVoteCasted || - EventType.pollVoteChanged when event.pollVote?.isAnswer == true => - event.copyWith(type: EventType.pollAnswerCasted), - _ => null, - }; + final validTypes = {EventType.pollVoteCasted, EventType.pollVoteChanged}; + if (!validTypes.contains(event.type)) return null; + + final pollVote = event.pollVote; + if (pollVote?.isAnswer == false) return null; + + // If the event is a poll vote casted or changed and it's an answer + // we can resolve it to a poll answer casted event. + return event.copyWith(type: EventType.pollAnswerCasted); } /// Resolves removed poll vote events into more specific @@ -29,9 +53,77 @@ Event? pollAnswerCastedResolver(Event event) { /// Returns a modified event with type `pollAnswerRemoved`, /// or `null` if not applicable. Event? pollAnswerRemovedResolver(Event event) { - return switch (event.type) { - EventType.pollVoteRemoved when event.pollVote?.isAnswer == true => - event.copyWith(type: EventType.pollAnswerRemoved), - _ => null, - }; + if (event.type != EventType.pollVoteRemoved) return null; + + final pollVote = event.pollVote; + if (pollVote?.isAnswer == false) return null; + + // If the event is a poll vote removed and it's an answer + // we can resolve it to a poll answer removed event. + return event.copyWith(type: EventType.pollAnswerRemoved); +} + +/// Resolves message new events into more specific `locationShared` events +/// for easier downstream state handling. +/// +/// Applies when: +/// - `event.type` is `messageNew` or `notification.message_new, and +/// - `event.message.sharedLocation` is not null +/// +/// Returns a modified event with type `locationShared`, +/// or `null` if not applicable. +Event? locationSharedResolver(Event event) { + final validTypes = {EventType.messageNew, EventType.notificationMessageNew}; + if (!validTypes.contains(event.type)) return null; + + final sharedLocation = event.message?.sharedLocation; + if (sharedLocation == null) return null; + + // If the event is a message new or notification message new and it + // contains a shared location, we can resolve it to a location shared event. + return event.copyWith(type: EventType.locationShared); +} + +/// Resolves message updated events into more specific `locationUpdated` +/// events for easier downstream state handling. +/// +/// Applies when: +/// - `event.type` is `messageUpdated`, and +/// - `event.message.sharedLocation` is not null and not expired +/// +/// Returns a modified event with type `locationUpdated`, +/// or `null` if not applicable. +Event? locationUpdatedResolver(Event event) { + if (event.type != EventType.messageUpdated) return null; + + final sharedLocation = event.message?.sharedLocation; + if (sharedLocation == null) return null; + + if (sharedLocation.isLive && sharedLocation.isExpired) return null; + + // If the location is static or still active, we can resolve it + // to a location updated event. + return event.copyWith(type: EventType.locationUpdated); +} + +/// Resolves message updated events into more specific `locationExpired` +/// events for easier downstream state handling. +/// +/// Applies when: +/// - `event.type` is `messageUpdated`, and +/// - `event.message.sharedLocation` is not null and expired +/// +/// Returns a modified event with type `locationExpired`, +/// or `null` if not applicable. +Event? locationExpiredResolver(Event event) { + if (event.type != EventType.messageUpdated) return null; + + final sharedLocation = event.message?.sharedLocation; + if (sharedLocation == null) return null; + + if (sharedLocation.isStatic || sharedLocation.isActive) return null; + + // If the location is live and expired, we can resolve it to a + // location expired event. + return event.copyWith(type: EventType.locationExpired); } diff --git a/packages/stream_chat/lib/src/core/api/responses.dart b/packages/stream_chat/lib/src/core/api/responses.dart index 0602e71f35..d8f38c7b55 100644 --- a/packages/stream_chat/lib/src/core/api/responses.dart +++ b/packages/stream_chat/lib/src/core/api/responses.dart @@ -9,6 +9,7 @@ import 'package:stream_chat/src/core/models/channel_state.dart'; import 'package:stream_chat/src/core/models/device.dart'; import 'package:stream_chat/src/core/models/draft.dart'; import 'package:stream_chat/src/core/models/event.dart'; +import 'package:stream_chat/src/core/models/location.dart'; import 'package:stream_chat/src/core/models/member.dart'; import 'package:stream_chat/src/core/models/message.dart'; import 'package:stream_chat/src/core/models/message_reminder.dart'; @@ -802,3 +803,14 @@ class QueryRemindersResponse extends _BaseResponse { static QueryRemindersResponse fromJson(Map json) => _$QueryRemindersResponseFromJson(json); } + +/// Model response for [StreamChatClient.updateDraft] api call +@JsonSerializable(createToJson: false) +class GetActiveLiveLocationsResponse extends _BaseResponse { + /// List of active live locations returned by the api call + late List activeLiveLocations; + + /// Create a new instance from a json + static GetActiveLiveLocationsResponse fromJson(Map json) => + _$GetActiveLiveLocationsResponseFromJson(json); +} diff --git a/packages/stream_chat/lib/src/core/api/responses.g.dart b/packages/stream_chat/lib/src/core/api/responses.g.dart index 75dcc1595e..fb0ae89527 100644 --- a/packages/stream_chat/lib/src/core/api/responses.g.dart +++ b/packages/stream_chat/lib/src/core/api/responses.g.dart @@ -467,3 +467,11 @@ QueryRemindersResponse _$QueryRemindersResponseFromJson( .toList() ?? [] ..next = json['next'] as String?; + +GetActiveLiveLocationsResponse _$GetActiveLiveLocationsResponseFromJson( + Map json) => + GetActiveLiveLocationsResponse() + ..duration = json['duration'] as String? + ..activeLiveLocations = (json['active_live_locations'] as List) + .map((e) => Location.fromJson(e as Map)) + .toList(); diff --git a/packages/stream_chat/lib/src/core/api/user_api.dart b/packages/stream_chat/lib/src/core/api/user_api.dart index c94c344bec..b08f2a96ed 100644 --- a/packages/stream_chat/lib/src/core/api/user_api.dart +++ b/packages/stream_chat/lib/src/core/api/user_api.dart @@ -5,6 +5,8 @@ import 'package:stream_chat/src/core/api/responses.dart'; import 'package:stream_chat/src/core/api/sort_order.dart'; import 'package:stream_chat/src/core/http/stream_http_client.dart'; import 'package:stream_chat/src/core/models/filter.dart'; +import 'package:stream_chat/src/core/models/location.dart'; +import 'package:stream_chat/src/core/models/location_coordinates.dart'; import 'package:stream_chat/src/core/models/user.dart'; /// Defines the api dedicated to users operations @@ -88,4 +90,34 @@ class UserApi { return BlockedUsersResponse.fromJson(response.data); } + + /// Retrieves all the active live locations of the current user. + Future getActiveLiveLocations() async { + final response = await _client.get( + '/users/live_locations', + ); + + return GetActiveLiveLocationsResponse.fromJson(response.data); + } + + /// Updates an existing live location created by the current user. + Future updateLiveLocation({ + required String messageId, + required String createdByDeviceId, + LocationCoordinates? location, + DateTime? endAt, + }) async { + final response = await _client.put( + '/users/live_locations', + data: json.encode({ + 'message_id': messageId, + 'created_by_device_id': createdByDeviceId, + if (location?.latitude case final latitude) 'latitude': latitude, + if (location?.longitude case final longitude) 'longitude': longitude, + if (endAt != null) 'end_at': endAt.toIso8601String(), + }), + ); + + return Location.fromJson(response.data); + } } diff --git a/packages/stream_chat/lib/src/core/models/channel_config.dart b/packages/stream_chat/lib/src/core/models/channel_config.dart index 2bcf0a1ed5..489b71e334 100644 --- a/packages/stream_chat/lib/src/core/models/channel_config.dart +++ b/packages/stream_chat/lib/src/core/models/channel_config.dart @@ -26,6 +26,7 @@ class ChannelConfig { this.urlEnrichment = false, this.skipLastMsgUpdateForSystemMsgs = false, this.userMessageReminders = false, + this.sharedLocations = false, }) : createdAt = createdAt ?? DateTime.now(), updatedAt = updatedAt ?? DateTime.now(); @@ -91,6 +92,9 @@ class ChannelConfig { /// True if the user can set reminders for messages in this channel. final bool userMessageReminders; + /// True if shared locations are enabled for this channel. + final bool sharedLocations; + /// Serialize to json Map toJson() => _$ChannelConfigToJson(this); } diff --git a/packages/stream_chat/lib/src/core/models/channel_config.g.dart b/packages/stream_chat/lib/src/core/models/channel_config.g.dart index 8cb758b875..1a57d3e743 100644 --- a/packages/stream_chat/lib/src/core/models/channel_config.g.dart +++ b/packages/stream_chat/lib/src/core/models/channel_config.g.dart @@ -34,6 +34,7 @@ ChannelConfig _$ChannelConfigFromJson(Map json) => skipLastMsgUpdateForSystemMsgs: json['skip_last_msg_update_for_system_msgs'] as bool? ?? false, userMessageReminders: json['user_message_reminders'] as bool? ?? false, + sharedLocations: json['shared_locations'] as bool? ?? false, ); Map _$ChannelConfigToJson(ChannelConfig instance) => @@ -57,4 +58,5 @@ Map _$ChannelConfigToJson(ChannelConfig instance) => 'skip_last_msg_update_for_system_msgs': instance.skipLastMsgUpdateForSystemMsgs, 'user_message_reminders': instance.userMessageReminders, + 'shared_locations': instance.sharedLocations, }; diff --git a/packages/stream_chat/lib/src/core/models/channel_model.dart b/packages/stream_chat/lib/src/core/models/channel_model.dart index d55f0e42b5..49a3c99bf2 100644 --- a/packages/stream_chat/lib/src/core/models/channel_model.dart +++ b/packages/stream_chat/lib/src/core/models/channel_model.dart @@ -366,4 +366,7 @@ extension type const ChannelCapability(String capability) implements String { /// Ability to query poll votes. static const queryPollVotes = ChannelCapability('query-poll-votes'); + + /// Ability to share location. + static const shareLocation = ChannelCapability('share-location'); } diff --git a/packages/stream_chat/lib/src/core/models/channel_state.dart b/packages/stream_chat/lib/src/core/models/channel_state.dart index ae7b9062b6..3e06a86d79 100644 --- a/packages/stream_chat/lib/src/core/models/channel_state.dart +++ b/packages/stream_chat/lib/src/core/models/channel_state.dart @@ -2,6 +2,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:stream_chat/src/core/models/channel_model.dart'; import 'package:stream_chat/src/core/models/comparable_field.dart'; import 'package:stream_chat/src/core/models/draft.dart'; +import 'package:stream_chat/src/core/models/location.dart'; import 'package:stream_chat/src/core/models/member.dart'; import 'package:stream_chat/src/core/models/message.dart'; import 'package:stream_chat/src/core/models/read.dart'; @@ -29,6 +30,7 @@ class ChannelState implements ComparableFieldProvider { this.read, this.membership, this.draft, + this.activeLiveLocations, }); /// The channel to which this state belongs @@ -58,6 +60,9 @@ class ChannelState implements ComparableFieldProvider { /// The draft message for this channel if it exists. final Draft? draft; + /// The list of active live locations in the channel. + final List? activeLiveLocations; + /// Create a new instance from a json static ChannelState fromJson(Map json) => _$ChannelStateFromJson(json); @@ -76,6 +81,7 @@ class ChannelState implements ComparableFieldProvider { List? read, Member? membership, Object? draft = _nullConst, + List? activeLiveLocations, }) => ChannelState( channel: channel ?? this.channel, @@ -87,6 +93,7 @@ class ChannelState implements ComparableFieldProvider { read: read ?? this.read, membership: membership ?? this.membership, draft: draft == _nullConst ? this.draft : draft as Draft?, + activeLiveLocations: activeLiveLocations ?? this.activeLiveLocations, ); @override diff --git a/packages/stream_chat/lib/src/core/models/channel_state.g.dart b/packages/stream_chat/lib/src/core/models/channel_state.g.dart index 88bd81e77e..99d5098b2e 100644 --- a/packages/stream_chat/lib/src/core/models/channel_state.g.dart +++ b/packages/stream_chat/lib/src/core/models/channel_state.g.dart @@ -32,6 +32,9 @@ ChannelState _$ChannelStateFromJson(Map json) => ChannelState( draft: json['draft'] == null ? null : Draft.fromJson(json['draft'] as Map), + activeLiveLocations: (json['active_live_locations'] as List?) + ?.map((e) => Location.fromJson(e as Map)) + .toList(), ); Map _$ChannelStateToJson(ChannelState instance) => @@ -46,4 +49,6 @@ Map _$ChannelStateToJson(ChannelState instance) => 'read': instance.read?.map((e) => e.toJson()).toList(), 'membership': instance.membership?.toJson(), 'draft': instance.draft?.toJson(), + 'active_live_locations': + instance.activeLiveLocations?.map((e) => e.toJson()).toList(), }; diff --git a/packages/stream_chat/lib/src/core/models/location.dart b/packages/stream_chat/lib/src/core/models/location.dart new file mode 100644 index 0000000000..bfdd2aaa28 --- /dev/null +++ b/packages/stream_chat/lib/src/core/models/location.dart @@ -0,0 +1,156 @@ +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:stream_chat/src/core/models/channel_model.dart'; +import 'package:stream_chat/src/core/models/location_coordinates.dart'; +import 'package:stream_chat/src/core/models/message.dart'; + +part 'location.g.dart'; + +/// {@template location} +/// A model class representing a shared location. +/// +/// The [Location] represents a location shared in a channel message. +/// +/// It can be of two types: +/// 1. **Static Location**: A location that does not change over time and has +/// no end time. +/// 2. **Live Location**: A location that updates in real-time and has an +/// end time. +/// {@endtemplate} +@JsonSerializable() +class Location extends Equatable { + /// {@macro location} + Location({ + this.channelCid, + this.channel, + this.messageId, + this.message, + this.userId, + required this.latitude, + required this.longitude, + required this.createdByDeviceId, + this.endAt, + DateTime? createdAt, + DateTime? updatedAt, + }) : createdAt = createdAt ?? DateTime.now(), + updatedAt = updatedAt ?? DateTime.now(); + + /// Create a new instance from a json + factory Location.fromJson(Map json) => + _$LocationFromJson(json); + + /// The channel CID where the message exists. + /// + /// This is only available if the location is coming from server response. + @JsonKey(includeToJson: false) + final String? channelCid; + + /// The channel where the message exists. + @JsonKey(includeToJson: false) + final ChannelModel? channel; + + /// The ID of the message that contains the shared location. + @JsonKey(includeToJson: false) + final String? messageId; + + /// The message that contains the shared location. + @JsonKey(includeToJson: false) + final Message? message; + + /// The ID of the user who shared the location. + @JsonKey(includeToJson: false) + final String? userId; + + /// The latitude of the shared location. + final double latitude; + + /// The longitude of the shared location. + final double longitude; + + /// The ID of the device that created the reminder. + final String createdByDeviceId; + + /// The date at which the shared location will end. + @JsonKey(includeIfNull: false) + final DateTime? endAt; + + /// The date at which the reminder was created. + @JsonKey(includeToJson: false) + final DateTime createdAt; + + /// The date at which the reminder was last updated. + @JsonKey(includeToJson: false) + final DateTime updatedAt; + + /// Returns true if the live location is still active (end_at > now) + bool get isActive { + final endAt = this.endAt; + if (endAt == null) return false; + + return endAt.isAfter(DateTime.now()); + } + + /// Returns true if the live location is expired (end_at <= now) + bool get isExpired => !isActive; + + /// Returns true if this is a live location (has end_at) + bool get isLive => endAt != null; + + /// Returns true if this is a static location (no end_at) + bool get isStatic => endAt == null; + + /// Returns the coordinates of the shared location. + LocationCoordinates get coordinates { + return LocationCoordinates( + latitude: latitude, + longitude: longitude, + ); + } + + /// Serialize to json + Map toJson() => _$LocationToJson(this); + + /// Creates a copy of [Location] with specified attributes overridden. + Location copyWith({ + String? channelCid, + ChannelModel? channel, + String? messageId, + Message? message, + String? userId, + double? latitude, + double? longitude, + String? createdByDeviceId, + DateTime? endAt, + DateTime? createdAt, + DateTime? updatedAt, + }) { + return Location( + channelCid: channelCid ?? this.channelCid, + channel: channel ?? this.channel, + messageId: messageId ?? this.messageId, + message: message ?? this.message, + userId: userId ?? this.userId, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + createdByDeviceId: createdByDeviceId ?? this.createdByDeviceId, + endAt: endAt ?? this.endAt, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ); + } + + @override + List get props => [ + channelCid, + channel, + messageId, + message, + userId, + latitude, + longitude, + createdByDeviceId, + endAt, + createdAt, + updatedAt, + ]; +} diff --git a/packages/stream_chat/lib/src/core/models/location.g.dart b/packages/stream_chat/lib/src/core/models/location.g.dart new file mode 100644 index 0000000000..e5a3b49028 --- /dev/null +++ b/packages/stream_chat/lib/src/core/models/location.g.dart @@ -0,0 +1,38 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'location.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Location _$LocationFromJson(Map json) => Location( + channelCid: json['channel_cid'] as String?, + channel: json['channel'] == null + ? null + : ChannelModel.fromJson(json['channel'] as Map), + messageId: json['message_id'] as String?, + message: json['message'] == null + ? null + : Message.fromJson(json['message'] as Map), + userId: json['user_id'] as String?, + latitude: (json['latitude'] as num).toDouble(), + longitude: (json['longitude'] as num).toDouble(), + createdByDeviceId: json['created_by_device_id'] as String, + endAt: json['end_at'] == null + ? null + : DateTime.parse(json['end_at'] as String), + createdAt: json['created_at'] == null + ? null + : DateTime.parse(json['created_at'] as String), + updatedAt: json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at'] as String), + ); + +Map _$LocationToJson(Location instance) => { + 'latitude': instance.latitude, + 'longitude': instance.longitude, + 'created_by_device_id': instance.createdByDeviceId, + if (instance.endAt?.toIso8601String() case final value?) 'end_at': value, + }; diff --git a/packages/stream_chat/lib/src/core/models/location_coordinates.dart b/packages/stream_chat/lib/src/core/models/location_coordinates.dart new file mode 100644 index 0000000000..f23389d7e6 --- /dev/null +++ b/packages/stream_chat/lib/src/core/models/location_coordinates.dart @@ -0,0 +1,33 @@ +import 'package:equatable/equatable.dart'; + +/// {@template locationInfo} +/// A model class representing a location with latitude and longitude. +/// {@endtemplate} +class LocationCoordinates extends Equatable { + /// {@macro locationInfo} + const LocationCoordinates({ + required this.latitude, + required this.longitude, + }); + + /// The latitude of the location. + final double latitude; + + /// The longitude of the location. + final double longitude; + + /// Creates a copy of [LocationCoordinates] with specified attributes + /// overridden. + LocationCoordinates copyWith({ + double? latitude, + double? longitude, + }) { + return LocationCoordinates( + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + ); + } + + @override + List get props => [latitude, longitude]; +} diff --git a/packages/stream_chat/lib/src/core/models/message.dart b/packages/stream_chat/lib/src/core/models/message.dart index 93847c11af..8fcd00f872 100644 --- a/packages/stream_chat/lib/src/core/models/message.dart +++ b/packages/stream_chat/lib/src/core/models/message.dart @@ -4,6 +4,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:stream_chat/src/core/models/attachment.dart'; import 'package:stream_chat/src/core/models/comparable_field.dart'; import 'package:stream_chat/src/core/models/draft.dart'; +import 'package:stream_chat/src/core/models/location.dart'; import 'package:stream_chat/src/core/models/message_reminder.dart'; import 'package:stream_chat/src/core/models/message_state.dart'; import 'package:stream_chat/src/core/models/moderation.dart'; @@ -69,6 +70,7 @@ class Message extends Equatable implements ComparableFieldProvider { this.moderation, this.draft, this.reminder, + this.sharedLocation, }) : id = id ?? const Uuid().v4(), type = MessageType(type), pinExpires = pinExpires?.toUtc(), @@ -307,6 +309,7 @@ class Message extends Equatable implements ComparableFieldProvider { /// Optional draft message linked to this message. /// /// This is present when the message is a thread i.e. contains replies. + @JsonKey(includeToJson: false) final Draft? draft; /// Optional reminder for this message. @@ -314,6 +317,12 @@ class Message extends Equatable implements ComparableFieldProvider { /// This is present when a user has set a reminder for this message. final MessageReminder? reminder; + /// Optional shared location associated with this message. + /// + /// This is used to share a location in a message, allowing users to view the + /// location on a map. + final Location? sharedLocation; + /// Message custom extraData. final Map extraData; @@ -362,6 +371,7 @@ class Message extends Equatable implements ComparableFieldProvider { 'moderation_details', 'draft', 'reminder', + 'shared_location', ]; /// Serialize to json. @@ -424,6 +434,7 @@ class Message extends Equatable implements ComparableFieldProvider { Moderation? moderation, Object? draft = _nullConst, Object? reminder = _nullConst, + Location? sharedLocation, }) { assert(() { if (pinExpires is! DateTime && @@ -506,6 +517,7 @@ class Message extends Equatable implements ComparableFieldProvider { draft: draft == _nullConst ? this.draft : draft as Draft?, reminder: reminder == _nullConst ? this.reminder : reminder as MessageReminder?, + sharedLocation: sharedLocation ?? this.sharedLocation, ); } @@ -551,6 +563,7 @@ class Message extends Equatable implements ComparableFieldProvider { moderation: other.moderation, draft: other.draft, reminder: other.reminder, + sharedLocation: other.sharedLocation, ); } @@ -616,7 +629,8 @@ class Message extends Equatable implements ComparableFieldProvider { moderation, draft, reminder, - ]; + sharedLocation, + ]; @override ComparableField? getComparableField(String sortKey) { diff --git a/packages/stream_chat/lib/src/core/models/message.g.dart b/packages/stream_chat/lib/src/core/models/message.g.dart index cc90809bd9..1e108ac986 100644 --- a/packages/stream_chat/lib/src/core/models/message.g.dart +++ b/packages/stream_chat/lib/src/core/models/message.g.dart @@ -95,6 +95,9 @@ Message _$MessageFromJson(Map json) => Message( reminder: json['reminder'] == null ? null : MessageReminder.fromJson(json['reminder'] as Map), + sharedLocation: json['shared_location'] == null + ? null + : Location.fromJson(json['shared_location'] as Map), ); Map _$MessageToJson(Message instance) => { @@ -112,7 +115,7 @@ Map _$MessageToJson(Message instance) => { 'poll_id': instance.pollId, if (instance.restrictedVisibility case final value?) 'restricted_visibility': value, - 'draft': instance.draft?.toJson(), 'reminder': instance.reminder?.toJson(), + 'shared_location': instance.sharedLocation?.toJson(), 'extra_data': instance.extraData, }; diff --git a/packages/stream_chat/lib/src/event_type.dart b/packages/stream_chat/lib/src/event_type.dart index 29ab5b1de8..189350d959 100644 --- a/packages/stream_chat/lib/src/event_type.dart +++ b/packages/stream_chat/lib/src/event_type.dart @@ -122,6 +122,9 @@ class EventType { /// Event sent when the AI indicator is cleared static const String aiIndicatorClear = 'ai_indicator.clear'; + /// Event sent when a new poll is created. + static const String pollCreated = 'poll.created'; + /// Event sent when a poll is updated. static const String pollUpdated = 'poll.updated'; @@ -170,4 +173,13 @@ class EventType { /// Event sent when a message reminder is due. static const String notificationReminderDue = 'notification.reminder_due'; + + /// Event sent when a new shared location is created. + static const String locationShared = 'location.shared'; + + /// Event sent when a live shared location is updated. + static const String locationUpdated = 'location.updated'; + + /// Event sent when a live shared location is expired. + static const String locationExpired = 'location.expired'; } diff --git a/packages/stream_chat/lib/stream_chat.dart b/packages/stream_chat/lib/stream_chat.dart index ea60b484b8..0093a7c6b6 100644 --- a/packages/stream_chat/lib/stream_chat.dart +++ b/packages/stream_chat/lib/stream_chat.dart @@ -42,6 +42,8 @@ export 'src/core/models/draft.dart'; export 'src/core/models/draft_message.dart'; export 'src/core/models/event.dart'; export 'src/core/models/filter.dart' show Filter; +export 'src/core/models/location.dart'; +export 'src/core/models/location_coordinates.dart'; export 'src/core/models/member.dart'; export 'src/core/models/message.dart'; export 'src/core/models/message_reminder.dart'; diff --git a/sample_app/android/app/src/main/AndroidManifest.xml b/sample_app/android/app/src/main/AndroidManifest.xml index 8ff8f0abb5..6fb866b633 100644 --- a/sample_app/android/app/src/main/AndroidManifest.xml +++ b/sample_app/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,13 @@ + + + + + + + ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) + ITSAppUsesNonExemptEncryption + LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAppleMusicUsageDescription Used to send message attachments NSCameraUsageDescription Used to send message attachments + NSLocationWhenInUseUsageDescription + We need access to your location to share it in the chat. + NSLocationAlwaysUsageDescription + We need access to your location to share it in the chat. NSMicrophoneUsageDescription Used to send message attachments NSPhotoLibraryUsageDescription @@ -43,6 +54,7 @@ fetch remote-notification + location UILaunchStoryboardName LaunchScreen @@ -65,12 +77,5 @@ UIViewControllerBasedStatusBarAppearance - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - ITSAppUsesNonExemptEncryption - diff --git a/sample_app/lib/pages/channel_list_page.dart b/sample_app/lib/pages/channel_list_page.dart index 6084a038fa..f7a8fb5934 100644 --- a/sample_app/lib/pages/channel_list_page.dart +++ b/sample_app/lib/pages/channel_list_page.dart @@ -17,6 +17,7 @@ import 'package:sample_app/routes/routes.dart'; import 'package:sample_app/state/init_data.dart'; import 'package:sample_app/utils/app_config.dart'; import 'package:sample_app/utils/localizations.dart'; +import 'package:sample_app/utils/shared_location_service.dart'; import 'package:sample_app/widgets/channel_list.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; @@ -105,6 +106,10 @@ class _ChannelListPageState extends State { ]; } + late final _locationService = SharedLocationService( + client: StreamChat.of(context).client, + ); + @override Widget build(BuildContext context) { final user = StreamChat.of(context).currentUser; @@ -156,6 +161,7 @@ class _ChannelListPageState extends State { @override void initState() { + super.initState(); if (!kIsWeb) { badgeListener = StreamChat.of(context) .client @@ -169,12 +175,14 @@ class _ChannelListPageState extends State { } }); } - super.initState(); + + _locationService.initialize(); } @override void dispose() { badgeListener?.cancel(); + _locationService.dispose(); super.dispose(); } } diff --git a/sample_app/lib/pages/channel_page.dart b/sample_app/lib/pages/channel_page.dart index ba7603935f..71cb913aef 100644 --- a/sample_app/lib/pages/channel_page.dart +++ b/sample_app/lib/pages/channel_page.dart @@ -5,6 +5,10 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:sample_app/pages/thread_page.dart'; import 'package:sample_app/routes/routes.dart'; +import 'package:sample_app/widgets/location/location_attachment.dart'; +import 'package:sample_app/widgets/location/location_detail_dialog.dart'; +import 'package:sample_app/widgets/location/location_picker_dialog.dart'; +import 'package:sample_app/widgets/location/location_picker_option.dart'; import 'package:sample_app/widgets/reminder_dialog.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -25,8 +29,7 @@ class ChannelPage extends StatefulWidget { class _ChannelPageState extends State { FocusNode? _focusNode; - final StreamMessageInputController _messageInputController = - StreamMessageInputController(); + final _messageInputController = StreamMessageInputController(); @override void initState() { @@ -53,6 +56,8 @@ class _ChannelPageState extends State { final textTheme = theme.textTheme; final colorTheme = theme.colorTheme; + final channel = StreamChannel.of(context).channel; + return Scaffold( backgroundColor: colorTheme.appBg, appBar: StreamChannelHeader( @@ -124,12 +129,76 @@ class _ChannelPageState extends State { messageInputController: _messageInputController, onQuotedMessageCleared: _messageInputController.clearQuotedMessage, enableVoiceRecording: true, + allowedAttachmentPickerTypes: [ + ...AttachmentPickerType.values, + if (channel.canShareLocation) const LocationPickerType(), + ], + onCustomAttachmentPickerResult: (result) { + return _onCustomAttachmentPickerResult(channel, result).ignore(); + }, + customAttachmentPickerOptions: [ + TabbedAttachmentPickerOption( + key: 'location-picker', + icon: const Icon(Icons.near_me_rounded), + supportedTypes: [const LocationPickerType()], + isEnabled: (value) { + // Enable if nothing has been selected yet. + if (value.isEmpty) return true; + + // Otherwise, enable only if there is a location. + return value.extraData['location'] != null; + }, + optionViewBuilder: (context, controller) => LocationPicker( + onLocationPicked: (locationResult) { + if (locationResult == null) return Navigator.pop(context); + + controller.extraData = { + ...controller.value.extraData, + 'location': locationResult, + }; + + final result = LocationPicked(location: locationResult); + return Navigator.pop(context, result); + }, + ), + ), + ], ), ], ), ); } + Future _onCustomAttachmentPickerResult( + Channel channel, + CustomAttachmentPickerResult result, + ) async { + final response = switch (result) { + LocationPicked() => _onShareLocationPicked(channel, result.location), + _ => null, + }; + + return response?.ignore(); + } + + Future _onShareLocationPicked( + Channel channel, + LocationPickerResult result, + ) async { + if (result.endSharingAt case final endSharingAt?) { + return channel.startLiveLocationSharing( + createdByDeviceId: 'test-device-id', + endSharingAt: endSharingAt, + location: result.coordinates, + ); + } + + return channel.sendStaticLocation( + createdByDeviceId: 'test-device-id', + location: result.coordinates, + ); + } + Widget customMessageBuilder( BuildContext context, MessageDetails details, @@ -142,7 +211,8 @@ class _ChannelPageState extends State { final message = details.message; final reminder = message.reminder; - final channelConfig = StreamChannel.of(context).channel.config; + final channel = StreamChannel.of(context).channel; + final channelConfig = channel.config; final customOptions = [ if (channelConfig?.userMessageReminders == true) ...[ @@ -184,6 +254,13 @@ class _ChannelPageState extends State { ] ]; + final locationAttachmentBuilder = LocationAttachmentBuilder( + onAttachmentTap: (location) => showLocationDetailDialog( + context: context, + location: location, + ), + ); + return Container( color: reminder != null ? colorTheme.accentPrimary.withOpacity(.1) : null, child: Column( @@ -220,6 +297,7 @@ class _ChannelPageState extends State { defaultMessageWidget.copyWith( onReplyTap: _reply, customActions: customOptions, + showEditMessage: message.sharedLocation == null, onCustomActionTap: (it) async => await switch (it) { CreateReminder() => _createReminder(it.message), CreateBookmark() => _createBookmark(it.message), @@ -227,6 +305,7 @@ class _ChannelPageState extends State { RemoveReminder() => _removeReminder(it.message, it.reminder), _ => null, }, + attachmentBuilders: [locationAttachmentBuilder], onShowMessage: (message, channel) => GoRouter.of(context).goNamed( Routes.CHANNEL_PAGE.name, pathParameters: Routes.CHANNEL_PAGE.params(channel), diff --git a/sample_app/lib/pages/thread_page.dart b/sample_app/lib/pages/thread_page.dart index 622b5772ca..3e8376eb44 100644 --- a/sample_app/lib/pages/thread_page.dart +++ b/sample_app/lib/pages/thread_page.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:sample_app/widgets/location/location_attachment.dart'; +import 'package:sample_app/widgets/location/location_detail_dialog.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class ThreadPage extends StatefulWidget { @@ -43,6 +45,13 @@ class _ThreadPageState extends State { @override Widget build(BuildContext context) { + final locationAttachmentBuilder = LocationAttachmentBuilder( + onAttachmentTap: (location) => showLocationDetailDialog( + context: context, + location: location, + ), + ); + return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: StreamThreadHeader( @@ -59,9 +68,18 @@ class _ThreadPageState extends State { messageFilter: defaultFilter, showScrollToBottom: false, highlightInitialMessage: true, + parentMessageBuilder: (context, message, defaultMessage) { + return defaultMessage.copyWith( + attachmentBuilders: [locationAttachmentBuilder], + ); + }, messageBuilder: (context, details, messages, defaultMessage) { + final message = details.message; + return defaultMessage.copyWith( onReplyTap: _reply, + showEditMessage: message.sharedLocation == null, + attachmentBuilders: [locationAttachmentBuilder], bottomRowBuilderWithDefaultWidget: ( context, message, diff --git a/sample_app/lib/utils/app_config.dart b/sample_app/lib/utils/app_config.dart index e006cddfee..c99afeb7ec 100644 --- a/sample_app/lib/utils/app_config.dart +++ b/sample_app/lib/utils/app_config.dart @@ -3,9 +3,13 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; const sentryDsn = 'https://6381ef88de4140db8f5e25ab37e0f08c@o1213503.ingest.sentry.io/6352870'; -const kDefaultStreamApiKey = 'kv7mcsxr24p8'; +const kDefaultStreamApiKey = 'pd67s34fzpgw'; final defaultUsers = { + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibGVpYV9vcmdhbmEifQ.8NXs4DZrx_hljsaC8d6xlZ07FUgenKmb6hDNU-KFQ3M': + User( + id: 'leia_organa', + ), 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8': User( id: 'salvatore', diff --git a/sample_app/lib/utils/location_provider.dart b/sample_app/lib/utils/location_provider.dart new file mode 100644 index 0000000000..5a572c99af --- /dev/null +++ b/sample_app/lib/utils/location_provider.dart @@ -0,0 +1,96 @@ +import 'dart:async'; + +import 'package:geolocator/geolocator.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +const notificationTitle = 'Live Location Tracking'; +const notificationText = 'Your location is being tracked live.'; + +class LocationProvider { + factory LocationProvider() => _instance; + LocationProvider._(); + + static final LocationProvider _instance = LocationProvider._(); + + Stream get positionStream => _positionStreamController.stream; + final _positionStreamController = StreamController.broadcast(); + + StreamSubscription? _positionSubscription; + + /// Get current static location + Future getCurrentLocation() async { + final hasPermission = await _handlePermission(); + if (!hasPermission) return null; + + return Geolocator.getCurrentPosition(); + } + + /// Start live tracking + Future startTracking({ + int distanceFilter = 10, + LocationAccuracy accuracy = LocationAccuracy.high, + ActivityType activityType = ActivityType.automotiveNavigation, + }) async { + final hasPermission = await _handlePermission(); + if (!hasPermission) return; + + final settings = switch (CurrentPlatform.type) { + PlatformType.android => AndroidSettings( + accuracy: accuracy, + distanceFilter: distanceFilter, + foregroundNotificationConfig: const ForegroundNotificationConfig( + setOngoing: true, + notificationText: notificationText, + notificationTitle: notificationTitle, + notificationIcon: AndroidResource(name: 'ic_notification'), + ), + ), + PlatformType.ios || PlatformType.macOS => AppleSettings( + accuracy: accuracy, + activityType: activityType, + distanceFilter: distanceFilter, + showBackgroundLocationIndicator: true, + pauseLocationUpdatesAutomatically: true, + ), + _ => LocationSettings( + accuracy: accuracy, + distanceFilter: distanceFilter, + ) + }; + + _positionSubscription?.cancel(); // avoid duplicate subscriptions + _positionSubscription = Geolocator.getPositionStream( + locationSettings: settings, + ).listen( + _positionStreamController.add, + onError: _positionStreamController.addError, + ); + } + + /// Stop live tracking + void stopTracking() { + _positionSubscription?.cancel(); + _positionSubscription = null; + } + + /// Clean up resources + void reset() { + stopTracking(); + _positionStreamController.close(); + } + + Future _handlePermission() async { + final serviceEnabled = await Geolocator.isLocationServiceEnabled(); + if (!serviceEnabled) return false; + + var permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + } + + return switch (permission) { + LocationPermission.denied || LocationPermission.deniedForever => false, + _ => true, + }; + } +} diff --git a/sample_app/lib/utils/shared_location_service.dart b/sample_app/lib/utils/shared_location_service.dart new file mode 100644 index 0000000000..6eb24c890b --- /dev/null +++ b/sample_app/lib/utils/shared_location_service.dart @@ -0,0 +1,91 @@ +import 'dart:async'; + +import 'package:geolocator/geolocator.dart'; +import 'package:rxdart/rxdart.dart'; +import 'package:sample_app/utils/location_provider.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class SharedLocationService { + SharedLocationService({ + required StreamChatClient client, + LocationProvider? locationProvider, + }) : _client = client, + _locationProvider = locationProvider ?? LocationProvider(); + + final StreamChatClient _client; + final LocationProvider _locationProvider; + + StreamSubscription? _positionSubscription; + StreamSubscription>? _activeLiveLocationsSubscription; + + Future initialize() async { + _activeLiveLocationsSubscription?.cancel(); + _activeLiveLocationsSubscription = _client.state.activeLiveLocationsStream + .distinct((prev, curr) => prev.length == curr.length) + .listen((locations) async { + // If there are no more active locations to update, stop tracking. + if (locations.isEmpty) return _stopTrackingLocation(); + + // Otherwise, start tracking the user's location. + return _startTrackingLocation(); + }); + + return _client.getActiveLiveLocations().ignore(); + } + + Future _startTrackingLocation() async { + if (_positionSubscription != null) return; + + // Start listening to the position stream. + _positionSubscription = _locationProvider.positionStream + .throttleTime(const Duration(seconds: 3)) + .listen(_onPositionUpdate); + + return _locationProvider.startTracking(); + } + + void _stopTrackingLocation() { + _locationProvider.stopTracking(); + + // Stop tracking the user's location + _positionSubscription?.cancel(); + _positionSubscription = null; + } + + void _onPositionUpdate(Position position) { + // Handle location updates, e.g., update the UI or send to server + final activeLiveLocations = _client.state.activeLiveLocations; + if (activeLiveLocations.isEmpty) return _stopTrackingLocation(); + + // Update all active live locations + for (final location in activeLiveLocations) { + // Skip if the location is not live or has expired + if (location.isLive && location.isExpired) continue; + + // Skip if the location does not have a messageId + final messageId = location.messageId; + if (messageId == null) continue; + + // Update the live location with the new position + _client.updateLiveLocation( + messageId: messageId, + createdByDeviceId: location.createdByDeviceId, + location: LocationCoordinates( + latitude: position.latitude, + longitude: position.longitude, + ), + ); + } + } + + /// Clean up resources + Future dispose() async { + _locationProvider.reset(); + + _positionSubscription?.cancel(); + _positionSubscription = null; + + _activeLiveLocationsSubscription?.cancel(); + _activeLiveLocationsSubscription = null; + } +} diff --git a/sample_app/lib/widgets/channel_list.dart b/sample_app/lib/widgets/channel_list.dart index c2dab2bb85..cdc130779c 100644 --- a/sample_app/lib/widgets/channel_list.dart +++ b/sample_app/lib/widgets/channel_list.dart @@ -61,7 +61,7 @@ class _ChannelList extends State { ChannelSortKey.pinnedAt, nullOrdering: NullOrdering.nullsLast, ), - const SortOption.desc(ChannelSortKey.lastMessageAt), + const SortOption.desc(ChannelSortKey.lastUpdated), ], limit: 30, ); @@ -251,6 +251,114 @@ class _ChannelListDefault extends StatelessWidget { ), ); } + + // BuildContext context, + // List items, + // int index, + // WidgetType defaultWidget, + + // Widget _customChannelTileBuilder( + // BuildContext context, + // List channels, + // int index, + // StreamChannelListTile defaultWidget, + // ) { + // final chatTheme = StreamChatTheme.of(context); + // final channel = channels[index]; + // final backgroundColor = chatTheme.colorTheme.inputBg; + // final canDeleteChannel = channel.canDeleteChannel; + // + // final lastMessage = channel.state?.lastMessage; + // + // final channelSubtitle = + // + // final channelTile = ColoredBox( + // color: switch (channel.isPinned) { + // true => chatTheme.colorTheme.highlight, + // false => Colors.transparent, + // }, + // child: defaultWidget.copyWith( + // subtitle: ChannelListTileSubtitle( + // channel: channel, + // textStyle: channelPreviewTheme.subtitleStyle, + // ), + // ), + // ); + // + // return Slidable( + // groupTag: 'channels-actions', + // endActionPane: ActionPane( + // extentRatio: canDeleteChannel ? 0.40 : 0.20, + // motion: const BehindMotion(), + // children: [ + // CustomSlidableAction( + // backgroundColor: backgroundColor, + // onPressed: (_) { + // showChannelInfoModalBottomSheet( + // context: context, + // channel: channel, + // onViewInfoTap: () { + // Navigator.pop(context); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) { + // final isOneToOne = + // channel.memberCount == 2 && channel.isDistinct; + // return StreamChannel( + // channel: channel, + // child: isOneToOne + // ? ChatInfoScreen( + // messageTheme: chatTheme.ownMessageTheme, + // user: channel.state!.members + // .where((m) => + // m.userId != + // channel.client.state.currentUser!.id) + // .first + // .user, + // ) + // : GroupInfoScreen( + // messageTheme: chatTheme.ownMessageTheme, + // ), + // ); + // }, + // ), + // ); + // }, + // ); + // }, + // child: const Icon(Icons.more_horiz), + // ), + // if (canDeleteChannel) + // CustomSlidableAction( + // backgroundColor: backgroundColor, + // child: StreamSvgIcon( + // icon: StreamSvgIcons.delete, + // color: chatTheme.colorTheme.accentError, + // ), + // onPressed: (_) async { + // final res = await showConfirmationBottomSheet( + // context, + // title: 'Delete Conversation', + // question: + // 'Are you sure you want to delete this conversation?', + // okText: 'Delete', + // cancelText: 'Cancel', + // icon: StreamSvgIcon( + // icon: StreamSvgIcons.delete, + // color: chatTheme.colorTheme.accentError, + // ), + // ); + // if (res == true) { + // await channelListController.deleteChannel(channel); + // } + // }, + // ), + // ], + // ), + // child: channelTile, + // ); + // } } class _ChannelListSearch extends StatelessWidget { diff --git a/sample_app/lib/widgets/location/location_attachment.dart b/sample_app/lib/widgets/location/location_attachment.dart new file mode 100644 index 0000000000..9770e16419 --- /dev/null +++ b/sample_app/lib/widgets/location/location_attachment.dart @@ -0,0 +1,235 @@ +import 'package:flutter/material.dart'; +import 'package:sample_app/widgets/location/location_user_marker.dart'; +import 'package:sample_app/widgets/simple_map_view.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +const _defaultLocationConstraints = BoxConstraints( + maxWidth: 270, + maxHeight: 180, +); + +/// {@template locationAttachmentBuilder} +/// A builder for creating a location attachment widget. +/// {@endtemplate} +class LocationAttachmentBuilder extends StreamAttachmentWidgetBuilder { + /// {@macro locationAttachmentBuilder} + const LocationAttachmentBuilder({ + this.constraints = _defaultLocationConstraints, + this.padding = const EdgeInsets.all(4), + this.onAttachmentTap, + }); + + /// The constraints to apply to the file attachment widget. + final BoxConstraints constraints; + + /// The padding to apply to the file attachment widget. + final EdgeInsetsGeometry padding; + + /// Optional callback to handle tap events on the attachment. + final ValueSetter? onAttachmentTap; + + @override + bool canHandle(Message message, _) => message.sharedLocation != null; + + @override + Widget build(BuildContext context, Message message, _) { + assert(debugAssertCanHandle(message, _), ''); + + final user = message.user; + final location = message.sharedLocation!; + return LocationAttachment( + user: user, + sharedLocation: location, + constraints: constraints, + padding: padding, + onLocationTap: switch (onAttachmentTap) { + final onTap? => () => onTap(location), + _ => null, + }, + ); + } +} + +/// Displays a location attachment with a map view and optional footer. +class LocationAttachment extends StatelessWidget { + /// Creates a new [LocationAttachment]. + const LocationAttachment({ + super.key, + required this.user, + required this.sharedLocation, + this.constraints = _defaultLocationConstraints, + this.padding = const EdgeInsets.all(2), + this.onLocationTap, + }); + + /// The user who shared the location. + final User? user; + + /// The shared location data. + final Location sharedLocation; + + /// The constraints to apply to the file attachment widget. + final BoxConstraints constraints; + + /// The padding to apply to the file attachment widget. + final EdgeInsetsGeometry padding; + + /// Optional callback to handle tap events on the location attachment. + final VoidCallback? onLocationTap; + + @override + Widget build(BuildContext context) { + final currentUser = StreamChat.of(context).currentUser; + final sharedLocationEndAt = sharedLocation.endAt; + + return Padding( + padding: padding, + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 270, maxHeight: 180), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Material( + clipBehavior: Clip.antiAlias, + type: MaterialType.transparency, + borderRadius: BorderRadius.circular(14), + child: InkWell( + onTap: onLocationTap, + child: IgnorePointer( + child: SimpleMapView( + markerSize: 40, + showLocateMeButton: false, + coordinates: sharedLocation.coordinates, + markerBuilder: (_, __, size) => LocationUserMarker( + user: user, + markerSize: size, + sharedLocation: sharedLocation, + ), + ), + ), + ), + ), + ), + if (sharedLocationEndAt != null && currentUser != null) + LocationAttachmentFooter( + currentUser: currentUser, + sharingEndAt: sharedLocationEndAt, + sharedLocation: sharedLocation, + onStopSharingPressed: () { + final client = StreamChat.of(context).client; + + final location = sharedLocation; + final messageId = location.messageId; + if (messageId == null) return; + + client.stopLiveLocation( + messageId: messageId, + createdByDeviceId: location.createdByDeviceId, + ); + }, + ), + ], + ), + ), + ); + } +} + +class LocationAttachmentFooter extends StatelessWidget { + const LocationAttachmentFooter({ + super.key, + required this.currentUser, + required this.sharingEndAt, + required this.sharedLocation, + this.onStopSharingPressed, + }); + + final User currentUser; + final DateTime sharingEndAt; + final Location sharedLocation; + final VoidCallback? onStopSharingPressed; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final textTheme = theme.textTheme; + final colorTheme = theme.colorTheme; + + const maximumSize = Size(double.infinity, 40); + + // If the location sharing has ended, show a message indicating that. + if (sharingEndAt.isBefore(DateTime.now())) { + return SizedBox.fromSize( + size: maximumSize, + child: Row( + spacing: 8, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.near_me_disabled_rounded, + color: colorTheme.textLowEmphasis, + ), + Text( + 'Live location ended', + style: textTheme.bodyBold.copyWith( + color: colorTheme.textLowEmphasis, + ), + ), + ], + ), + ); + } + + final currentUserId = currentUser.id; + final sharedLocationUserId = sharedLocation.userId; + + // If the shared location is not shared by the current user, show the + // "Live until" duration text. + if (sharedLocationUserId != currentUserId) { + final liveUntil = Jiffy.parseFromDateTime(sharingEndAt.toLocal()); + + return SizedBox.fromSize( + size: maximumSize, + child: Row( + spacing: 8, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.near_me_rounded, + color: colorTheme.accentPrimary, + ), + Text( + 'Live until ${liveUntil.jm}', + style: textTheme.bodyBold.copyWith( + color: colorTheme.accentPrimary, + ), + ), + ], + ), + ); + } + + // Otherwise, show the "Stop Sharing" button. + final buttonStyle = TextButton.styleFrom( + maximumSize: maximumSize, + textStyle: textTheme.bodyBold, + visualDensity: VisualDensity.compact, + foregroundColor: colorTheme.accentError, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + ); + + return TextButton.icon( + style: buttonStyle, + onPressed: onStopSharingPressed, + icon: Icon( + Icons.near_me_disabled_rounded, + color: colorTheme.accentError, + ), + label: const Text('Stop Sharing'), + ); + } +} diff --git a/sample_app/lib/widgets/location/location_detail_dialog.dart b/sample_app/lib/widgets/location/location_detail_dialog.dart new file mode 100644 index 0000000000..083a9ce2e5 --- /dev/null +++ b/sample_app/lib/widgets/location/location_detail_dialog.dart @@ -0,0 +1,319 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:sample_app/widgets/location/location_user_marker.dart'; +import 'package:sample_app/widgets/simple_map_view.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +/// {@template showStreamPollCommentsDialog} +/// Displays an interactive dialog to show all the comments for a poll. +/// +/// The comments are paginated and get's loaded as the user scrolls. +/// +/// The dialog also allows the user to update their comment. +/// {@endtemplate} +Future showLocationDetailDialog({ + required BuildContext context, + required Location location, +}) async { + final navigator = Navigator.of(context); + return navigator.push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (_) => StreamChannel( + channel: StreamChannel.of(context).channel, + child: LocationDetailDialog(sharedLocation: location), + ), + ), + ); +} + +Stream _findLocationMessageStream( + Channel channel, + Location location, +) { + final messageId = location.messageId; + if (messageId == null) return Stream.value(null); + + final channelState = channel.state; + if (channelState == null) return Stream.value(null); + + return channelState.messagesStream.map((messages) { + return messages.firstWhereOrNull((message) => message.id == messageId); + }); +} + +class LocationDetailDialog extends StatelessWidget { + const LocationDetailDialog({ + super.key, + required this.sharedLocation, + }); + + final Location sharedLocation; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final colorTheme = theme.colorTheme; + + final channel = StreamChannel.of(context).channel; + final locationStream = _findLocationMessageStream(channel, sharedLocation); + + return Scaffold( + backgroundColor: colorTheme.appBg, + appBar: AppBar( + backgroundColor: colorTheme.barsBg, + title: const Text('Shared Location'), + ), + body: BetterStreamBuilder( + stream: locationStream, + errorBuilder: (_, __) => const Center(child: LocationNotFound()), + noDataBuilder: (_) => const Center(child: CircularProgressIndicator()), + builder: (context, message) { + final sharedLocation = message.sharedLocation; + if (sharedLocation == null) { + return const Center(child: LocationNotFound()); + } + + return Stack( + alignment: AlignmentDirectional.bottomCenter, + children: [ + SimpleMapView( + cameraZoom: 16, + markerSize: 48, + coordinates: sharedLocation.coordinates, + markerBuilder: (_, __, size) => LocationUserMarker( + user: message.user, + markerSize: size, + sharedLocation: sharedLocation, + ), + ), + if (sharedLocation.isLive) + LocationDetailBottomSheet( + sharedLocation: sharedLocation, + onStopSharingPressed: () { + final client = StreamChat.of(context).client; + + final messageId = sharedLocation.messageId; + if (messageId == null) return; + + client.stopLiveLocation( + messageId: messageId, + createdByDeviceId: sharedLocation.createdByDeviceId, + ); + }, + ), + ], + ); + }, + ), + ); + } +} + +class LocationNotFound extends StatelessWidget { + const LocationNotFound({super.key}); + + @override + Widget build(BuildContext context) { + final chatThemeData = StreamChatTheme.of(context); + final colorTheme = chatThemeData.colorTheme; + final textTheme = chatThemeData.textTheme; + + return Column( + spacing: 8, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 48, + Icons.near_me_disabled_rounded, + color: colorTheme.accentError, + ), + Text( + 'Location not found', + style: textTheme.headline.copyWith( + color: colorTheme.textHighEmphasis, + ), + ), + Text( + 'The location you are looking for is not available.', + style: textTheme.body.copyWith( + color: colorTheme.textLowEmphasis, + ), + ), + ], + ); + } +} + +class LocationDetailBottomSheet extends StatelessWidget { + const LocationDetailBottomSheet({ + super.key, + required this.sharedLocation, + this.onStopSharingPressed, + }); + + final Location sharedLocation; + final VoidCallback? onStopSharingPressed; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final colorTheme = theme.colorTheme; + + return Material( + color: colorTheme.barsBg, + borderRadius: const BorderRadiusDirectional.only( + topEnd: Radius.circular(14), + topStart: Radius.circular(14), + ), + child: SafeArea( + minimum: const EdgeInsets.all(8), + child: LocationDetail( + sharedLocation: sharedLocation, + onStopSharingPressed: onStopSharingPressed, + ), + ), + ); + } +} + +class LocationDetail extends StatelessWidget { + const LocationDetail({ + super.key, + required this.sharedLocation, + this.onStopSharingPressed, + }); + + final Location sharedLocation; + final VoidCallback? onStopSharingPressed; + + @override + Widget build(BuildContext context) { + assert( + sharedLocation.isLive, + 'Footer should only be shown for live locations', + ); + + final theme = StreamChatTheme.of(context); + final textTheme = theme.textTheme; + final colorTheme = theme.colorTheme; + + final updatedAt = sharedLocation.updatedAt; + final sharingEndAt = sharedLocation.endAt!; + const maximumButtonSize = Size(double.infinity, 40); + + if (sharingEndAt.isBefore(DateTime.now())) { + final jiffyUpdatedAt = Jiffy.parseFromDateTime(updatedAt.toLocal()); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox.fromSize( + size: maximumButtonSize, + child: Row( + spacing: 8, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.near_me_disabled_rounded, + color: colorTheme.accentError, + ), + Text( + 'Live location ended', + style: textTheme.headlineBold.copyWith( + color: colorTheme.accentError, + ), + ), + ], + ), + ), + Text( + 'Location last updated at ${jiffyUpdatedAt.jm}', + style: textTheme.body.copyWith( + color: colorTheme.textLowEmphasis, + ), + ), + ], + ); + } + + final sharedLocationUserId = sharedLocation.userId; + final currentUserId = StreamChat.of(context).currentUser?.id; + + // If the shared location is not shared by the current user, show the + // "Live until" duration text. + if (sharedLocationUserId != currentUserId) { + final jiffySharingEndAt = Jiffy.parseFromDateTime(sharingEndAt.toLocal()); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox.fromSize( + size: maximumButtonSize, + child: Row( + spacing: 8, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.near_me_rounded, + color: colorTheme.accentPrimary, + ), + Text( + 'Live Location', + style: textTheme.headlineBold.copyWith( + color: colorTheme.accentPrimary, + ), + ), + ], + ), + ), + Text( + 'Live until ${jiffySharingEndAt.jm}', + style: textTheme.body.copyWith( + color: colorTheme.textLowEmphasis, + ), + ), + ], + ); + } + + // Otherwise, show the "Stop Sharing" button. + final buttonStyle = TextButton.styleFrom( + maximumSize: maximumButtonSize, + textStyle: textTheme.headlineBold, + visualDensity: VisualDensity.compact, + foregroundColor: colorTheme.accentError, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + ); + + final jiffySharingEndAt = Jiffy.parseFromDateTime(sharingEndAt.toLocal()); + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: TextButton.icon( + style: buttonStyle, + onPressed: onStopSharingPressed, + icon: Icon( + Icons.near_me_disabled_rounded, + color: colorTheme.accentError, + ), + label: const Text('Stop Sharing'), + ), + ), + Center( + child: Text( + 'Live until ${jiffySharingEndAt.jm}', + style: textTheme.body.copyWith( + color: colorTheme.textLowEmphasis, + ), + ), + ), + ], + ); + } +} diff --git a/sample_app/lib/widgets/location/location_picker_dialog.dart b/sample_app/lib/widgets/location/location_picker_dialog.dart new file mode 100644 index 0000000000..1abaaf9e1c --- /dev/null +++ b/sample_app/lib/widgets/location/location_picker_dialog.dart @@ -0,0 +1,362 @@ +import 'package:avatar_glow/avatar_glow.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:sample_app/utils/location_provider.dart'; +import 'package:sample_app/widgets/simple_map_view.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class LocationPickerResult { + const LocationPickerResult({ + this.endSharingAt, + required this.coordinates, + }); + + final DateTime? endSharingAt; + final LocationCoordinates coordinates; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + return other is LocationPickerResult && + runtimeType == other.runtimeType && + endSharingAt == other.endSharingAt && + coordinates == other.coordinates; + } + + @override + int get hashCode => endSharingAt.hashCode ^ coordinates.hashCode; +} + +Future showLocationPickerDialog({ + required BuildContext context, + bool barrierDismissible = true, + Color? barrierColor, + String? barrierLabel, + bool useSafeArea = true, + bool useRootNavigator = false, + RouteSettings? routeSettings, + Offset? anchorPoint, + EdgeInsets padding = const EdgeInsets.all(16), + TraversalEdgeBehavior? traversalEdgeBehavior, +}) { + final navigator = Navigator.of(context, rootNavigator: useRootNavigator); + return navigator.push( + MaterialPageRoute( + fullscreenDialog: true, + barrierDismissible: barrierDismissible, + builder: (context) => const LocationPickerDialog(), + ), + ); +} + +class LocationPickerDialog extends StatefulWidget { + const LocationPickerDialog({super.key}); + + @override + State createState() => _LocationPickerDialogState(); +} + +class _LocationPickerDialogState extends State { + LocationCoordinates? _currentLocation; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final colorTheme = theme.colorTheme; + + return Scaffold( + backgroundColor: colorTheme.appBg, + appBar: AppBar( + backgroundColor: colorTheme.barsBg, + title: const Text('Share Location'), + ), + body: Stack( + alignment: AlignmentDirectional.bottomCenter, + children: [ + FutureBuilder( + future: LocationProvider().getCurrentLocation(), + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return const Center( + child: CircularProgressIndicator.adaptive(), + ); + } + + final position = snapshot.data; + if (snapshot.hasError || position == null) { + return const Center(child: LocationNotFound()); + } + + final coordinates = _currentLocation = LocationCoordinates( + latitude: position.latitude, + longitude: position.longitude, + ); + + return SimpleMapView( + cameraZoom: 18, + markerSize: 24, + coordinates: coordinates, + markerBuilder: (context, _, size) => AvatarGlow( + glowColor: colorTheme.accentPrimary, + child: Material( + elevation: 2, + shape: CircleBorder( + side: BorderSide( + width: 4, + color: colorTheme.barsBg, + ), + ), + child: CircleAvatar( + radius: size / 2, + backgroundColor: colorTheme.accentPrimary, + ), + ), + ), + ); + }, + ), + // Location picker options + LocationPickerOptionList( + onOptionSelected: (option) { + final currentLocation = _currentLocation; + if (currentLocation == null) return Navigator.pop(context); + + final result = LocationPickerResult( + endSharingAt: switch (option) { + ShareStaticLocation() => null, + ShareLiveLocation() => option.endSharingAt, + }, + coordinates: currentLocation, + ); + + return Navigator.pop(context, result); + }, + ), + ], + ), + ); + } +} + +class LocationNotFound extends StatelessWidget { + const LocationNotFound({super.key}); + + @override + Widget build(BuildContext context) { + final chatThemeData = StreamChatTheme.of(context); + final colorTheme = chatThemeData.colorTheme; + final textTheme = chatThemeData.textTheme; + + return Column( + spacing: 8, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 48, + Icons.near_me_disabled_rounded, + color: colorTheme.accentError, + ), + Text( + 'Something went wrong', + style: textTheme.headline.copyWith( + color: colorTheme.textHighEmphasis, + ), + ), + Text( + 'Please check your location settings and try again.', + style: textTheme.body.copyWith( + color: colorTheme.textLowEmphasis, + ), + ), + ], + ); + } +} + +class LocationPickerOptionList extends StatelessWidget { + const LocationPickerOptionList({ + super.key, + required this.onOptionSelected, + }); + + final ValueSetter onOptionSelected; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final colorTheme = theme.colorTheme; + + return Material( + color: colorTheme.barsBg, + borderRadius: const BorderRadiusDirectional.only( + topEnd: Radius.circular(14), + topStart: Radius.circular(14), + ), + child: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 14, + horizontal: 14, + ), + child: Column( + spacing: 8, + mainAxisSize: MainAxisSize.min, + children: [ + LocationPickerOptionItem( + icon: const Icon(Icons.share_location_rounded), + title: 'Share Live Location', + subtitle: 'Your location will update in real-time', + onTap: () async { + final duration = await showCupertinoModalPopup( + context: context, + builder: (_) => const LiveLocationDurationDialog(), + ); + + if (duration == null) return; + final endSharingAt = DateTime.timestamp().add(duration); + + return onOptionSelected( + ShareLiveLocation(endSharingAt: endSharingAt), + ); + }, + ), + LocationPickerOptionItem( + icon: const Icon(Icons.my_location), + title: 'Share Static Location', + subtitle: 'Send your current location only', + onTap: () => onOptionSelected(const ShareStaticLocation()), + ), + ], + ), + ), + ), + ); + } +} + +sealed class LocationPickerOption { + const LocationPickerOption(); +} + +final class ShareLiveLocation extends LocationPickerOption { + const ShareLiveLocation({required this.endSharingAt}); + final DateTime endSharingAt; +} + +final class ShareStaticLocation extends LocationPickerOption { + const ShareStaticLocation(); +} + +class LocationPickerOptionItem extends StatelessWidget { + const LocationPickerOptionItem({ + super.key, + required this.icon, + required this.title, + required this.subtitle, + required this.onTap, + }); + + final Widget icon; + final String title; + final String subtitle; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final textTheme = theme.textTheme; + final colorTheme = theme.colorTheme; + + return OutlinedButton( + onPressed: onTap, + style: OutlinedButton.styleFrom( + backgroundColor: colorTheme.barsBg, + foregroundColor: colorTheme.accentPrimary, + side: BorderSide(color: colorTheme.borders, width: 1.2), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8), + ), + child: IconTheme( + data: IconTheme.of(context).copyWith( + size: 24, + color: colorTheme.accentPrimary, + ), + child: Row( + spacing: 16, + children: [ + icon, + Expanded( + child: Column( + spacing: 2, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: textTheme.bodyBold.copyWith( + color: colorTheme.textHighEmphasis, + ), + ), + Text( + subtitle, + style: textTheme.footnote.copyWith( + color: colorTheme.textLowEmphasis, + ), + ), + ], + ), + ), + StreamSvgIcon( + size: 24, + icon: StreamSvgIcons.right, + color: colorTheme.textLowEmphasis, + ), + ], + ), + ), + ); + } +} + +class LiveLocationDurationDialog extends StatelessWidget { + const LiveLocationDurationDialog({super.key}); + + static const _endAtDurations = [ + Duration(minutes: 15), + Duration(hours: 1), + Duration(hours: 8), + ]; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + + return CupertinoTheme( + data: CupertinoTheme.of(context).copyWith( + primaryColor: theme.colorTheme.accentPrimary, + ), + child: CupertinoActionSheet( + title: const Text('Share Live Location'), + message: Text( + 'Select the duration for sharing your live location.', + style: theme.textTheme.footnote.copyWith( + color: theme.colorTheme.textLowEmphasis, + ), + ), + actions: [ + ..._endAtDurations.map((duration) { + final endAt = Jiffy.now().addDuration(duration); + return CupertinoActionSheetAction( + onPressed: () => Navigator.of(context).pop(duration), + child: Text(endAt.fromNow(withPrefixAndSuffix: false)), + ); + }), + ], + cancelButton: CupertinoActionSheetAction( + isDestructiveAction: true, + onPressed: Navigator.of(context).pop, + child: const Text('Cancel'), + ), + ), + ); + } +} diff --git a/sample_app/lib/widgets/location/location_picker_option.dart b/sample_app/lib/widgets/location/location_picker_option.dart new file mode 100644 index 0000000000..bee6f97728 --- /dev/null +++ b/sample_app/lib/widgets/location/location_picker_option.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:sample_app/widgets/location/location_picker_dialog.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +final class LocationPickerType extends CustomAttachmentPickerType { + const LocationPickerType(); +} + +final class LocationPicked extends CustomAttachmentPickerResult { + const LocationPicked({required this.location}); + final LocationPickerResult location; +} + +class LocationPicker extends StatelessWidget { + const LocationPicker({ + super.key, + this.onLocationPicked, + }); + + final ValueSetter? onLocationPicked; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final colorTheme = theme.colorTheme; + + return OptionDrawer( + child: EndOfFrameCallbackWidget( + child: Icon( + size: 148, + Icons.near_me_rounded, + color: colorTheme.disabled, + ), + onEndOfFrame: (context) async { + final result = await runInPermissionRequestLock(() { + return showLocationPickerDialog(context: context); + }); + + onLocationPicked?.call(result); + }, + errorBuilder: (context, error, stacktrace) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + size: 148, + Icons.pin_drop_rounded, + color: theme.colorTheme.disabled, + ), + Text( + context.translations.enablePhotoAndVideoAccessMessage, + style: theme.textTheme.body.copyWith( + color: theme.colorTheme.textLowEmphasis, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 8), + TextButton( + onPressed: null, + child: Text( + context.translations.allowGalleryAccessMessage, + style: theme.textTheme.bodyBold.copyWith( + color: theme.colorTheme.accentPrimary, + ), + ), + ), + ], + ); + }, + ), + ); + } +} diff --git a/sample_app/lib/widgets/location/location_user_marker.dart b/sample_app/lib/widgets/location/location_user_marker.dart new file mode 100644 index 0000000000..102e16876c --- /dev/null +++ b/sample_app/lib/widgets/location/location_user_marker.dart @@ -0,0 +1,56 @@ +import 'package:avatar_glow/avatar_glow.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +class LocationUserMarker extends StatelessWidget { + const LocationUserMarker({ + super.key, + this.user, + this.markerSize = 40, + required this.sharedLocation, + }); + + final User? user; + final double markerSize; + final Location sharedLocation; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final colorTheme = theme.colorTheme; + + if (user case final user? when sharedLocation.isLive) { + const borderWidth = 4.0; + + final avatar = Material( + shape: const CircleBorder(), + clipBehavior: Clip.antiAlias, + color: colorTheme.overlayDark, + child: Padding( + padding: const EdgeInsets.all(borderWidth), + child: StreamUserAvatar( + user: user, + constraints: BoxConstraints.tightFor( + width: markerSize, + height: markerSize, + ), + showOnlineStatus: false, + ), + ), + ); + + if (sharedLocation.isExpired) return avatar; + + return AvatarGlow( + glowColor: colorTheme.accentPrimary, + child: avatar, + ); + } + + return Icon( + size: markerSize, + Icons.person_pin, + color: colorTheme.accentPrimary, + ); + } +} diff --git a/sample_app/lib/widgets/simple_map_view.dart b/sample_app/lib/widgets/simple_map_view.dart new file mode 100644 index 0000000000..0faadc11f7 --- /dev/null +++ b/sample_app/lib/widgets/simple_map_view.dart @@ -0,0 +1,153 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map_animations/flutter_map_animations.dart'; +import 'package:latlong2/latlong.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +typedef MarkerBuilder = Widget Function( + BuildContext context, + Animation animation, + double markerSize, +); + +class SimpleMapView extends StatefulWidget { + const SimpleMapView({ + super.key, + this.cameraZoom = 15, + this.markerSize = 30, + required this.coordinates, + this.showLocateMeButton = true, + this.markerBuilder = _defaultMarkerBuilder, + }); + + final double cameraZoom; + + final double markerSize; + + final LocationCoordinates coordinates; + + final bool showLocateMeButton; + + final MarkerBuilder markerBuilder; + static Widget _defaultMarkerBuilder(BuildContext context, _, double size) { + final theme = StreamChatTheme.of(context); + final iconColor = theme.colorTheme.accentPrimary; + return Icon(size: size, Icons.person_pin, color: iconColor); + } + + @override + State createState() => _SimpleMapViewState(); +} + +class _SimpleMapViewState extends State + with TickerProviderStateMixin { + late final _mapController = AnimatedMapController(vsync: this); + late final _initialCenter = widget.coordinates.toLatLng(); + + @override + void didUpdateWidget(covariant SimpleMapView oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.coordinates != widget.coordinates) { + _mapController.animateTo( + dest: widget.coordinates.toLatLng(), + zoom: widget.cameraZoom, + curve: Curves.easeInOut, + ); + } + } + + @override + Widget build(BuildContext context) { + final brightness = Theme.of(context).brightness; + const baseMapTemplate = 'https://{s}.basemaps.cartocdn.com'; + const mapTemplate = '$baseMapTemplate/rastertiles/voyager/{z}/{x}/{y}.png'; + const fallbackTemplate = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'; + + return FlutterMap( + mapController: _mapController.mapController, + options: MapOptions( + keepAlive: true, + initialCenter: _initialCenter, + initialZoom: widget.cameraZoom, + ), + children: [ + TileLayer( + urlTemplate: mapTemplate, + fallbackUrl: fallbackTemplate, + tileBuilder: (context, tile, __) => switch (brightness) { + Brightness.light => tile, + Brightness.dark => darkModeTilesContainerBuilder(context, tile), + }, + userAgentPackageName: switch (CurrentPlatform.type) { + PlatformType.ios => 'io.getstream.flutter', + PlatformType.android => 'io.getstream.chat.android.flutter.sample', + _ => 'unknown', + }, + ), + AnimatedMarkerLayer( + markers: [ + AnimatedMarker( + height: widget.markerSize, + width: widget.markerSize, + point: widget.coordinates.toLatLng(), + builder: (context, animation) => widget.markerBuilder( + context, + animation, + widget.markerSize, + ), + ), + ], + ), + if (widget.showLocateMeButton) + SimpleMapLocateMeButton( + onPressed: () => _mapController.animateTo( + zoom: widget.cameraZoom, + curve: Curves.easeInOut, + dest: widget.coordinates.toLatLng(), + ), + ), + ], + ); + } + + @override + void dispose() { + _mapController.dispose(); + super.dispose(); + } +} + +class SimpleMapLocateMeButton extends StatelessWidget { + const SimpleMapLocateMeButton({ + super.key, + this.onPressed, + this.alignment = AlignmentDirectional.topEnd, + }); + + final AlignmentGeometry alignment; + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + final theme = StreamChatTheme.of(context); + final colorTheme = theme.colorTheme; + + return Align( + alignment: alignment, + child: Padding( + padding: const EdgeInsets.all(8), + child: FloatingActionButton.small( + onPressed: onPressed, + shape: const CircleBorder(), + foregroundColor: colorTheme.accentPrimary, + backgroundColor: colorTheme.barsBg, + child: const Icon(Icons.near_me_rounded), + ), + ), + ); + } +} + +extension on LocationCoordinates { + LatLng toLatLng() => LatLng(latitude, longitude); +} diff --git a/sample_app/macos/Flutter/Flutter-Debug.xcconfig b/sample_app/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b2d2..0000000000 --- a/sample_app/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/sample_app/macos/Flutter/Flutter-Release.xcconfig b/sample_app/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d1579..0000000000 --- a/sample_app/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/sample_app/macos/Runner/DebugProfile.entitlements b/sample_app/macos/Runner/DebugProfile.entitlements index 0eaccf1418..6bc96b3bc4 100644 --- a/sample_app/macos/Runner/DebugProfile.entitlements +++ b/sample_app/macos/Runner/DebugProfile.entitlements @@ -12,5 +12,7 @@ com.apple.security.network.server + com.apple.security.personal-information.location + diff --git a/sample_app/macos/Runner/Info.plist b/sample_app/macos/Runner/Info.plist index 4789daa6a4..49bb9bb13c 100644 --- a/sample_app/macos/Runner/Info.plist +++ b/sample_app/macos/Runner/Info.plist @@ -28,5 +28,7 @@ MainMenu NSPrincipalClass NSApplication + NSLocationUsageDescription + We need access to your location to share it in the chat. diff --git a/sample_app/macos/Runner/Release.entitlements b/sample_app/macos/Runner/Release.entitlements index a0463869a9..731447a00b 100644 --- a/sample_app/macos/Runner/Release.entitlements +++ b/sample_app/macos/Runner/Release.entitlements @@ -8,5 +8,7 @@ com.apple.security.network.client + com.apple.security.personal-information.location + diff --git a/sample_app/pubspec.yaml b/sample_app/pubspec.yaml index 960ae43812..21b3a18e2d 100644 --- a/sample_app/pubspec.yaml +++ b/sample_app/pubspec.yaml @@ -20,6 +20,7 @@ environment: flutter: ">=3.27.4" dependencies: + avatar_glow: ^3.0.0 collection: ^1.17.2 firebase_core: ^3.0.0 firebase_messaging: ^15.0.0 @@ -27,12 +28,17 @@ dependencies: sdk: flutter flutter_app_badger: ^1.5.0 flutter_local_notifications: ^18.0.1 + flutter_map: ^8.1.1 + flutter_map_animations: ^0.9.0 flutter_secure_storage: ^9.2.2 flutter_slidable: ^3.1.1 flutter_svg: ^2.0.10+1 + geolocator: ^13.0.0 go_router: ^14.6.2 + latlong2: ^0.9.1 lottie: ^3.1.2 provider: ^6.0.5 + rxdart: ^0.28.0 sentry_flutter: ^8.3.0 stream_chat_flutter: ^10.0.0-beta.2 stream_chat_localizations: ^10.0.0-beta.2 From bf1cd728c3a14ee2058c94cd5ec78e10cb85d728 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 12:45:02 +0200 Subject: [PATCH 02/26] chore: minor improvements --- packages/stream_chat/lib/src/core/models/message.dart | 2 ++ packages/stream_chat/lib/src/core/models/message.g.dart | 2 -- sample_app/lib/pages/channel_page.dart | 4 +++- sample_app/lib/utils/app_config.dart | 2 +- sample_app/lib/widgets/location/location_attachment.dart | 2 +- .../lib/widgets/location/location_detail_dialog.dart | 7 ------- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/stream_chat/lib/src/core/models/message.dart b/packages/stream_chat/lib/src/core/models/message.dart index 8fcd00f872..d91be6eeba 100644 --- a/packages/stream_chat/lib/src/core/models/message.dart +++ b/packages/stream_chat/lib/src/core/models/message.dart @@ -315,12 +315,14 @@ class Message extends Equatable implements ComparableFieldProvider { /// Optional reminder for this message. /// /// This is present when a user has set a reminder for this message. + @JsonKey(includeToJson: false) final MessageReminder? reminder; /// Optional shared location associated with this message. /// /// This is used to share a location in a message, allowing users to view the /// location on a map. + @JsonKey(includeToJson: false) final Location? sharedLocation; /// Message custom extraData. diff --git a/packages/stream_chat/lib/src/core/models/message.g.dart b/packages/stream_chat/lib/src/core/models/message.g.dart index 1e108ac986..1a36d370af 100644 --- a/packages/stream_chat/lib/src/core/models/message.g.dart +++ b/packages/stream_chat/lib/src/core/models/message.g.dart @@ -115,7 +115,5 @@ Map _$MessageToJson(Message instance) => { 'poll_id': instance.pollId, if (instance.restrictedVisibility case final value?) 'restricted_visibility': value, - 'reminder': instance.reminder?.toJson(), - 'shared_location': instance.sharedLocation?.toJson(), 'extra_data': instance.extraData, }; diff --git a/sample_app/lib/pages/channel_page.dart b/sample_app/lib/pages/channel_page.dart index 71cb913aef..8681d48057 100644 --- a/sample_app/lib/pages/channel_page.dart +++ b/sample_app/lib/pages/channel_page.dart @@ -131,7 +131,9 @@ class _ChannelPageState extends State { enableVoiceRecording: true, allowedAttachmentPickerTypes: [ ...AttachmentPickerType.values, - if (channel.canShareLocation) const LocationPickerType(), + if (channel.config?.sharedLocations == true && + channel.canShareLocation) + const LocationPickerType(), ], onCustomAttachmentPickerResult: (result) { return _onCustomAttachmentPickerResult(channel, result).ignore(); diff --git a/sample_app/lib/utils/app_config.dart b/sample_app/lib/utils/app_config.dart index c99afeb7ec..b66a4328f8 100644 --- a/sample_app/lib/utils/app_config.dart +++ b/sample_app/lib/utils/app_config.dart @@ -3,7 +3,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; const sentryDsn = 'https://6381ef88de4140db8f5e25ab37e0f08c@o1213503.ingest.sentry.io/6352870'; -const kDefaultStreamApiKey = 'pd67s34fzpgw'; +const kDefaultStreamApiKey = 'kv7mcsxr24p8'; final defaultUsers = { 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibGVpYV9vcmdhbmEifQ.8NXs4DZrx_hljsaC8d6xlZ07FUgenKmb6hDNU-KFQ3M': diff --git a/sample_app/lib/widgets/location/location_attachment.dart b/sample_app/lib/widgets/location/location_attachment.dart index 9770e16419..405f97b7df 100644 --- a/sample_app/lib/widgets/location/location_attachment.dart +++ b/sample_app/lib/widgets/location/location_attachment.dart @@ -85,7 +85,7 @@ class LocationAttachment extends StatelessWidget { return Padding( padding: padding, child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 270, maxHeight: 180), + constraints: constraints, child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, diff --git a/sample_app/lib/widgets/location/location_detail_dialog.dart b/sample_app/lib/widgets/location/location_detail_dialog.dart index 083a9ce2e5..c5082bf365 100644 --- a/sample_app/lib/widgets/location/location_detail_dialog.dart +++ b/sample_app/lib/widgets/location/location_detail_dialog.dart @@ -4,13 +4,6 @@ import 'package:sample_app/widgets/location/location_user_marker.dart'; import 'package:sample_app/widgets/simple_map_view.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; -/// {@template showStreamPollCommentsDialog} -/// Displays an interactive dialog to show all the comments for a poll. -/// -/// The comments are paginated and get's loaded as the user scrolls. -/// -/// The dialog also allows the user to update their comment. -/// {@endtemplate} Future showLocationDetailDialog({ required BuildContext context, required Location location, From 7c53f16e478c3be2a8bbaeed9df9bcc39dfd1a04 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 12:46:01 +0200 Subject: [PATCH 03/26] chore: run formatter --- packages/stream_chat/lib/src/core/models/message.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat/lib/src/core/models/message.dart b/packages/stream_chat/lib/src/core/models/message.dart index d91be6eeba..bee0a3b9d1 100644 --- a/packages/stream_chat/lib/src/core/models/message.dart +++ b/packages/stream_chat/lib/src/core/models/message.dart @@ -632,7 +632,7 @@ class Message extends Equatable implements ComparableFieldProvider { draft, reminder, sharedLocation, - ]; + ]; @override ComparableField? getComparableField(String sortKey) { From b7c8550e3643d3adb1c7bb9135a4abc9d2e3ddd3 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 12:46:57 +0200 Subject: [PATCH 04/26] chore: minor improvement --- sample_app/lib/pages/channel_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sample_app/lib/pages/channel_page.dart b/sample_app/lib/pages/channel_page.dart index 8681d48057..0d3caf0b50 100644 --- a/sample_app/lib/pages/channel_page.dart +++ b/sample_app/lib/pages/channel_page.dart @@ -57,6 +57,7 @@ class _ChannelPageState extends State { final colorTheme = theme.colorTheme; final channel = StreamChannel.of(context).channel; + final config = channel.config; return Scaffold( backgroundColor: colorTheme.appBg, @@ -131,8 +132,7 @@ class _ChannelPageState extends State { enableVoiceRecording: true, allowedAttachmentPickerTypes: [ ...AttachmentPickerType.values, - if (channel.config?.sharedLocations == true && - channel.canShareLocation) + if (config?.sharedLocations == true && channel.canShareLocation) const LocationPickerType(), ], onCustomAttachmentPickerResult: (result) { From 0d29e177cddafb31a63c0513315e96a80429b262 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 13:08:31 +0200 Subject: [PATCH 05/26] chore: improve location attachment option --- sample_app/lib/utils/location_provider.dart | 6 ++++++ .../lib/widgets/location/location_picker_option.dart | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/sample_app/lib/utils/location_provider.dart b/sample_app/lib/utils/location_provider.dart index 5a572c99af..a50264bb2d 100644 --- a/sample_app/lib/utils/location_provider.dart +++ b/sample_app/lib/utils/location_provider.dart @@ -17,6 +17,12 @@ class LocationProvider { StreamSubscription? _positionSubscription; + /// Opens the device's location settings page. + /// + /// Returns [true] if the location settings page could be opened, otherwise + /// [false] is returned. + Future openLocationSettings() => Geolocator.openLocationSettings(); + /// Get current static location Future getCurrentLocation() async { final hasPermission = await _handlePermission(); diff --git a/sample_app/lib/widgets/location/location_picker_option.dart b/sample_app/lib/widgets/location/location_picker_option.dart index bee6f97728..e32ba43ee7 100644 --- a/sample_app/lib/widgets/location/location_picker_option.dart +++ b/sample_app/lib/widgets/location/location_picker_option.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:sample_app/utils/location_provider.dart'; import 'package:sample_app/widgets/location/location_picker_dialog.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; @@ -44,11 +45,11 @@ class LocationPicker extends StatelessWidget { children: [ Icon( size: 148, - Icons.pin_drop_rounded, + Icons.near_me_rounded, color: theme.colorTheme.disabled, ), Text( - context.translations.enablePhotoAndVideoAccessMessage, + 'Please enable access to your location', style: theme.textTheme.body.copyWith( color: theme.colorTheme.textLowEmphasis, ), @@ -56,9 +57,9 @@ class LocationPicker extends StatelessWidget { ), const SizedBox(height: 8), TextButton( - onPressed: null, + onPressed: LocationProvider().openLocationSettings, child: Text( - context.translations.allowGalleryAccessMessage, + 'Allow Location Access', style: theme.textTheme.bodyBold.copyWith( color: theme.colorTheme.accentPrimary, ), From 79bca6c39a8ea3f060d915a318c86538221cb79c Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 13:10:22 +0200 Subject: [PATCH 06/26] chore: apply review suggestion --- sample_app/lib/utils/location_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample_app/lib/utils/location_provider.dart b/sample_app/lib/utils/location_provider.dart index a50264bb2d..5b3950e518 100644 --- a/sample_app/lib/utils/location_provider.dart +++ b/sample_app/lib/utils/location_provider.dart @@ -82,7 +82,7 @@ class LocationProvider { /// Clean up resources void reset() { stopTracking(); - _positionStreamController.close(); + if (!_positionStreamController.isClosed) _positionStreamController.close(); } Future _handlePermission() async { From c1dd0eff2b94f2dcba3e9562271f6072ded14628 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 13:10:57 +0200 Subject: [PATCH 07/26] chore: remove dead code --- sample_app/lib/widgets/channel_list.dart | 108 ----------------------- 1 file changed, 108 deletions(-) diff --git a/sample_app/lib/widgets/channel_list.dart b/sample_app/lib/widgets/channel_list.dart index cdc130779c..a87e51b012 100644 --- a/sample_app/lib/widgets/channel_list.dart +++ b/sample_app/lib/widgets/channel_list.dart @@ -251,114 +251,6 @@ class _ChannelListDefault extends StatelessWidget { ), ); } - - // BuildContext context, - // List items, - // int index, - // WidgetType defaultWidget, - - // Widget _customChannelTileBuilder( - // BuildContext context, - // List channels, - // int index, - // StreamChannelListTile defaultWidget, - // ) { - // final chatTheme = StreamChatTheme.of(context); - // final channel = channels[index]; - // final backgroundColor = chatTheme.colorTheme.inputBg; - // final canDeleteChannel = channel.canDeleteChannel; - // - // final lastMessage = channel.state?.lastMessage; - // - // final channelSubtitle = - // - // final channelTile = ColoredBox( - // color: switch (channel.isPinned) { - // true => chatTheme.colorTheme.highlight, - // false => Colors.transparent, - // }, - // child: defaultWidget.copyWith( - // subtitle: ChannelListTileSubtitle( - // channel: channel, - // textStyle: channelPreviewTheme.subtitleStyle, - // ), - // ), - // ); - // - // return Slidable( - // groupTag: 'channels-actions', - // endActionPane: ActionPane( - // extentRatio: canDeleteChannel ? 0.40 : 0.20, - // motion: const BehindMotion(), - // children: [ - // CustomSlidableAction( - // backgroundColor: backgroundColor, - // onPressed: (_) { - // showChannelInfoModalBottomSheet( - // context: context, - // channel: channel, - // onViewInfoTap: () { - // Navigator.pop(context); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) { - // final isOneToOne = - // channel.memberCount == 2 && channel.isDistinct; - // return StreamChannel( - // channel: channel, - // child: isOneToOne - // ? ChatInfoScreen( - // messageTheme: chatTheme.ownMessageTheme, - // user: channel.state!.members - // .where((m) => - // m.userId != - // channel.client.state.currentUser!.id) - // .first - // .user, - // ) - // : GroupInfoScreen( - // messageTheme: chatTheme.ownMessageTheme, - // ), - // ); - // }, - // ), - // ); - // }, - // ); - // }, - // child: const Icon(Icons.more_horiz), - // ), - // if (canDeleteChannel) - // CustomSlidableAction( - // backgroundColor: backgroundColor, - // child: StreamSvgIcon( - // icon: StreamSvgIcons.delete, - // color: chatTheme.colorTheme.accentError, - // ), - // onPressed: (_) async { - // final res = await showConfirmationBottomSheet( - // context, - // title: 'Delete Conversation', - // question: - // 'Are you sure you want to delete this conversation?', - // okText: 'Delete', - // cancelText: 'Cancel', - // icon: StreamSvgIcon( - // icon: StreamSvgIcons.delete, - // color: chatTheme.colorTheme.accentError, - // ), - // ); - // if (res == true) { - // await channelListController.deleteChannel(channel); - // } - // }, - // ), - // ], - // ), - // child: channelTile, - // ); - // } } class _ChannelListSearch extends StatelessWidget { From c0faec48d692a0c76611e8dfb5de3fe2bd0cdbed Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 17:43:09 +0200 Subject: [PATCH 08/26] chore: add client.dart tests --- .../test/src/client/client_test.dart | 355 ++++++++++++++++++ 1 file changed, 355 insertions(+) diff --git a/packages/stream_chat/test/src/client/client_test.dart b/packages/stream_chat/test/src/client/client_test.dart index 2b10620968..af851fd8d8 100644 --- a/packages/stream_chat/test/src/client/client_test.dart +++ b/packages/stream_chat/test/src/client/client_test.dart @@ -2747,6 +2747,361 @@ void main() { verifyNoMoreInteractions(api.moderation); }); + test('`.getActiveLiveLocations`', () async { + final locations = [ + Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ), + Location( + latitude: 34.0522, + longitude: -118.2437, + createdByDeviceId: 'device-2', + endAt: DateTime.now().add(const Duration(hours: 2)), + ), + ]; + + when(() => api.user.getActiveLiveLocations()).thenAnswer( + (_) async => GetActiveLiveLocationsResponse() // + ..activeLiveLocations = locations, + ); + + // Initial state should be empty + expect(client.state.activeLiveLocations, isEmpty); + + final res = await client.getActiveLiveLocations(); + + expect(res, isNotNull); + expect(res.activeLiveLocations, hasLength(2)); + expect(res.activeLiveLocations, equals(locations)); + expect(client.state.activeLiveLocations, equals(locations)); + + verify(() => api.user.getActiveLiveLocations()).called(1); + verifyNoMoreInteractions(api.user); + }); + + test('`.updateLiveLocation`', () async { + const messageId = 'test-message-id'; + const createdByDeviceId = 'test-device-id'; + final endAt = DateTime.timestamp().add(const Duration(hours: 1)); + const location = LocationCoordinates( + latitude: 40.7128, + longitude: -74.0060, + ); + + final expectedLocation = Location( + latitude: location.latitude, + longitude: location.longitude, + createdByDeviceId: createdByDeviceId, + endAt: endAt, + ); + + when( + () => api.user.updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + location: location, + endAt: endAt, + ), + ).thenAnswer((_) async => expectedLocation); + + final res = await client.updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + location: location, + endAt: endAt, + ); + + expect(res, isNotNull); + expect(res, equals(expectedLocation)); + + verify( + () => api.user.updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + location: location, + endAt: endAt, + ), + ).called(1); + verifyNoMoreInteractions(api.user); + }); + + test('`.stopLiveLocation`', () async { + const messageId = 'test-message-id'; + const createdByDeviceId = 'test-device-id'; + + final expectedLocation = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: createdByDeviceId, + endAt: DateTime.now(), // Should be expired + ); + + when( + () => api.user.updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + endAt: any(named: 'endAt'), + ), + ).thenAnswer((_) async => expectedLocation); + + final res = await client.stopLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + ); + + expect(res, isNotNull); + expect(res, equals(expectedLocation)); + + verify( + () => api.user.updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + endAt: any(named: 'endAt'), + ), + ).called(1); + verifyNoMoreInteractions(api.user); + }); + + group('Live Location Event Handling', () { + test('should handle location.shared event', () async { + final location = Location( + channelCid: 'test-channel:123', + messageId: 'message-123', + userId: userId, + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final event = Event( + type: EventType.locationShared, + cid: 'test-channel:123', + message: Message( + id: 'message-123', + sharedLocation: location, + ), + ); + + // Initially empty + expect(client.state.activeLiveLocations, isEmpty); + + // Trigger the event + client.handleEvent(event); + + // Wait for the event to get processed + await Future.delayed(Duration.zero); + + // Should add location to active live locations + final activeLiveLocations = client.state.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations.first.messageId, equals('message-123')); + }); + + test('should handle location.updated event', () async { + final initialLocation = Location( + channelCid: 'test-channel:123', + messageId: 'message-123', + userId: userId, + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + // Set initial location + client.state.activeLiveLocations = [initialLocation]; + + final updatedLocation = Location( + channelCid: 'test-channel:123', + messageId: 'message-123', + userId: userId, + latitude: 40.7500, // Updated latitude + longitude: -74.1000, // Updated longitude + createdByDeviceId: 'device-1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final event = Event( + type: EventType.locationUpdated, + cid: 'test-channel:123', + message: Message( + id: 'message-123', + sharedLocation: updatedLocation, + ), + ); + + // Trigger the event + client.handleEvent(event); + + // Wait for the event to get processed + await Future.delayed(Duration.zero); + + // Should update the location + final activeLiveLocations = client.state.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations.first.latitude, equals(40.7500)); + expect(activeLiveLocations.first.longitude, equals(-74.1000)); + }); + + test('should handle location.expired event', () async { + final location = Location( + channelCid: 'test-channel:123', + messageId: 'message-123', + userId: userId, + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + // Set initial location + client.state.activeLiveLocations = [location]; + expect(client.state.activeLiveLocations, hasLength(1)); + + final expiredLocation = location.copyWith( + endAt: DateTime.now().subtract(const Duration(hours: 1)), + ); + + final event = Event( + type: EventType.locationExpired, + cid: 'test-channel:123', + message: Message( + id: 'message-123', + sharedLocation: expiredLocation, + ), + ); + + // Trigger the event + client.handleEvent(event); + + // Wait for the event to get processed + await Future.delayed(Duration.zero); + + // Should remove the location + expect(client.state.activeLiveLocations, isEmpty); + }); + + test('should ignore location events for other users', () async { + final location = Location( + channelCid: 'test-channel:123', + messageId: 'message-123', + userId: 'other-user', // Different user + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final event = Event( + type: EventType.locationShared, + cid: 'test-channel:123', + message: Message( + id: 'message-123', + sharedLocation: location, + ), + ); + + // Trigger the event + client.handleEvent(event); + + // Wait for the event to get processed + await Future.delayed(Duration.zero); + + // Should not add location from other user + expect(client.state.activeLiveLocations, isEmpty); + }); + + test('should ignore static location events', () async { + final staticLocation = Location( + channelCid: 'test-channel:123', + messageId: 'message-123', + userId: userId, + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-1', + // No endAt means it's static + ); + + final event = Event( + type: EventType.locationShared, + cid: 'test-channel:123', + message: Message( + id: 'message-123', + sharedLocation: staticLocation, + ), + ); + + // Trigger the event + client.handleEvent(event); + + // Wait for the event to get processed + await Future.delayed(Duration.zero); + + // Should not add static location + expect(client.state.activeLiveLocations, isEmpty); + }); + + test('should merge locations with same key', () async { + final location1 = Location( + channelCid: 'test-channel:123', + messageId: 'message-123', + userId: userId, + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final location2 = Location( + channelCid: 'test-channel:123', + messageId: 'message-456', + userId: userId, + latitude: 40.7500, + longitude: -74.1000, + createdByDeviceId: 'device-1', // Same device, should merge + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final event1 = Event( + type: EventType.locationShared, + cid: 'test-channel:123', + message: Message( + id: 'message-123', + sharedLocation: location1, + ), + ); + + final event2 = Event( + type: EventType.locationShared, + cid: 'test-channel:123', + message: Message( + id: 'message-456', + sharedLocation: location2, + ), + ); + + // Trigger first event + client.handleEvent(event1); + await Future.delayed(Duration.zero); + + final activeLiveLocations = client.state.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations.first.messageId, equals('message-123')); + + // Trigger second event - should merge/update + client.handleEvent(event2); + await Future.delayed(Duration.zero); + + final activeLiveLocations2 = client.state.activeLiveLocations; + expect(activeLiveLocations2, hasLength(1)); + expect(activeLiveLocations2.first.messageId, equals('message-456')); + }); + }); + test('`.markAllRead`', () async { when(() => api.channel.markAllRead()) .thenAnswer((_) async => EmptyResponse()); From bdd5b2a8a59af2e19adba05e95664911d1be5585 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 20:43:57 +0200 Subject: [PATCH 09/26] chore: add channel.dart tests --- .../stream_chat/lib/src/client/channel.dart | 147 +++-- .../lib/src/core/models/location.dart | 4 +- .../test/src/client/channel_test.dart | 589 ++++++++++++++++++ 3 files changed, 684 insertions(+), 56 deletions(-) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index c3aa702ee0..987eba539a 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1093,12 +1093,14 @@ class Channel { /// Optionally, provide a [messageText] and [extraData] to send along with /// the location. Future sendStaticLocation({ + String? id, String? messageText, required String createdByDeviceId, required LocationCoordinates location, Map extraData = const {}, }) { final message = Message( + id: id, text: messageText, extraData: extraData, ); @@ -1123,6 +1125,7 @@ class Channel { /// Optionally, provide a [messageText] and [extraData] to send along with /// the location. Future startLiveLocationSharing({ + String? id, String? messageText, required DateTime endSharingAt, required String createdByDeviceId, @@ -1130,6 +1133,7 @@ class Channel { Map extraData = const {}, }) { final message = Message( + id: id, text: messageText, extraData: extraData, ); @@ -3107,12 +3111,6 @@ class ChannelClientState { newMessages.add(message); } - // Handle updates to pinned messages. - final newPinnedMessages = _updatePinnedMessages(message); - - // Handle updates to the active live locations. - final newActiveLiveLocations = _updateActiveLiveLocations(message); - // Calculate the new last message at time. var lastMessageAt = _channelState.channel?.lastMessageAt; lastMessageAt ??= message.createdAt; @@ -3123,18 +3121,45 @@ class ChannelClientState { // Apply the updated lists to the channel state. _channelState = _channelState.copyWith( messages: newMessages.sorted(_sortByCreatedAt), - pinnedMessages: newPinnedMessages, - activeLiveLocations: newActiveLiveLocations, channel: _channelState.channel?.copyWith( lastMessageAt: lastMessageAt, ), ); } - // If the message is part of a thread, update thread information. + // If the message is part of a thread, update thread message. if (message.parentId case final parentId?) { - updateThreadInfo(parentId, [message]); + _updateThreadMessage(parentId, message); } + + // Handle updates to pinned messages. + final newPinnedMessages = _updatePinnedMessages(message); + + // Handle updates to the active live locations. + final newActiveLiveLocations = _updateActiveLiveLocations(message); + + // Update the channel state with the new pinned messages and + // active live locations. + _channelState = _channelState.copyWith( + pinnedMessages: newPinnedMessages, + activeLiveLocations: newActiveLiveLocations, + ); + } + + void _updateThreadMessage(String parentId, Message message) { + final existingThreadMessages = threads[parentId] ?? []; + final updatedThreadMessages = [ + ...existingThreadMessages.merge( + [message], + key: (it) => it.id, + update: (original, updated) => updated.syncWith(original), + ), + ]; + + _threads = { + ...threads, + parentId: updatedThreadMessages.sorted(_sortByCreatedAt) + }; } /// Cleans up all the stale error messages which requires no action. @@ -3206,53 +3231,66 @@ class ChannelClientState { void removeMessage(Message message) async { await _channel._client.chatPersistenceClient?.deleteMessageById(message.id); - final parentId = message.parentId; - // i.e. it's a thread message, Remove it - if (parentId != null) { - final newThreads = {...threads}; - // Early return in case the thread is not available - if (!newThreads.containsKey(parentId)) return; - - // Remove thread message shown in thread page. - newThreads.update( - parentId, - (messages) => [...messages.where((e) => e.id != message.id)], - ); - - _threads = newThreads; - - // Early return if the thread message is not shown in channel. - if (message.showInChannel == false) return; - } + if (message.parentId == null || message.showInChannel == true) { + // Remove regular message, thread message shown in channel + var updatedMessages = [...messages.where((e) => e.id != message.id)]; - // Remove regular message, thread message shown in channel - var updatedMessages = [...messages]..removeWhere((e) => e.id == message.id); + // Remove quoted message reference from every message if available. + updatedMessages = [ + ...updatedMessages.map((it) { + // Early return if the message doesn't have a quoted message. + if (it.quotedMessageId != message.id) return it; - // Remove quoted message reference from every message if available. - updatedMessages = [...updatedMessages].map((it) { - // Early return if the message doesn't have a quoted message. - if (it.quotedMessageId != message.id) return it; + // Setting it to null will remove the quoted message from the message. + return it.copyWith(quotedMessage: null, quotedMessageId: null); + }), + ]; - // Setting it to null will remove the quoted message from the message. - return it.copyWith( - quotedMessage: null, - quotedMessageId: null, + _channelState = _channelState.copyWith( + messages: updatedMessages.sorted(_sortByCreatedAt), ); - }).toList(); + } + + if (message.parentId case final parentId?) { + // If the message is a thread message, remove it from the threads. + _removeThreadMessage(message, parentId); + } // If the message is pinned, remove it from the pinned messages. - final updatedPinnedMessages = _updatePinnedMessages(message); + final updatedPinnedMessages = [ + ...pinnedMessages.where((it) => it.id != message.id), + ]; // If the message is a live location, update the active live locations. - final updatedActiveLiveLocations = _updateActiveLiveLocations(message); + final updatedActiveLiveLocations = [ + ...activeLiveLocations.where((it) => it.messageId != message.id), + ]; _channelState = _channelState.copyWith( - messages: updatedMessages.sorted(_sortByCreatedAt), pinnedMessages: updatedPinnedMessages, activeLiveLocations: updatedActiveLiveLocations, ); } + void _removeThreadMessage(Message message, String parentId) { + final existingThreadMessages = threads[parentId] ?? []; + final updatedThreadMessages = [ + ...existingThreadMessages.where((it) => it.id != message.id), + ]; + + // If there are no more messages in the thread, remove the thread entry. + if (updatedThreadMessages.isEmpty) { + _threads = {...threads}..remove(parentId); + return; + } + + // Otherwise, update the thread messages. + _threads = { + ...threads, + parentId: updatedThreadMessages.sorted(_sortByCreatedAt), + }; + } + /// Removes/Updates the [message] based on the [hardDelete] value. void deleteMessage(Message message, {bool hardDelete = false}) { if (hardDelete) return removeMessage(message); @@ -3543,6 +3581,7 @@ class ChannelClientState { read: newReads, draft: updatedState.draft, pinnedMessages: updatedState.pinnedMessages, + activeLiveLocations: updatedState.activeLiveLocations, ); } @@ -3582,19 +3621,19 @@ class ChannelClientState { /// Update threads with updated information about messages. void updateThreadInfo(String parentId, List messages) { - final newThreads = {...threads}..update( - parentId, - (original) => [ - ...original.merge( - messages, - key: (message) => message.id, - update: (original, updated) => updated.syncWith(original), - ), - ].sorted(_sortByCreatedAt), - ifAbsent: () => messages.sorted(_sortByCreatedAt), - ); + final existingThreadMessages = threads[parentId] ?? []; + final updatedThreadMessages = [ + ...existingThreadMessages.merge( + messages, + key: (it) => it.id, + update: (original, updated) => updated.syncWith(original), + ), + ]; - _threads = newThreads; + _threads = { + ...threads, + parentId: updatedThreadMessages.sorted(_sortByCreatedAt) + }; } Draft? _getThreadDraft(String parentId, List? messages) { diff --git a/packages/stream_chat/lib/src/core/models/location.dart b/packages/stream_chat/lib/src/core/models/location.dart index bfdd2aaa28..57085e9894 100644 --- a/packages/stream_chat/lib/src/core/models/location.dart +++ b/packages/stream_chat/lib/src/core/models/location.dart @@ -32,8 +32,8 @@ class Location extends Equatable { this.endAt, DateTime? createdAt, DateTime? updatedAt, - }) : createdAt = createdAt ?? DateTime.now(), - updatedAt = updatedAt ?? DateTime.now(); + }) : createdAt = createdAt ?? DateTime.timestamp(), + updatedAt = updatedAt ?? DateTime.timestamp(); /// Create a new instance from a json factory Location.fromJson(Map json) => diff --git a/packages/stream_chat/test/src/client/channel_test.dart b/packages/stream_chat/test/src/client/channel_test.dart index fb011ded70..4573a74cf8 100644 --- a/packages/stream_chat/test/src/client/channel_test.dart +++ b/packages/stream_chat/test/src/client/channel_test.dart @@ -462,6 +462,109 @@ void main() { }); }); + group('`.sendStaticLocation`', () { + const deviceId = 'test-device-id'; + const locationId = 'test-location-id'; + const coordinates = LocationCoordinates( + latitude: 40.7128, + longitude: -74.0060, + ); + + test('should create a static location and call sendMessage', () async { + when( + () => client.sendMessage(any(), channelId, channelType), + ).thenAnswer( + (_) async => SendMessageResponse() + ..message = Message( + id: locationId, + text: 'Location shared', + extraData: const {'custom': 'data'}, + sharedLocation: Location( + channelCid: channel.cid, + messageId: locationId, + userId: client.state.currentUser?.id, + latitude: coordinates.latitude, + longitude: coordinates.longitude, + createdByDeviceId: deviceId, + ), + ), + ); + + final response = await channel.sendStaticLocation( + id: locationId, + messageText: 'Location shared', + createdByDeviceId: deviceId, + location: coordinates, + extraData: {'custom': 'data'}, + ); + + expect(response, isNotNull); + expect(response.message.id, locationId); + expect(response.message.text, 'Location shared'); + expect(response.message.extraData['custom'], 'data'); + expect(response.message.sharedLocation, isNotNull); + + verify( + () => client.sendMessage(any(), channelId, channelType), + ).called(1); + }); + }); + + group('`.startLiveLocationSharing`', () { + const deviceId = 'test-device-id'; + const locationId = 'test-location-id'; + final endSharingAt = DateTime.now().add(const Duration(hours: 1)); + const coordinates = LocationCoordinates( + latitude: 40.7128, + longitude: -74.0060, + ); + + test( + 'should create message with live location and call sendMessage', + () async { + when( + () => client.sendMessage(any(), channelId, channelType), + ).thenAnswer( + (_) async => SendMessageResponse() + ..message = Message( + id: locationId, + text: 'Location shared', + extraData: const {'custom': 'data'}, + sharedLocation: Location( + channelCid: channel.cid, + messageId: locationId, + userId: client.state.currentUser?.id, + latitude: coordinates.latitude, + longitude: coordinates.longitude, + createdByDeviceId: deviceId, + endAt: endSharingAt, + ), + ), + ); + + final response = await channel.startLiveLocationSharing( + id: locationId, + messageText: 'Location shared', + createdByDeviceId: deviceId, + location: coordinates, + endSharingAt: endSharingAt, + extraData: {'custom': 'data'}, + ); + + expect(response, isNotNull); + expect(response.message.id, locationId); + expect(response.message.text, 'Location shared'); + expect(response.message.extraData['custom'], 'data'); + expect(response.message.sharedLocation, isNotNull); + expect(response.message.sharedLocation?.endAt, endSharingAt); + + verify( + () => client.sendMessage(any(), channelId, channelType), + ).called(1); + }, + ); + }); + group('`.createDraft`', () { final draftMessage = DraftMessage(text: 'Draft message text'); @@ -4815,6 +4918,486 @@ void main() { expect(updatedMessage?.reminder, isNull); }); }); + + group('Location events', () { + const channelId = 'test-channel-id'; + const channelType = 'test-channel-type'; + late Channel channel; + + setUp(() { + final channelState = _generateChannelState(channelId, channelType); + channel = Channel.fromState(client, channelState); + }); + + tearDown(() { + channel.dispose(); + }); + + test('should handle location.shared event', () async { + // Verify initial state + expect(channel.state?.activeLiveLocations, isEmpty); + + // Create live location + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final locationMessage = Message( + id: 'msg1', + text: 'Live location shared', + sharedLocation: liveLocation, + ); + + // Create location.shared event + final locationSharedEvent = Event( + cid: channel.cid, + type: EventType.locationShared, + message: locationMessage, + ); + + // Dispatch event + client.addEvent(locationSharedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Check if message was added + final messages = channel.state?.messages; + final message = messages?.firstWhere((m) => m.id == 'msg1'); + expect(message, isNotNull); + + // Check if active live location was updated + final activeLiveLocations = channel.state?.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations?.first.messageId, equals('msg1')); + }); + + test('should handle location.updated event', () async { + // Setup initial state with location message + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final locationMessage = Message( + id: 'msg1', + text: 'Live location shared', + sharedLocation: liveLocation, + ); + + // Add initial message + channel.state?.addNewMessage(locationMessage); + + // Create updated location + final updatedLocation = liveLocation.copyWith( + latitude: 40.7500, // Updated latitude + longitude: -74.1000, // Updated longitude + ); + + final updatedMessage = locationMessage.copyWith( + sharedLocation: updatedLocation, + ); + + // Create location.updated event + final locationUpdatedEvent = Event( + cid: channel.cid, + type: EventType.locationUpdated, + message: updatedMessage, + ); + + // Dispatch event + client.addEvent(locationUpdatedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Check if message was updated + final messages = channel.state?.messages; + final message = messages?.firstWhere((m) => m.id == 'msg1'); + expect(message?.sharedLocation?.latitude, equals(40.7500)); + expect(message?.sharedLocation?.longitude, equals(-74.1000)); + + // Check if active live location was updated + final activeLiveLocations = channel.state?.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations?.first.latitude, equals(40.7500)); + expect(activeLiveLocations?.first.longitude, equals(-74.1000)); + }); + + test('should handle location.expired event', () async { + // Setup initial state with location message + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final locationMessage = Message( + id: 'msg1', + text: 'Live location shared', + sharedLocation: liveLocation, + ); + + // Add initial message + channel.state?.addNewMessage(locationMessage); + expect(channel.state?.activeLiveLocations, hasLength(1)); + + // Create expired location + final expiredLocation = liveLocation.copyWith( + endAt: DateTime.now().subtract(const Duration(hours: 1)), + ); + + final expiredMessage = locationMessage.copyWith( + sharedLocation: expiredLocation, + ); + + // Create location.expired event + final locationExpiredEvent = Event( + cid: channel.cid, + type: EventType.locationExpired, + message: expiredMessage, + ); + + // Dispatch event + client.addEvent(locationExpiredEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Check if message was updated + final messages = channel.state?.messages; + final message = messages?.firstWhere((m) => m.id == 'msg1'); + expect(message?.sharedLocation?.isExpired, isTrue); + + // Check if active live location was removed + expect(channel.state?.activeLiveLocations, isEmpty); + }); + + test('should not add static location to active locations', () async { + final staticLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + // No endAt - static location + ); + + final staticMessage = Message( + id: 'msg1', + text: 'Static location shared', + sharedLocation: staticLocation, + ); + + // Create location.shared event + final locationSharedEvent = Event( + cid: channel.cid, + type: EventType.locationShared, + message: staticMessage, + ); + + // Dispatch event + client.addEvent(locationSharedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Check if message was added + final messages = channel.state?.messages; + final message = messages?.firstWhere((m) => m.id == 'msg1'); + expect(message?.sharedLocation, isNotNull); + + // Check if active live location was NOT updated (should remain empty) + expect(channel.state?.activeLiveLocations, isEmpty); + }); + + test( + 'should update active locations when location message is deleted', + () async { + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final locationMessage = Message( + id: 'msg1', + text: 'Live location shared', + sharedLocation: liveLocation, + ); + + // Verify initial state + channel.state?.addNewMessage(locationMessage); + expect(channel.state?.activeLiveLocations, hasLength(1)); + + final messageDeletedEvent = Event( + type: EventType.messageDeleted, + cid: channel.cid, + message: locationMessage.copyWith( + type: MessageType.deleted, + deletedAt: DateTime.timestamp(), + ), + ); + + // Dispatch event + client.addEvent(messageDeletedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Verify active locations are updated + expect(channel.state?.activeLiveLocations, isEmpty); + }, + ); + + test('should merge locations with same key', () async { + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final locationMessage = Message( + id: 'msg1', + text: 'Live location shared', + sharedLocation: liveLocation, + ); + + // Add initial location for setup + channel.state?.addNewMessage(locationMessage); + expect(channel.state?.activeLiveLocations, hasLength(1)); + + // Create new location with same user, channel, and device + final newLocation = Location( + channelCid: channel.cid, + userId: 'user1', // Same user + messageId: 'msg2', // Different message + latitude: 40.7500, + longitude: -74.1000, + createdByDeviceId: 'device1', // Same device + endAt: DateTime.now().add(const Duration(hours: 2)), + ); + + final newMessage = Message( + id: 'msg2', + text: 'Updated location', + sharedLocation: newLocation, + ); + + // Create location.shared event for the new message + final locationSharedEvent = Event( + cid: channel.cid, + type: EventType.locationShared, + message: newMessage, + ); + + // Dispatch event + client.addEvent(locationSharedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Should still have only one active location (merged) + final activeLiveLocations = channel.state?.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations?.first.messageId, equals('msg2')); + expect(activeLiveLocations?.first.latitude, equals(40.7500)); + }); + + test( + 'should handle multiple active locations from different devices', + () async { + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final locationMessage = Message( + id: 'msg1', + text: 'Live location shared', + sharedLocation: liveLocation, + ); + + // Add first location for setup + channel.state?.addNewMessage(locationMessage); + expect(channel.state?.activeLiveLocations, hasLength(1)); + + // Create location from different device + final location2 = Location( + channelCid: channel.cid, + userId: 'user1', // Same user + messageId: 'msg2', + latitude: 34.0522, + longitude: -118.2437, + createdByDeviceId: 'device2', // Different device + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final message2 = Message( + id: 'msg2', + text: 'Location from device 2', + sharedLocation: location2, + ); + + // Create location.shared event for the second message + final locationSharedEvent = Event( + cid: channel.cid, + type: EventType.locationShared, + message: message2, + ); + + // Dispatch event + client.addEvent(locationSharedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Should have two active locations + expect(channel.state?.activeLiveLocations, hasLength(2)); + }, + ); + + test('should handle location messages in threads', () async { + final parentMessage = Message( + id: 'parent1', + text: 'Thread parent', + ); + + // Add parent message first for setup + channel.state?.addNewMessage(parentMessage); + + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'thread-msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final threadLocationMessage = Message( + id: 'thread-msg1', + text: 'Live location in thread', + parentId: 'parent1', + sharedLocation: liveLocation, + ); + + // Create location.shared event for the thread message + final locationSharedEvent = Event( + cid: channel.cid, + type: EventType.locationShared, + message: threadLocationMessage, + ); + + // Dispatch event + client.addEvent(locationSharedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Check if thread message was added + final thread = channel.state?.threads['parent1']; + expect(thread, contains(threadLocationMessage)); + + // Check if location was added to active locations + final activeLiveLocations = channel.state?.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations?.first.messageId, equals('thread-msg1')); + }); + + test('should update thread location messages', () async { + final parentMessage = Message( + id: 'parent1', + text: 'Thread parent', + ); + + final liveLocation = Location( + channelCid: channel.cid, + userId: 'user1', + messageId: 'thread-msg1', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device1', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final threadLocationMessage = Message( + id: 'thread-msg1', + text: 'Live location in thread', + parentId: 'parent1', + sharedLocation: liveLocation, + ); + + // Add messages + channel.state?.addNewMessage(parentMessage); + channel.state?.addNewMessage(threadLocationMessage); + + // Update the location + final updatedLocation = liveLocation.copyWith( + latitude: 40.7500, + longitude: -74.1000, + ); + + final updatedThreadMessage = threadLocationMessage.copyWith( + sharedLocation: updatedLocation, + ); + + // Create location.updated event for the thread message + final locationUpdatedEvent = Event( + cid: channel.cid, + type: EventType.locationUpdated, + message: updatedThreadMessage, + ); + + // Dispatch event + client.addEvent(locationUpdatedEvent); + + // Wait for the event to be processed + await Future.delayed(Duration.zero); + + // Check if thread message was updated + final thread = channel.state?.threads['parent1']; + final threadMessage = thread?.firstWhere((m) => m.id == 'thread-msg1'); + expect(threadMessage?.sharedLocation?.latitude, equals(40.7500)); + expect(threadMessage?.sharedLocation?.longitude, equals(-74.1000)); + + // Check if active location was updated + final activeLiveLocations = channel.state?.activeLiveLocations; + expect(activeLiveLocations, hasLength(1)); + expect(activeLiveLocations?.first.latitude, equals(40.7500)); + expect(activeLiveLocations?.first.longitude, equals(-74.1000)); + }); + }); }); group('ChannelCapabilityCheck', () { @@ -5077,6 +5660,12 @@ void main() { (channel) => channel.canQueryPollVotes, ); + testCapability( + 'ShareLocation', + ChannelCapability.shareLocation, + (channel) => channel.canShareLocation, + ); + test('returns correct values with multiple capabilities', () { final channelState = _generateChannelState( channelId, From 0de479efccb83dc890abc114cb7b9583843d925c Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 20:52:03 +0200 Subject: [PATCH 10/26] test: fix failing tests --- .../test/fixtures/channel_state_to_json.json | 101 +++++------------- .../test/fixtures/message_to_json.json | 2 - .../src/core/models/channel_state_test.dart | 1 + 3 files changed, 27 insertions(+), 77 deletions(-) diff --git a/packages/stream_chat/test/fixtures/channel_state_to_json.json b/packages/stream_chat/test/fixtures/channel_state_to_json.json index 9eec788ae6..662cf61908 100644 --- a/packages/stream_chat/test/fixtures/channel_state_to_json.json +++ b/packages/stream_chat/test/fixtures/channel_state_to_json.json @@ -29,9 +29,7 @@ "poll_id": null, "restricted_visibility": [ "user-id-3" - ], - "draft": null, - "reminder": null + ] }, { "id": "dry-meadow-0-e8e74482-b4cd-48db-9d1e-30e6c191786f", @@ -46,9 +44,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0", @@ -63,9 +59,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "dry-meadow-0-80925be0-786e-40a5-b225-486518dafd35", @@ -80,9 +74,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe", @@ -97,9 +89,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "withered-cell-0-84cbd760-cf55-4f7e-9207-c5f66cccc6dc", @@ -114,9 +104,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "dry-meadow-0-e9203588-43c3-40b1-91f7-f217fc42aa53", @@ -131,9 +119,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "withered-cell-0-7e3552d7-7a0d-45f2-a856-e91b23a7e240", @@ -148,9 +134,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "dry-meadow-0-1ffeafd4-e4fc-4c84-9394-9d7cb10fff42", @@ -165,9 +149,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "dry-meadow-0-3f147324-12c8-4b41-9fb5-2db88d065efa", @@ -182,9 +164,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "dry-meadow-0-51a348ae-0c0a-44de-a556-eac7891c0cf0", @@ -199,9 +179,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "icy-recipe-7-a29e237b-8d81-4a97-9bc8-d42bca3f1356", @@ -216,9 +194,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055", @@ -233,9 +209,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "throbbing-boat-5-1e4d5730-5ff0-4d25-9948-9f34ffda43e4", @@ -250,9 +224,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21", @@ -267,9 +239,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "snowy-credit-3-3319537e-2d0e-4876-8170-a54f046e4b7d", @@ -284,9 +254,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d", @@ -301,9 +269,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "snowy-credit-3-cebe25a7-a3a3-49fc-9919-91c6725e81f3", @@ -318,9 +284,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "divine-glade-9-0cea9262-5766-48e9-8b22-311870aed3bf", @@ -335,9 +299,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "red-firefly-9-c4e9007b-bb7d-4238-ae08-5f8e3cd03d73", @@ -352,9 +314,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "bitter-glade-2-02aee4eb-4093-4736-808b-2de75820e854", @@ -369,9 +329,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "morning-sea-1-0c700bcb-46dd-4224-b590-e77bdbccc480", @@ -386,9 +344,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "ancient-salad-0-53e8b4e6-5b7b-43ad-aeee-8bfb6a9ed0be", @@ -403,9 +359,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "ancient-salad-0-8c225075-bd4c-42e2-8024-530aae13cd40", @@ -420,9 +374,7 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null }, { "id": "proud-sea-7-17802096-cbf8-4e3c-addd-4ee31f4c8b5c", @@ -437,12 +389,11 @@ "silent": false, "pinned": false, "pin_expires": null, - "poll_id": null, - "draft": null, - "reminder": null + "poll_id": null } ], "pinned_messages": [], "members": [], + "active_live_locations": [], "watcher_count": 5 } diff --git a/packages/stream_chat/test/fixtures/message_to_json.json b/packages/stream_chat/test/fixtures/message_to_json.json index 8803f1ed1d..c4568628d3 100644 --- a/packages/stream_chat/test/fixtures/message_to_json.json +++ b/packages/stream_chat/test/fixtures/message_to_json.json @@ -26,7 +26,5 @@ "restricted_visibility": [ "user-id-3" ], - "draft": null, - "reminder": null, "hey": "test" } \ No newline at end of file diff --git a/packages/stream_chat/test/src/core/models/channel_state_test.dart b/packages/stream_chat/test/src/core/models/channel_state_test.dart index 6a436f1dcf..2d20cc8760 100644 --- a/packages/stream_chat/test/src/core/models/channel_state_test.dart +++ b/packages/stream_chat/test/src/core/models/channel_state_test.dart @@ -59,6 +59,7 @@ void main() { watcherCount: 5, pinnedMessages: [], watchers: [], + activeLiveLocations: [], ); expect( From 3eb8ada20fd49e7a32b8077bc96603c4c96203bd Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 21:00:37 +0200 Subject: [PATCH 11/26] chore: add user_api_test.dart --- .../test/src/core/api/user_api_test.dart | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/packages/stream_chat/test/src/core/api/user_api_test.dart b/packages/stream_chat/test/src/core/api/user_api_test.dart index 75b392ebf9..99b724b693 100644 --- a/packages/stream_chat/test/src/core/api/user_api_test.dart +++ b/packages/stream_chat/test/src/core/api/user_api_test.dart @@ -182,4 +182,80 @@ void main() { verify(() => client.get(path)).called(1); verifyNoMoreInteractions(client); }); + + test('getActiveLiveLocations', () async { + const path = '/users/live_locations'; + + when(() => client.get(path)).thenAnswer( + (_) async => successResponse( + path, + data: {'active_live_locations': []}, + ), + ); + + final res = await userApi.getActiveLiveLocations(); + + expect(res, isNotNull); + + verify(() => client.get(path)).called(1); + verifyNoMoreInteractions(client); + }); + + test('updateLiveLocation', () async { + const path = '/users/live_locations'; + const messageId = 'test-message-id'; + const createdByDeviceId = 'test-device-id'; + final endAt = DateTime.timestamp().add(const Duration(hours: 1)); + const coordinates = LocationCoordinates( + latitude: 40.7128, + longitude: -74.0060, + ); + + when( + () => client.put( + path, + data: json.encode({ + 'message_id': messageId, + 'created_by_device_id': createdByDeviceId, + 'latitude': coordinates.latitude, + 'longitude': coordinates.longitude, + 'end_at': endAt.toIso8601String(), + }), + ), + ).thenAnswer( + (_) async => successResponse( + path, + data: { + 'message_id': messageId, + 'created_by_device_id': createdByDeviceId, + 'latitude': coordinates.latitude, + 'longitude': coordinates.longitude, + 'end_at': endAt.toIso8601String(), + }, + ), + ); + + final res = await userApi.updateLiveLocation( + messageId: messageId, + createdByDeviceId: createdByDeviceId, + location: coordinates, + endAt: endAt, + ); + + expect(res, isNotNull); + + verify( + () => client.put( + path, + data: json.encode({ + 'message_id': messageId, + 'created_by_device_id': createdByDeviceId, + 'latitude': coordinates.latitude, + 'longitude': coordinates.longitude, + 'end_at': endAt.toIso8601String(), + }), + ), + ).called(1); + verifyNoMoreInteractions(client); + }); } From 9690aa7299d9b5e90b651c300835ff1e9f8c4592 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 21:11:23 +0200 Subject: [PATCH 12/26] chore: update CHANGELOG.md --- packages/stream_chat/CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index b388c37cdc..48d6b13264 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,3 +1,14 @@ +## Upcoming Beta + +✅ Added + +- Added comprehensive location sharing support with static and live location features: + - `Channel.sendStaticLocation()` - Send a static location message to the channel + - `Channel.startLiveLocationSharing()` - Start sharing live location with automatic updates + - `Channel.activeLiveLocations` - Track members active live location shares in the channel + - `Client.activeLiveLocations` - Access current user active live location shares across channels + - Location event listeners for `locationShared`, `locationUpdated`, and `locationExpired` events + ## Upcoming 🐞 Fixed From 192cc35e45fc2106cee92d4b2192f36e979bb8df Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 14 Jul 2025 21:34:34 +0200 Subject: [PATCH 13/26] chore: add event_resolvers and event_controller test --- .../test/src/client/event_resolvers_test.dart | 669 ++++++++++++++++++ .../src/core/util/event_controller_test.dart | 337 +++++++++ 2 files changed, 1006 insertions(+) create mode 100644 packages/stream_chat/test/src/client/event_resolvers_test.dart create mode 100644 packages/stream_chat/test/src/core/util/event_controller_test.dart diff --git a/packages/stream_chat/test/src/client/event_resolvers_test.dart b/packages/stream_chat/test/src/client/event_resolvers_test.dart new file mode 100644 index 0000000000..521aa3160e --- /dev/null +++ b/packages/stream_chat/test/src/client/event_resolvers_test.dart @@ -0,0 +1,669 @@ +// ignore_for_file: avoid_redundant_argument_values + +import 'package:stream_chat/src/client/event_resolvers.dart'; +import 'package:stream_chat/src/core/models/event.dart'; +import 'package:stream_chat/src/core/models/location.dart'; +import 'package:stream_chat/src/core/models/message.dart'; +import 'package:stream_chat/src/core/models/poll.dart'; +import 'package:stream_chat/src/core/models/poll_option.dart'; +import 'package:stream_chat/src/core/models/poll_vote.dart'; +import 'package:stream_chat/src/core/models/user.dart'; +import 'package:stream_chat/src/event_type.dart'; +import 'package:test/test.dart'; + +void main() { + group('Poll resolver events', () { + group('pollCreatedResolver', () { + test('should resolve messageNew event with poll to pollCreated', () { + final poll = Poll( + id: 'poll-123', + name: 'Test Poll', + options: const [ + PollOption(id: 'option-1', text: 'Option 1'), + PollOption(id: 'option-2', text: 'Option 2'), + ], + ); + + final event = Event( + type: EventType.messageNew, + poll: poll, + cid: 'channel-123', + ); + + final resolved = pollCreatedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.pollCreated); + expect(resolved.poll, equals(poll)); + expect(resolved.cid, equals('channel-123')); + }); + + test( + 'should resolve notificationMessageNew event with poll to pollCreated', + () { + final poll = Poll( + id: 'poll-123', + name: 'Test Poll', + options: const [ + PollOption(id: 'option-1', text: 'Option 1'), + ], + ); + + final event = Event( + type: EventType.notificationMessageNew, + poll: poll, + cid: 'channel-123', + ); + + final resolved = pollCreatedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.pollCreated); + expect(resolved.poll, equals(poll)); + }, + ); + + test('should return null for messageNew event without poll', () { + final event = Event( + type: EventType.messageNew, + cid: 'channel-123', + ); + + final resolved = pollCreatedResolver(event); + + expect(resolved, isNull); + }); + + test('should return null for invalid event types', () { + final poll = Poll( + id: 'poll-123', + name: 'Test Poll', + options: const [ + PollOption(id: 'option-1', text: 'Option 1'), + ], + ); + + final event = Event( + type: EventType.messageUpdated, + poll: poll, + cid: 'channel-123', + ); + + final resolved = pollCreatedResolver(event); + + expect(resolved, isNull); + }); + + test('should return null for event with null poll', () { + final event = Event( + type: EventType.messageNew, + poll: null, + cid: 'channel-123', + ); + + final resolved = pollCreatedResolver(event); + + expect(resolved, isNull); + }); + }); + + group('pollAnswerCastedResolver', () { + test( + 'should resolve pollVoteCasted event with answer to pollAnswerCasted', + () { + final pollVote = PollVote( + id: 'vote-123', + answerText: 'My answer', + pollId: 'poll-123', + ); + + final event = Event( + type: EventType.pollVoteCasted, + pollVote: pollVote, + cid: 'channel-123', + ); + + final resolved = pollAnswerCastedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.pollAnswerCasted); + expect(resolved.pollVote, equals(pollVote)); + expect(resolved.cid, equals('channel-123')); + }, + ); + + test( + 'should resolve pollVoteChanged event with answer to pollAnswerCasted', + () { + final pollVote = PollVote( + id: 'vote-123', + answerText: 'My updated answer', + pollId: 'poll-123', + ); + + final event = Event( + type: EventType.pollVoteChanged, + pollVote: pollVote, + cid: 'channel-123', + ); + + final resolved = pollAnswerCastedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.pollAnswerCasted); + expect(resolved.pollVote, equals(pollVote)); + }, + ); + + test('should return null for pollVoteCasted event with option vote', () { + final pollVote = PollVote( + id: 'vote-123', + optionId: 'option-1', + pollId: 'poll-123', + ); + + final event = Event( + type: EventType.pollVoteCasted, + pollVote: pollVote, + cid: 'channel-123', + ); + + final resolved = pollAnswerCastedResolver(event); + + expect(resolved, isNull); + }); + + test('should return null for invalid event types', () { + final pollVote = PollVote( + id: 'vote-123', + answerText: 'My answer', + pollId: 'poll-123', + ); + + final event = Event( + type: EventType.pollVoteRemoved, + pollVote: pollVote, + cid: 'channel-123', + ); + + final resolved = pollAnswerCastedResolver(event); + + expect(resolved, isNull); + }); + + test('should return resolved event for event with null pollVote', () { + final event = Event( + type: EventType.pollVoteCasted, + pollVote: null, + cid: 'channel-123', + ); + + final resolved = pollAnswerCastedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.pollAnswerCasted); + expect(resolved.pollVote, isNull); + }); + }); + + group('pollAnswerRemovedResolver', () { + test( + 'should resolve pollVoteRemoved event with answer to pollAnswerRemoved', + () { + final pollVote = PollVote( + id: 'vote-123', + answerText: 'My answer', + pollId: 'poll-123', + ); + + final event = Event( + type: EventType.pollVoteRemoved, + pollVote: pollVote, + cid: 'channel-123', + ); + + final resolved = pollAnswerRemovedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.pollAnswerRemoved); + expect(resolved.pollVote, equals(pollVote)); + expect(resolved.cid, equals('channel-123')); + }, + ); + + test('should return null for pollVoteRemoved event with option vote', () { + final pollVote = PollVote( + id: 'vote-123', + optionId: 'option-1', + pollId: 'poll-123', + ); + + final event = Event( + type: EventType.pollVoteRemoved, + pollVote: pollVote, + cid: 'channel-123', + ); + + final resolved = pollAnswerRemovedResolver(event); + + expect(resolved, isNull); + }); + + test('should return null for invalid event types', () { + final pollVote = PollVote( + id: 'vote-123', + answerText: 'My answer', + pollId: 'poll-123', + ); + + final event = Event( + type: EventType.pollVoteCasted, + pollVote: pollVote, + cid: 'channel-123', + ); + + final resolved = pollAnswerRemovedResolver(event); + + expect(resolved, isNull); + }); + + test('should return resolved event for event with null pollVote', () { + final event = Event( + type: EventType.pollVoteRemoved, + pollVote: null, + cid: 'channel-123', + ); + + final resolved = pollAnswerRemovedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.pollAnswerRemoved); + expect(resolved.pollVote, isNull); + }); + }); + }); + + group('Location resolver events', () { + group('locationSharedResolver', () { + test( + 'should resolve messageNew event with sharedLocation to locationShared', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + ); + + final message = Message( + id: 'message-123', + text: 'Check out this location', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageNew, + message: message, + cid: 'channel-123', + ); + + final resolved = locationSharedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.locationShared); + expect(resolved.message, equals(message)); + expect(resolved.cid, equals('channel-123')); + }, + ); + + test( + 'should resolve notificationMessageNew event with sharedLocation to locationShared', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + ); + + final message = Message( + id: 'message-123', + text: 'Check out this location', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.notificationMessageNew, + message: message, + cid: 'channel-123', + ); + + final resolved = locationSharedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.locationShared); + expect(resolved.message, equals(message)); + }, + ); + + test( + 'should return null for messageNew event without sharedLocation', + () { + final message = Message( + id: 'message-123', + text: 'Just a regular message', + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageNew, + message: message, + cid: 'channel-123', + ); + + final resolved = locationSharedResolver(event); + + expect(resolved, isNull); + }, + ); + + test('should return null for invalid event types', () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + ); + + final message = Message( + id: 'message-123', + text: 'Check out this location', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageUpdated, + message: message, + cid: 'channel-123', + ); + + final resolved = locationSharedResolver(event); + + expect(resolved, isNull); + }); + + test('should return null for event with null message', () { + final event = Event( + type: EventType.messageNew, + message: null, + cid: 'channel-123', + ); + + final resolved = locationSharedResolver(event); + + expect(resolved, isNull); + }); + }); + + group('locationUpdatedResolver', () { + test( + 'should resolve messageUpdated event with active live location to locationUpdated', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final message = Message( + id: 'message-123', + text: 'Live location sharing', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageUpdated, + message: message, + cid: 'channel-123', + ); + + final resolved = locationUpdatedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.locationUpdated); + expect(resolved.message, equals(message)); + expect(resolved.cid, equals('channel-123')); + }, + ); + + test( + 'should resolve messageUpdated event with static location to locationUpdated', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + // No endAt means static location + ); + + final message = Message( + id: 'message-123', + text: 'Static location sharing', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageUpdated, + message: message, + cid: 'channel-123', + ); + + final resolved = locationUpdatedResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.locationUpdated); + expect(resolved.message, equals(message)); + }, + ); + + test( + 'should return null for messageUpdated event with expired live location', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + endAt: DateTime.now().subtract(const Duration(hours: 1)), + ); + + final message = Message( + id: 'message-123', + text: 'Expired location sharing', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageUpdated, + message: message, + cid: 'channel-123', + ); + + final resolved = locationUpdatedResolver(event); + + expect(resolved, isNull); + }, + ); + + test('should return null for invalid event types', () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + ); + + final message = Message( + id: 'message-123', + text: 'Check out this location', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageNew, + message: message, + cid: 'channel-123', + ); + + final resolved = locationUpdatedResolver(event); + + expect(resolved, isNull); + }); + + test('should return null for event with null message', () { + final event = Event( + type: EventType.messageUpdated, + message: null, + cid: 'channel-123', + ); + + final resolved = locationUpdatedResolver(event); + + expect(resolved, isNull); + }); + }); + + group('locationExpiredResolver', () { + test( + 'should resolve messageUpdated event with expired live location to locationExpired', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + endAt: DateTime.now().subtract(const Duration(hours: 1)), + ); + + final message = Message( + id: 'message-123', + text: 'Expired location sharing', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageUpdated, + message: message, + cid: 'channel-123', + ); + + final resolved = locationExpiredResolver(event); + + expect(resolved, isNotNull); + expect(resolved!.type, EventType.locationExpired); + expect(resolved.message, equals(message)); + expect(resolved.cid, equals('channel-123')); + }, + ); + + test( + 'should return null for messageUpdated event with active live location', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + endAt: DateTime.now().add(const Duration(hours: 1)), + ); + + final message = Message( + id: 'message-123', + text: 'Active location sharing', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageUpdated, + message: message, + cid: 'channel-123', + ); + + final resolved = locationExpiredResolver(event); + + expect(resolved, isNull); + }, + ); + + test( + 'should return null for messageUpdated event with static location', + () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + // No endAt means static location + ); + + final message = Message( + id: 'message-123', + text: 'Static location sharing', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageUpdated, + message: message, + cid: 'channel-123', + ); + + final resolved = locationExpiredResolver(event); + + expect(resolved, isNull); + }, + ); + + test('should return null for invalid event types', () { + final location = Location( + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'device-123', + endAt: DateTime.now().subtract(const Duration(hours: 1)), + ); + + final message = Message( + id: 'message-123', + text: 'Expired location sharing', + sharedLocation: location, + user: User(id: 'user-123'), + ); + + final event = Event( + type: EventType.messageNew, + message: message, + cid: 'channel-123', + ); + + final resolved = locationExpiredResolver(event); + + expect(resolved, isNull); + }); + + test('should return null for event with null message', () { + final event = Event( + type: EventType.messageUpdated, + message: null, + cid: 'channel-123', + ); + + final resolved = locationExpiredResolver(event); + + expect(resolved, isNull); + }); + }); + }); +} diff --git a/packages/stream_chat/test/src/core/util/event_controller_test.dart b/packages/stream_chat/test/src/core/util/event_controller_test.dart new file mode 100644 index 0000000000..6b01dfffbf --- /dev/null +++ b/packages/stream_chat/test/src/core/util/event_controller_test.dart @@ -0,0 +1,337 @@ +// ignore_for_file: cascade_invocations + +import 'dart:async'; +import 'package:stream_chat/src/core/models/event.dart'; +import 'package:stream_chat/src/core/util/event_controller.dart'; +import 'package:stream_chat/src/event_type.dart'; +import 'package:test/test.dart'; + +void main() { + group('EventController events', () { + late EventController controller; + + setUp(() { + controller = EventController(); + }); + + tearDown(() { + controller.close(); + }); + + test('should emit events without resolvers', () async { + final event = Event(type: EventType.messageNew); + + final streamEvents = []; + controller.listen(streamEvents.add); + + controller.add(event); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.messageNew); + }); + + test('should apply resolvers in order', () async { + Event? firstResolver(Event event) { + if (event.type == EventType.messageNew) { + return event.copyWith(type: EventType.pollCreated); + } + return null; + } + + Event? secondResolver(Event event) { + if (event.type == EventType.pollCreated) { + return event.copyWith(type: EventType.locationShared); + } + return null; + } + + controller = EventController( + resolvers: [firstResolver, secondResolver], + ); + + final streamEvents = []; + controller.listen(streamEvents.add); + + final originalEvent = Event(type: EventType.messageNew); + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.pollCreated); + }); + + test('should stop at first matching resolver', () async { + var firstResolverCalled = false; + var secondResolverCalled = false; + + Event? firstResolver(Event event) { + firstResolverCalled = true; + if (event.type == EventType.messageNew) { + return event.copyWith(type: EventType.pollCreated); + } + return null; + } + + Event? secondResolver(Event event) { + secondResolverCalled = true; + return event.copyWith(type: EventType.locationShared); + } + + controller = EventController( + resolvers: [firstResolver, secondResolver], + ); + + final streamEvents = []; + controller.listen(streamEvents.add); + + final originalEvent = Event(type: EventType.messageNew); + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(firstResolverCalled, isTrue); + expect(secondResolverCalled, isFalse); + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.pollCreated); + }); + + test('should emit original event when no resolver matches', () async { + Event? resolver(Event event) { + if (event.type == EventType.pollCreated) { + return event.copyWith(type: EventType.locationShared); + } + return null; + } + + controller = EventController( + resolvers: [resolver], + ); + + final streamEvents = []; + controller.listen(streamEvents.add); + + final originalEvent = Event(type: EventType.messageNew); + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.messageNew); + }); + + test('should work with multiple resolvers that return null', () async { + Event? firstResolver(Event event) => null; + Event? secondResolver(Event event) => null; + Event? thirdResolver(Event event) => null; + + controller = EventController( + resolvers: [firstResolver, secondResolver, thirdResolver], + ); + + final streamEvents = []; + controller.listen(streamEvents.add); + + final originalEvent = Event(type: EventType.messageNew); + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.messageNew); + }); + + test('should handle empty resolvers list', () async { + controller = EventController(resolvers: []); + + final streamEvents = []; + controller.listen(streamEvents.add); + + final originalEvent = Event(type: EventType.messageNew); + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.messageNew); + }); + + test('should support custom onListen callback', () async { + var onListenCalled = false; + + controller = EventController( + onListen: () => onListenCalled = true, + ); + + expect(onListenCalled, isFalse); + + controller.listen((_) {}); + + expect(onListenCalled, isTrue); + }); + + test('should support custom onCancel callback', () async { + var onCancelCalled = false; + + controller = EventController( + onCancel: () => onCancelCalled = true, + ); + + final subscription = controller.listen((_) {}); + + expect(onCancelCalled, isFalse); + + await subscription.cancel(); + + expect(onCancelCalled, isTrue); + }); + + test('should support sync mode', () async { + controller = EventController(sync: true); + + final streamEvents = []; + controller.listen(streamEvents.add); + + final originalEvent = Event(type: EventType.messageNew); + controller.add(originalEvent); + + // In sync mode, events should be available immediately + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.messageNew); + }); + + test('should handle resolver exceptions gracefully', () async { + Event? failingResolver(Event event) { + throw Exception('Resolver failed'); + } + + Event? workingResolver(Event event) { + return event.copyWith(type: EventType.pollCreated); + } + + controller = EventController( + resolvers: [failingResolver, workingResolver], + ); + + final streamEvents = []; + controller.listen(streamEvents.add); + + final originalEvent = Event(type: EventType.messageNew); + + // This should throw an exception because the resolver throws + expect(() => controller.add(originalEvent), throwsException); + }); + + test('should be compatible with stream operations', () async { + final event1 = Event(type: EventType.messageNew); + final event2 = Event(type: EventType.messageUpdated); + + final streamEvents = []; + controller + .where((event) => event.type == EventType.messageNew) + .listen(streamEvents.add); + + controller.add(event1); + controller.add(event2); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + expect(streamEvents.first.type, EventType.messageNew); + }); + + test('should work with multiple listeners', () async { + final streamEvents1 = []; + final streamEvents2 = []; + + controller.listen(streamEvents1.add); + controller.listen(streamEvents2.add); + + final originalEvent = Event(type: EventType.messageNew); + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(streamEvents1, hasLength(1)); + expect(streamEvents2, hasLength(1)); + expect(streamEvents1.first.type, EventType.messageNew); + expect(streamEvents2.first.type, EventType.messageNew); + }); + + test('should preserve event properties through resolvers', () async { + final originalEvent = Event( + type: EventType.messageNew, + userId: 'user123', + cid: 'channel123', + connectionId: 'conn123', + me: null, + user: null, + extraData: {'custom': 'data'}, + ); + + Event? resolver(Event event) { + if (event.type == EventType.messageNew) { + return event.copyWith(type: EventType.pollCreated); + } + return null; + } + + controller = EventController( + resolvers: [resolver], + ); + + final streamEvents = []; + controller.listen(streamEvents.add); + + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + final resolvedEvent = streamEvents.first; + expect(resolvedEvent.type, EventType.pollCreated); + expect(resolvedEvent.userId, 'user123'); + expect(resolvedEvent.cid, 'channel123'); + expect(resolvedEvent.connectionId, 'conn123'); + expect(resolvedEvent.extraData, {'custom': 'data'}); + }); + + test('should handle resolver modifying event data', () async { + final originalEvent = Event( + type: EventType.messageNew, + userId: 'user123', + extraData: {'original': 'data'}, + ); + + Event? resolver(Event event) { + if (event.type == EventType.messageNew) { + return event.copyWith( + type: EventType.pollCreated, + userId: 'modified_user', + extraData: {'modified': 'data'}, + ); + } + return null; + } + + controller = EventController( + resolvers: [resolver], + ); + + final streamEvents = []; + controller.listen(streamEvents.add); + + controller.add(originalEvent); + + await Future.delayed(Duration.zero); + + expect(streamEvents, hasLength(1)); + final resolvedEvent = streamEvents.first; + expect(resolvedEvent.type, EventType.pollCreated); + expect(resolvedEvent.userId, 'modified_user'); + expect(resolvedEvent.extraData, {'modified': 'data'}); + }); + }); +} From 1d21e9bc73f091c44d895facbee13656c4693856 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 15 Jul 2025 00:28:03 +0200 Subject: [PATCH 14/26] chore: fix analysis --- packages/stream_chat/test/src/client/event_resolvers_test.dart | 2 +- .../stream_chat/test/src/core/util/event_controller_test.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat/test/src/client/event_resolvers_test.dart b/packages/stream_chat/test/src/client/event_resolvers_test.dart index 521aa3160e..0d8155ccf4 100644 --- a/packages/stream_chat/test/src/client/event_resolvers_test.dart +++ b/packages/stream_chat/test/src/client/event_resolvers_test.dart @@ -1,4 +1,4 @@ -// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_redundant_argument_values, lines_longer_than_80_chars import 'package:stream_chat/src/client/event_resolvers.dart'; import 'package:stream_chat/src/core/models/event.dart'; diff --git a/packages/stream_chat/test/src/core/util/event_controller_test.dart b/packages/stream_chat/test/src/core/util/event_controller_test.dart index 6b01dfffbf..a789d2826b 100644 --- a/packages/stream_chat/test/src/core/util/event_controller_test.dart +++ b/packages/stream_chat/test/src/core/util/event_controller_test.dart @@ -1,4 +1,4 @@ -// ignore_for_file: cascade_invocations +// ignore_for_file: cascade_invocations, avoid_redundant_argument_values import 'dart:async'; import 'package:stream_chat/src/core/models/event.dart'; From 849900adb2c5db4b6f06b16fc345756298c45fb8 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 15 Jul 2025 00:38:00 +0200 Subject: [PATCH 15/26] chore: add location_test.dart --- .../test/src/core/models/location_test.dart | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 packages/stream_chat/test/src/core/models/location_test.dart diff --git a/packages/stream_chat/test/src/core/models/location_test.dart b/packages/stream_chat/test/src/core/models/location_test.dart new file mode 100644 index 0000000000..2ddcfbaf5d --- /dev/null +++ b/packages/stream_chat/test/src/core/models/location_test.dart @@ -0,0 +1,200 @@ +import 'package:stream_chat/src/core/models/channel_model.dart'; +import 'package:stream_chat/src/core/models/location.dart'; +import 'package:stream_chat/src/core/models/location_coordinates.dart'; +import 'package:stream_chat/src/core/models/message.dart'; +import 'package:test/test.dart'; + +void main() { + group('Location', () { + const latitude = 37.7749; + const longitude = -122.4194; + const createdByDeviceId = 'device_123'; + + final location = Location( + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + ); + + test('should create a valid instance with minimal parameters', () { + expect(location.latitude, equals(latitude)); + expect(location.longitude, equals(longitude)); + expect(location.createdByDeviceId, equals(createdByDeviceId)); + expect(location.endAt, isNull); + expect(location.channelCid, isNull); + expect(location.channel, isNull); + expect(location.messageId, isNull); + expect(location.message, isNull); + expect(location.userId, isNull); + expect(location.createdAt, isA()); + expect(location.updatedAt, isA()); + }); + + test('should create a valid instance with all parameters', () { + final createdAt = DateTime.parse('2023-01-01T00:00:00.000Z'); + final updatedAt = DateTime.parse('2023-01-01T01:00:00.000Z'); + final endAt = DateTime.parse('2024-12-31T23:59:59.999Z'); + final channel = ChannelModel( + cid: 'test:channel', + id: 'channel', + type: 'test', + createdAt: createdAt, + updatedAt: updatedAt, + ); + final message = Message( + id: 'message_123', + text: 'Test message', + createdAt: createdAt, + updatedAt: updatedAt, + ); + + final fullLocation = Location( + channelCid: 'test:channel', + channel: channel, + messageId: 'message_123', + message: message, + userId: 'user_123', + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, + ); + + expect(fullLocation.channelCid, equals('test:channel')); + expect(fullLocation.channel, equals(channel)); + expect(fullLocation.messageId, equals('message_123')); + expect(fullLocation.message, equals(message)); + expect(fullLocation.userId, equals('user_123')); + expect(fullLocation.latitude, equals(latitude)); + expect(fullLocation.longitude, equals(longitude)); + expect(fullLocation.createdByDeviceId, equals(createdByDeviceId)); + expect(fullLocation.endAt, equals(endAt)); + expect(fullLocation.createdAt, equals(createdAt)); + expect(fullLocation.updatedAt, equals(updatedAt)); + }); + + test('should correctly serialize to JSON', () { + final json = location.toJson(); + + expect(json['latitude'], equals(latitude)); + expect(json['longitude'], equals(longitude)); + expect(json['created_by_device_id'], equals(createdByDeviceId)); + expect(json['end_at'], isNull); + expect(json.containsKey('channel_cid'), isFalse); + expect(json.containsKey('channel'), isFalse); + expect(json.containsKey('message_id'), isFalse); + expect(json.containsKey('message'), isFalse); + expect(json.containsKey('user_id'), isFalse); + expect(json.containsKey('created_at'), isFalse); + expect(json.containsKey('updated_at'), isFalse); + }); + + test('should serialize live location with endAt correctly', () { + final endAt = DateTime.parse('2024-12-31T23:59:59.999Z'); + final liveLocation = Location( + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: endAt, + ); + + final json = liveLocation.toJson(); + + expect(json['latitude'], equals(latitude)); + expect(json['longitude'], equals(longitude)); + expect(json['created_by_device_id'], equals(createdByDeviceId)); + expect(json['end_at'], equals('2024-12-31T23:59:59.999Z')); + }); + + test('should return correct coordinates', () { + final coordinates = location.coordinates; + + expect(coordinates, isA()); + expect(coordinates.latitude, equals(latitude)); + expect(coordinates.longitude, equals(longitude)); + }); + + test('isActive should return true for active live location', () { + final futureDate = DateTime.now().add(const Duration(hours: 1)); + final activeLocation = Location( + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: futureDate, + ); + + expect(activeLocation.isActive, isTrue); + expect(activeLocation.isExpired, isFalse); + }); + + test('isActive should return false for expired live location', () { + final pastDate = DateTime.now().subtract(const Duration(hours: 1)); + final expiredLocation = Location( + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: pastDate, + ); + + expect(expiredLocation.isActive, isFalse); + expect(expiredLocation.isExpired, isTrue); + }); + + test('isLive should return true for live location', () { + final futureDate = DateTime.now().add(const Duration(hours: 1)); + final liveLocation = Location( + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: futureDate, + ); + + expect(liveLocation.isLive, isTrue); + expect(liveLocation.isStatic, isFalse); + }); + + test('equality should work correctly', () { + final location1 = Location( + channelCid: 'test:channel', + messageId: 'message_123', + userId: 'user_123', + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: DateTime.parse('2024-12-31T23:59:59.999Z'), + createdAt: DateTime.parse('2023-01-01T00:00:00.000Z'), + updatedAt: DateTime.parse('2023-01-01T00:00:00.000Z'), + ); + + final location2 = Location( + channelCid: 'test:channel', + messageId: 'message_123', + userId: 'user_123', + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: DateTime.parse('2024-12-31T23:59:59.999Z'), + createdAt: DateTime.parse('2023-01-01T00:00:00.000Z'), + updatedAt: DateTime.parse('2023-01-01T00:00:00.000Z'), + ); + + final location3 = Location( + channelCid: 'test:channel', + messageId: 'message_123', + userId: 'user_123', + latitude: 40.7128, // Different latitude + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: DateTime.parse('2024-12-31T23:59:59.999Z'), + createdAt: DateTime.parse('2023-01-01T00:00:00.000Z'), + updatedAt: DateTime.parse('2023-01-01T00:00:00.000Z'), + ); + + expect(location1, equals(location2)); + expect(location1.hashCode, equals(location2.hashCode)); + expect(location1, isNot(equals(location3))); + }); + }); +} From 5d647004ba163a28467aaf56949c30cb4056c92a Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 15 Jul 2025 13:38:40 +0200 Subject: [PATCH 16/26] chore: cleanup and minor fixes --- .../stream_chat/lib/src/core/api/message_api.dart | 2 +- .../stream_chat/lib/src/core/models/message.dart | 2 +- .../stream_chat/lib/src/core/models/message.g.dart | 2 ++ sample_app/lib/utils/app_config.dart | 4 ---- sample_app/lib/utils/location_provider.dart | 12 ++++-------- sample_app/lib/utils/shared_location_service.dart | 5 +---- 6 files changed, 9 insertions(+), 18 deletions(-) diff --git a/packages/stream_chat/lib/src/core/api/message_api.dart b/packages/stream_chat/lib/src/core/api/message_api.dart index afd00caed6..6b8103fa3c 100644 --- a/packages/stream_chat/lib/src/core/api/message_api.dart +++ b/packages/stream_chat/lib/src/core/api/message_api.dart @@ -27,7 +27,7 @@ class MessageApi { final response = await _client.post( '/channels/$channelType/$channelId/message', data: { - 'message': message, + 'message': message.toJson(), 'skip_push': skipPush, 'skip_enrich_url': skipEnrichUrl, }, diff --git a/packages/stream_chat/lib/src/core/models/message.dart b/packages/stream_chat/lib/src/core/models/message.dart index bee0a3b9d1..e517bad464 100644 --- a/packages/stream_chat/lib/src/core/models/message.dart +++ b/packages/stream_chat/lib/src/core/models/message.dart @@ -322,7 +322,7 @@ class Message extends Equatable implements ComparableFieldProvider { /// /// This is used to share a location in a message, allowing users to view the /// location on a map. - @JsonKey(includeToJson: false) + @JsonKey(includeIfNull: false) final Location? sharedLocation; /// Message custom extraData. diff --git a/packages/stream_chat/lib/src/core/models/message.g.dart b/packages/stream_chat/lib/src/core/models/message.g.dart index 1a36d370af..84912eb1c3 100644 --- a/packages/stream_chat/lib/src/core/models/message.g.dart +++ b/packages/stream_chat/lib/src/core/models/message.g.dart @@ -115,5 +115,7 @@ Map _$MessageToJson(Message instance) => { 'poll_id': instance.pollId, if (instance.restrictedVisibility case final value?) 'restricted_visibility': value, + if (instance.sharedLocation?.toJson() case final value?) + 'shared_location': value, 'extra_data': instance.extraData, }; diff --git a/sample_app/lib/utils/app_config.dart b/sample_app/lib/utils/app_config.dart index b66a4328f8..e006cddfee 100644 --- a/sample_app/lib/utils/app_config.dart +++ b/sample_app/lib/utils/app_config.dart @@ -6,10 +6,6 @@ const sentryDsn = const kDefaultStreamApiKey = 'kv7mcsxr24p8'; final defaultUsers = { - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibGVpYV9vcmdhbmEifQ.8NXs4DZrx_hljsaC8d6xlZ07FUgenKmb6hDNU-KFQ3M': - User( - id: 'leia_organa', - ), 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8': User( id: 'salvatore', diff --git a/sample_app/lib/utils/location_provider.dart b/sample_app/lib/utils/location_provider.dart index 5b3950e518..fbf7168028 100644 --- a/sample_app/lib/utils/location_provider.dart +++ b/sample_app/lib/utils/location_provider.dart @@ -1,3 +1,5 @@ +// ignore_for_file: close_sinks + import 'dart:async'; import 'package:geolocator/geolocator.dart'; @@ -68,8 +70,8 @@ class LocationProvider { _positionSubscription = Geolocator.getPositionStream( locationSettings: settings, ).listen( - _positionStreamController.add, - onError: _positionStreamController.addError, + _positionStreamController.safeAdd, + onError: _positionStreamController.safeAddError, ); } @@ -79,12 +81,6 @@ class LocationProvider { _positionSubscription = null; } - /// Clean up resources - void reset() { - stopTracking(); - if (!_positionStreamController.isClosed) _positionStreamController.close(); - } - Future _handlePermission() async { final serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) return false; diff --git a/sample_app/lib/utils/shared_location_service.dart b/sample_app/lib/utils/shared_location_service.dart index 6eb24c890b..1d7a7128c6 100644 --- a/sample_app/lib/utils/shared_location_service.dart +++ b/sample_app/lib/utils/shared_location_service.dart @@ -80,10 +80,7 @@ class SharedLocationService { /// Clean up resources Future dispose() async { - _locationProvider.reset(); - - _positionSubscription?.cancel(); - _positionSubscription = null; + _stopTrackingLocation(); _activeLiveLocationsSubscription?.cancel(); _activeLiveLocationsSubscription = null; From a6965cb166e5820576a77eeb63d1705431f28a07 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 15 Jul 2025 15:14:49 +0200 Subject: [PATCH 17/26] chore: fix test --- packages/stream_chat/lib/src/core/api/message_api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat/lib/src/core/api/message_api.dart b/packages/stream_chat/lib/src/core/api/message_api.dart index 6b8103fa3c..afd00caed6 100644 --- a/packages/stream_chat/lib/src/core/api/message_api.dart +++ b/packages/stream_chat/lib/src/core/api/message_api.dart @@ -27,7 +27,7 @@ class MessageApi { final response = await _client.post( '/channels/$channelType/$channelId/message', data: { - 'message': message.toJson(), + 'message': message, 'skip_push': skipPush, 'skip_enrich_url': skipEnrichUrl, }, From 7016d005cb9bd9c2eb0ce473002f5d2f22aeb97d Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 21 Jul 2025 12:22:42 +0200 Subject: [PATCH 18/26] refactor(llc): group event listeners using `region` comments Groups related event listener method calls within `StreamChatClient` and `Channel` using `// region` and `// endregion` comments for better code organization and readability. --- .../stream_chat/lib/src/client/channel.dart | 60 +++++++------------ .../stream_chat/lib/src/client/client.dart | 12 ++-- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 87f796bf33..165b10ad13 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -2156,87 +2156,71 @@ class ChannelClientState { _channelStateController = BehaviorSubject.seeded(channelState); + // region TYPING EVENTS _listenTypingEvents(); + // endregion + // region MESSAGE EVENTS _listenMessageNew(); - _listenMessageDeleted(); - _listenMessageUpdated(); + // endregion - /* Start of draft events */ - + // region DRAFT EVENTS _listenDraftUpdated(); - _listenDraftDeleted(); + // endregion - /* End of draft events */ - + // region REACTION EVENTS _listenReactionNew(); - _listenReactionUpdated(); - _listenReactionDeleted(); + // endregion - /* Start of poll events */ - + // region POLL EVENTS _listenPollCreated(); - _listenPollUpdated(); - _listenPollClosed(); - _listenPollAnswerCasted(); - _listenPollVoteCasted(); - _listenPollVoteChanged(); - _listenPollAnswerRemoved(); - _listenPollVoteRemoved(); + // endregion - /* End of poll events */ - + // region READ EVENTS _listenReadEvents(); + // endregion + // region CHANNEL EVENTS _listenChannelTruncated(); - _listenChannelUpdated(); + // endregion + // region MEMBER EVENTS _listenMemberAdded(); - _listenMemberRemoved(); - _listenMemberUpdated(); - _listenMemberBanned(); - _listenMemberUnbanned(); + // endregion + // region USER WATCHING EVENTS _listenUserStartWatching(); - _listenUserStopWatching(); + // endregion - /* Start of reminder events */ - + // region REMINDER EVENTS _listenReminderCreated(); - _listenReminderUpdated(); - _listenReminderDeleted(); + // endregion - /* End of reminder events */ - - /* Start of location events */ - + // region LOCATION EVENTS _listenLocationShared(); - _listenLocationUpdated(); - _listenLocationExpired(); - - /* End of location events */ + // endregion _startCleaningStaleTypingEvents(); diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 1bbd5eeeff..dab7f0bc57 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -2124,21 +2124,25 @@ class ClientState { }), ); + // region CHANNEL EVENTS _listenChannelLeft(); - _listenChannelDeleted(); - _listenChannelHidden(); + // endregion + // region USER EVENTS _listenUserUpdated(); + // endregion + // region READ EVENTS _listenAllChannelsRead(); + // endregion + // region LOCATION EVENTS _listenLocationShared(); - _listenLocationUpdated(); - _listenLocationExpired(); + // endregion _startCleaningExpiredLocations(); } From 4e9141cfc77f09e1be2b6862f9db148164551cf6 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 21 Jul 2025 12:25:48 +0200 Subject: [PATCH 19/26] chore: format --- packages/stream_chat/lib/src/core/api/responses.g.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat/lib/src/core/api/responses.g.dart b/packages/stream_chat/lib/src/core/api/responses.g.dart index 67c8135245..a8cc26f578 100644 --- a/packages/stream_chat/lib/src/core/api/responses.g.dart +++ b/packages/stream_chat/lib/src/core/api/responses.g.dart @@ -477,7 +477,7 @@ GetUnreadCountResponse _$GetUnreadCountResponseFromJson( .toList(); GetActiveLiveLocationsResponse _$GetActiveLiveLocationsResponseFromJson( - Map json) => + Map json) => GetActiveLiveLocationsResponse() ..duration = json['duration'] as String? ..activeLiveLocations = (json['active_live_locations'] as List) From c91ca6479d3f0e57f93c5723b305a267ea1e7a7f Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 21 Jul 2025 16:30:01 +0200 Subject: [PATCH 20/26] feat(persistence): add support for location persistence Adds support for `Location` entity in the database. Adds new methods in `ChatPersistenceClient`: - `getLocationsByCid` - `getLocationByMessageId` - `updateLocations` - `deleteLocationsByCid` - `deleteLocationsByMessageIds` Updates `Message` and `PinnedMessage` mappers to include `sharedLocation`. --- .../lib/src/db/chat_persistence_client.dart | 24 + .../src/db/chat_persistence_client_test.dart | 17 + packages/stream_chat_persistence/CHANGELOG.md | 4 + .../lib/src/dao/dao.dart | 1 + .../lib/src/dao/draft_message_dao.dart | 17 +- .../lib/src/dao/location_dao.dart | 83 + .../lib/src/dao/location_dao.g.dart | 10 + .../lib/src/dao/message_dao.dart | 69 +- .../lib/src/dao/pinned_message_dao.dart | 111 +- .../lib/src/db/drift_chat_database.dart | 4 +- .../lib/src/db/drift_chat_database.g.dart | 10452 +++++++++------- .../lib/src/entity/entity.dart | 1 + .../lib/src/entity/locations.dart | 43 + .../lib/src/mapper/location_mapper.dart | 40 + .../lib/src/mapper/mapper.dart | 1 + .../lib/src/mapper/message_mapper.dart | 2 + .../lib/src/mapper/pinned_message_mapper.dart | 5 + .../src/stream_chat_persistence_client.dart | 35 + .../test/mock_chat_database.dart | 6 + .../test/src/dao/location_dao_test.dart | 316 + .../test/src/mapper/location_mapper_test.dart | 141 + .../stream_chat_persistence_client_test.dart | 90 + 22 files changed, 6715 insertions(+), 4757 deletions(-) create mode 100644 packages/stream_chat_persistence/lib/src/dao/location_dao.dart create mode 100644 packages/stream_chat_persistence/lib/src/dao/location_dao.g.dart create mode 100644 packages/stream_chat_persistence/lib/src/entity/locations.dart create mode 100644 packages/stream_chat_persistence/lib/src/mapper/location_mapper.dart create mode 100644 packages/stream_chat_persistence/test/src/dao/location_dao_test.dart create mode 100644 packages/stream_chat_persistence/test/src/mapper/location_mapper_test.dart diff --git a/packages/stream_chat/lib/src/db/chat_persistence_client.dart b/packages/stream_chat/lib/src/db/chat_persistence_client.dart index ade11ffab4..ccf5c3f03f 100644 --- a/packages/stream_chat/lib/src/db/chat_persistence_client.dart +++ b/packages/stream_chat/lib/src/db/chat_persistence_client.dart @@ -7,6 +7,7 @@ import 'package:stream_chat/src/core/models/channel_state.dart'; import 'package:stream_chat/src/core/models/draft.dart'; import 'package:stream_chat/src/core/models/event.dart'; import 'package:stream_chat/src/core/models/filter.dart'; +import 'package:stream_chat/src/core/models/location.dart'; import 'package:stream_chat/src/core/models/member.dart'; import 'package:stream_chat/src/core/models/message.dart'; import 'package:stream_chat/src/core/models/poll.dart'; @@ -83,6 +84,12 @@ abstract class ChatPersistenceClient { /// [parentId] for thread messages. Future getDraftMessageByCid(String cid, {String? parentId}); + /// Get stored [Location]s by providing channel [cid] + Future> getLocationsByCid(String cid); + + /// Get stored [Location] by providing [messageId] + Future getLocationByMessageId(String messageId); + /// Get [ChannelState] data by providing channel [cid] Future getChannelStateByCid( String cid, { @@ -168,6 +175,12 @@ abstract class ChatPersistenceClient { /// [DraftMessages.parentId]. Future deleteDraftMessageByCid(String cid, {String? parentId}); + /// Removes locations by channel [cid] + Future deleteLocationsByCid(String cid); + + /// Removes locations by message [messageIds] + Future deleteLocationsByMessageIds(List messageIds); + /// Updates the message data of a particular channel [cid] with /// the new [messages] data Future updateMessages(String cid, List messages) => @@ -228,6 +241,9 @@ abstract class ChatPersistenceClient { /// Updates the draft messages data with the new [draftMessages] data Future updateDraftMessages(List draftMessages); + /// Updates the locations data with the new [locations] data + Future updateLocations(List locations); + /// Deletes all the reactions by [messageIds] Future deleteReactionsByMessageId(List messageIds); @@ -287,6 +303,8 @@ abstract class ChatPersistenceClient { final pollVotes = []; final pollVotesToDelete = []; + final locations = []; + for (final state in channelStates) { final channel = state.channel; // Continue if channel is not available. @@ -336,6 +354,11 @@ abstract class ChatPersistenceClient { ...?pinnedMessages?.map((it) => it.draft), ].nonNulls); + locations.addAll([ + ...?messages?.map((it) => it.sharedLocation), + ...?pinnedMessages?.map((it) => it.sharedLocation), + ].nonNulls); + users.addAll([ channel.createdBy, ...?messages?.map((it) => it.user), @@ -379,6 +402,7 @@ abstract class ChatPersistenceClient { updatePinnedMessageReactions(pinnedReactions), updatePollVotes(pollVotes), updateDraftMessages(drafts), + updateLocations(locations), ]); } diff --git a/packages/stream_chat/test/src/db/chat_persistence_client_test.dart b/packages/stream_chat/test/src/db/chat_persistence_client_test.dart index 00adbe6686..9d1492efc7 100644 --- a/packages/stream_chat/test/src/db/chat_persistence_client_test.dart +++ b/packages/stream_chat/test/src/db/chat_persistence_client_test.dart @@ -6,6 +6,7 @@ import 'package:stream_chat/src/core/models/draft.dart'; import 'package:stream_chat/src/core/models/draft_message.dart'; import 'package:stream_chat/src/core/models/event.dart'; import 'package:stream_chat/src/core/models/filter.dart'; +import 'package:stream_chat/src/core/models/location.dart'; import 'package:stream_chat/src/core/models/member.dart'; import 'package:stream_chat/src/core/models/message.dart'; import 'package:stream_chat/src/core/models/poll.dart'; @@ -173,6 +174,22 @@ class TestPersistenceClient extends ChatPersistenceClient { @override Future updateDraftMessages(List draftMessages) => Future.value(); + + @override + Future> getLocationsByCid(String cid) async => []; + + @override + Future getLocationByMessageId(String messageId) async => null; + + @override + Future updateLocations(List locations) => Future.value(); + + @override + Future deleteLocationsByCid(String cid) => Future.value(); + + @override + Future deleteLocationsByMessageIds(List messageIds) => + Future.value(); } void main() { diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md index 1a3e3bff99..d179d4a8a9 100644 --- a/packages/stream_chat_persistence/CHANGELOG.md +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -1,3 +1,7 @@ +## Upcoming Beta + +- Added support for `Location` entity in the database. + ## 10.0.0-beta.3 - Included the changes from version [`9.14.0`](https://pub.dev/packages/stream_chat_persistence/changelog). diff --git a/packages/stream_chat_persistence/lib/src/dao/dao.dart b/packages/stream_chat_persistence/lib/src/dao/dao.dart index d0aab7b212..d2f088c399 100644 --- a/packages/stream_chat_persistence/lib/src/dao/dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/dao.dart @@ -2,6 +2,7 @@ export 'channel_dao.dart'; export 'channel_query_dao.dart'; export 'connection_event_dao.dart'; export 'draft_message_dao.dart'; +export 'location_dao.dart'; export 'member_dao.dart'; export 'message_dao.dart'; export 'pinned_message_dao.dart'; diff --git a/packages/stream_chat_persistence/lib/src/dao/draft_message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/draft_message_dao.dart index 1c69c31658..1b8cd4eda2 100644 --- a/packages/stream_chat_persistence/lib/src/dao/draft_message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/draft_message_dao.dart @@ -18,18 +18,27 @@ class DraftMessageDao extends DatabaseAccessor final DriftChatDatabase _db; Future _draftFromEntity(DraftMessageEntity entity) async { - // We do not want to fetch the draft message of the parent and quoted - // message because it will create a circular dependency and will + // We do not want to fetch the draft and shared location of the parent and + // quoted message because it will create a circular dependency and will // result in infinite loop. const fetchDraft = false; + const fetchSharedLocation = false; final parentMessage = await switch (entity.parentId) { - final id? => _db.messageDao.getMessageById(id, fetchDraft: fetchDraft), + final id? => _db.messageDao.getMessageById( + id, + fetchDraft: fetchDraft, + fetchSharedLocation: fetchSharedLocation, + ), _ => null, }; final quotedMessage = await switch (entity.quotedMessageId) { - final id? => _db.messageDao.getMessageById(id, fetchDraft: fetchDraft), + final id? => _db.messageDao.getMessageById( + id, + fetchDraft: fetchDraft, + fetchSharedLocation: fetchSharedLocation, + ), _ => null, }; diff --git a/packages/stream_chat_persistence/lib/src/dao/location_dao.dart b/packages/stream_chat_persistence/lib/src/dao/location_dao.dart new file mode 100644 index 0000000000..6e12421179 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/location_dao.dart @@ -0,0 +1,83 @@ +// ignore_for_file: join_return_with_assignment + +import 'package:drift/drift.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; +import 'package:stream_chat_persistence/src/entity/locations.dart'; +import 'package:stream_chat_persistence/src/mapper/mapper.dart'; + +part 'location_dao.g.dart'; + +/// The Data Access Object for operations in [Locations] table. +@DriftAccessor(tables: [Locations]) +class LocationDao extends DatabaseAccessor + with _$LocationDaoMixin { + /// Creates a new location dao instance + LocationDao(this._db) : super(_db); + + final DriftChatDatabase _db; + + Future _locationFromEntity(LocationEntity entity) async { + // We do not want to fetch the location of the parent and quoted + // message because it will create a circular dependency and will + // result in infinite loop. + const fetchDraft = false; + const fetchSharedLocation = false; + + final channel = await switch (entity.channelCid) { + final cid? => db.channelDao.getChannelByCid(cid), + _ => null, + }; + + final message = await switch (entity.messageId) { + final id? => _db.messageDao.getMessageById( + id, + fetchDraft: fetchDraft, + fetchSharedLocation: fetchSharedLocation, + ), + _ => null, + }; + + return entity.toLocation( + channel: channel, + message: message, + ); + } + + /// Get all locations for a channel + Future> getLocationsByCid(String cid) async { + final query = select(locations)..where((tbl) => tbl.channelCid.equals(cid)); + + final result = await query.map(_locationFromEntity).get(); + return Future.wait(result); + } + + /// Get location by message ID + Future getLocationByMessageId(String messageId) async { + final query = select(locations) // + ..where((tbl) => tbl.messageId.equals(messageId)); + + final result = await query.getSingleOrNull(); + if (result == null) return null; + + return _locationFromEntity(result); + } + + /// Update multiple locations + Future updateLocations(List locationList) { + return batch( + (it) => it.insertAllOnConflictUpdate( + locations, + locationList.map((it) => it.toEntity()), + ), + ); + } + + /// Delete locations by channel ID + Future deleteLocationsByCid(String cid) => + (delete(locations)..where((tbl) => tbl.channelCid.equals(cid))).go(); + + /// Delete locations by message IDs + Future deleteLocationsByMessageIds(List messageIds) => + (delete(locations)..where((tbl) => tbl.messageId.isIn(messageIds))).go(); +} diff --git a/packages/stream_chat_persistence/lib/src/dao/location_dao.g.dart b/packages/stream_chat_persistence/lib/src/dao/location_dao.g.dart new file mode 100644 index 0000000000..240b3b4b83 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/dao/location_dao.g.dart @@ -0,0 +1,10 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'location_dao.dart'; + +// ignore_for_file: type=lint +mixin _$LocationDaoMixin on DatabaseAccessor { + $ChannelsTable get channels => attachedDatabase.channels; + $MessagesTable get messages => attachedDatabase.messages; + $LocationsTable get locations => attachedDatabase.locations; +} 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 3d11267a6d..350867dfdd 100644 --- a/packages/stream_chat_persistence/lib/src/dao/message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/message_dao.dart @@ -38,7 +38,8 @@ class MessageDao extends DatabaseAccessor Future _messageFromJoinRow( TypedResult rows, { - bool fetchDraft = true, + bool fetchDraft = false, + bool fetchSharedLocation = false, }) async { final userEntity = rows.readTableOrNull(_users); final pinnedByEntity = rows.readTableOrNull(_pinnedByUsers); @@ -67,6 +68,11 @@ class MessageDao extends DatabaseAccessor _ => null, }; + final sharedLocation = await switch (fetchSharedLocation) { + true => _db.locationDao.getLocationByMessageId(msgEntity.id), + _ => null, + }; + return msgEntity.toMessage( user: userEntity?.toUser(), pinnedBy: pinnedByEntity?.toUser(), @@ -75,6 +81,7 @@ class MessageDao extends DatabaseAccessor quotedMessage: quotedMessage, poll: poll, draft: draft, + sharedLocation: sharedLocation, ); } @@ -85,19 +92,26 @@ class MessageDao extends DatabaseAccessor Future getMessageById( String id, { bool fetchDraft = true, - }) async => - await (select(messages).join( - [ - leftOuterJoin(_users, messages.userId.equalsExp(_users.id)), - leftOuterJoin( - _pinnedByUsers, - messages.pinnedByUserId.equalsExp(_pinnedByUsers.id), - ), - ], - )..where(messages.id.equals(id))) - .map((row) { - return _messageFromJoinRow(row, fetchDraft: fetchDraft); - }).getSingleOrNull(); + bool fetchSharedLocation = true, + }) async { + final query = select(messages).join([ + leftOuterJoin(_users, messages.userId.equalsExp(_users.id)), + leftOuterJoin( + _pinnedByUsers, + messages.pinnedByUserId.equalsExp(_pinnedByUsers.id), + ), + ]) + ..where(messages.id.equals(id)); + + final result = await query.getSingleOrNull(); + if (result == null) return null; + + return _messageFromJoinRow( + result, + fetchDraft: fetchDraft, + fetchSharedLocation: fetchSharedLocation, + ); + } /// Returns all the messages of a particular thread by matching /// [Messages.channelCid] with [cid] @@ -163,22 +177,33 @@ class MessageDao extends DatabaseAccessor /// [Messages.channelCid] with [parentId] Future> getMessagesByCid( String cid, { + bool fetchDraft = true, + bool fetchSharedLocation = true, PaginationParams? messagePagination, }) async { - final msgList = await Future.wait(await (select(messages).join([ + final query = select(messages).join([ leftOuterJoin(_users, messages.userId.equalsExp(_users.id)), leftOuterJoin( _pinnedByUsers, messages.pinnedByUserId.equalsExp(_pinnedByUsers.id), ), ]) - ..where(messages.channelCid.equals(cid)) - ..where( - messages.parentId.isNull() | messages.showInChannel.equals(true), - ) - ..orderBy([OrderingTerm.asc(messages.createdAt)])) - .map(_messageFromJoinRow) - .get()); + ..where(messages.channelCid.equals(cid)) + ..where(messages.parentId.isNull() | messages.showInChannel.equals(true)) + ..orderBy([OrderingTerm.asc(messages.createdAt)]); + + final result = await query.get(); + if (result.isEmpty) return []; + + final msgList = await Future.wait( + result.map( + (row) => _messageFromJoinRow( + row, + fetchDraft: fetchDraft, + fetchSharedLocation: fetchSharedLocation, + ), + ), + ); if (msgList.isNotEmpty) { if (messagePagination?.lessThan != null) { diff --git a/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart index bf7b45b12b..10459eeebc 100644 --- a/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart @@ -35,27 +35,43 @@ class PinnedMessageDao extends DatabaseAccessor Future deleteMessageByCids(List cids) async => (delete(pinnedMessages)..where((tbl) => tbl.channelCid.isIn(cids))).go(); - Future _messageFromJoinRow(TypedResult rows) async { - final userEntity = rows.readTableOrNull(users); + Future _messageFromJoinRow( + TypedResult rows, { + bool fetchDraft = false, + bool fetchSharedLocation = false, + }) async { + final userEntity = rows.readTableOrNull(_users); final pinnedByEntity = rows.readTableOrNull(_pinnedByUsers); final msgEntity = rows.readTable(pinnedMessages); - final latestReactions = - await _db.pinnedMessageReactionDao.getReactions(msgEntity.id); - final ownReactions = - await _db.pinnedMessageReactionDao.getReactionsByUserId( + final latestReactions = await _db.reactionDao.getReactions(msgEntity.id); + final ownReactions = await _db.reactionDao.getReactionsByUserId( msgEntity.id, _db.userId, ); - Message? quotedMessage; - final quotedMessageId = msgEntity.quotedMessageId; - if (quotedMessageId != null) { - quotedMessage = await getMessageById(quotedMessageId); - } - Poll? poll; - final pollId = msgEntity.pollId; - if (pollId != null) { - poll = await _db.pollDao.getPollById(pollId); - } + + final quotedMessage = await switch (msgEntity.quotedMessageId) { + final id? => getMessageById(id), + _ => null, + }; + + final poll = await switch (msgEntity.pollId) { + final id? => _db.pollDao.getPollById(id), + _ => null, + }; + + final draft = await switch (fetchDraft) { + true => _db.draftMessageDao.getDraftMessageByCid( + msgEntity.channelCid, + parentId: msgEntity.parentId, + ), + _ => null, + }; + + final sharedLocation = await switch (fetchSharedLocation) { + true => _db.locationDao.getLocationByMessageId(msgEntity.id), + _ => null, + }; + return msgEntity.toMessage( user: userEntity?.toUser(), pinnedBy: pinnedByEntity?.toUser(), @@ -63,21 +79,35 @@ class PinnedMessageDao extends DatabaseAccessor ownReactions: ownReactions, quotedMessage: quotedMessage, poll: poll, + draft: draft, + sharedLocation: sharedLocation, ); } /// Returns a single message by matching the [PinnedMessages.id] with [id] - Future getMessageById(String id) async => - await (select(pinnedMessages).join([ - leftOuterJoin(_users, pinnedMessages.userId.equalsExp(_users.id)), - leftOuterJoin( - _pinnedByUsers, - pinnedMessages.pinnedByUserId.equalsExp(_pinnedByUsers.id), - ), - ]) - ..where(pinnedMessages.id.equals(id))) - .map(_messageFromJoinRow) - .getSingleOrNull(); + Future getMessageById( + String id, { + bool fetchDraft = true, + bool fetchSharedLocation = true, + }) async { + final query = select(pinnedMessages).join([ + leftOuterJoin(_users, pinnedMessages.userId.equalsExp(_users.id)), + leftOuterJoin( + _pinnedByUsers, + pinnedMessages.pinnedByUserId.equalsExp(_pinnedByUsers.id), + ), + ]) + ..where(pinnedMessages.id.equals(id)); + + final result = await query.getSingleOrNull(); + if (result == null) return null; + + return _messageFromJoinRow( + result, + fetchDraft: fetchDraft, + fetchSharedLocation: fetchSharedLocation, + ); + } /// Returns all the messages of a particular thread by matching /// [PinnedMessages.channelCid] with [cid] @@ -142,21 +172,34 @@ class PinnedMessageDao extends DatabaseAccessor /// [PinnedMessages.channelCid] with [parentId] Future> getMessagesByCid( String cid, { + bool fetchDraft = true, + bool fetchSharedLocation = true, PaginationParams? messagePagination, }) async { - final msgList = await Future.wait(await (select(pinnedMessages).join([ + final query = select(pinnedMessages).join([ leftOuterJoin(_users, pinnedMessages.userId.equalsExp(_users.id)), leftOuterJoin( _pinnedByUsers, pinnedMessages.pinnedByUserId.equalsExp(_pinnedByUsers.id), ), ]) - ..where(pinnedMessages.channelCid.equals(cid)) - ..where(pinnedMessages.parentId.isNull() | - pinnedMessages.showInChannel.equals(true)) - ..orderBy([OrderingTerm.asc(pinnedMessages.createdAt)])) - .map(_messageFromJoinRow) - .get()); + ..where(pinnedMessages.channelCid.equals(cid)) + ..where(pinnedMessages.parentId.isNull() | + pinnedMessages.showInChannel.equals(true)) + ..orderBy([OrderingTerm.asc(pinnedMessages.createdAt)]); + + final result = await query.get(); + if (result.isEmpty) return []; + + final msgList = await Future.wait( + result.map( + (row) => _messageFromJoinRow( + row, + fetchDraft: fetchDraft, + fetchSharedLocation: fetchSharedLocation, + ), + ), + ); if (msgList.isNotEmpty) { if (messagePagination?.lessThan != null) { diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart index c1aa217973..e01545bf4b 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart @@ -13,6 +13,7 @@ part 'drift_chat_database.g.dart'; tables: [ Channels, DraftMessages, + Locations, Messages, PinnedMessages, Polls, @@ -30,6 +31,7 @@ part 'drift_chat_database.g.dart'; ChannelDao, MessageDao, DraftMessageDao, + LocationDao, PinnedMessageDao, PinnedMessageReactionDao, MemberDao, @@ -55,7 +57,7 @@ class DriftChatDatabase extends _$DriftChatDatabase { // you should bump this number whenever you change or add a table definition. @override - int get schemaVersion => 21; + int get schemaVersion => 22; @override MigrationStrategy get migration => MigrationStrategy( diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart index 62b81b61e0..9dff3dc78a 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart @@ -2808,1302 +2808,426 @@ class DraftMessagesCompanion extends UpdateCompanion { } } -class $PinnedMessagesTable extends PinnedMessages - with TableInfo<$PinnedMessagesTable, PinnedMessageEntity> { +class $LocationsTable extends Locations + with TableInfo<$LocationsTable, LocationEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $PinnedMessagesTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _idMeta = const VerificationMeta('id'); - @override - late final GeneratedColumn id = GeneratedColumn( - 'id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _messageTextMeta = - const VerificationMeta('messageText'); - @override - late final GeneratedColumn messageText = GeneratedColumn( - 'message_text', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - @override - late final GeneratedColumnWithTypeConverter, String> - attachments = GeneratedColumn('attachments', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true) - .withConverter>( - $PinnedMessagesTable.$converterattachments); - static const VerificationMeta _stateMeta = const VerificationMeta('state'); - @override - late final GeneratedColumn state = GeneratedColumn( - 'state', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _typeMeta = const VerificationMeta('type'); + $LocationsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _channelCidMeta = + const VerificationMeta('channelCid'); @override - late final GeneratedColumn type = GeneratedColumn( - 'type', aliasedName, false, + late final GeneratedColumn channelCid = GeneratedColumn( + 'channel_cid', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false, - defaultValue: const Constant('regular')); - @override - late final GeneratedColumnWithTypeConverter, String> - mentionedUsers = GeneratedColumn( - 'mentioned_users', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true) - .withConverter>( - $PinnedMessagesTable.$convertermentionedUsers); - @override - late final GeneratedColumnWithTypeConverter?, - String> reactionGroups = GeneratedColumn( - 'reaction_groups', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $PinnedMessagesTable.$converterreactionGroupsn); - static const VerificationMeta _parentIdMeta = - const VerificationMeta('parentId'); - @override - late final GeneratedColumn parentId = GeneratedColumn( - 'parent_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _quotedMessageIdMeta = - const VerificationMeta('quotedMessageId'); - @override - late final GeneratedColumn quotedMessageId = GeneratedColumn( - 'quoted_message_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _pollIdMeta = const VerificationMeta('pollId'); - @override - late final GeneratedColumn pollId = GeneratedColumn( - 'poll_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _replyCountMeta = - const VerificationMeta('replyCount'); - @override - late final GeneratedColumn replyCount = GeneratedColumn( - 'reply_count', aliasedName, true, - type: DriftSqlType.int, requiredDuringInsert: false); - static const VerificationMeta _showInChannelMeta = - const VerificationMeta('showInChannel'); - @override - late final GeneratedColumn showInChannel = GeneratedColumn( - 'show_in_channel', aliasedName, true, - type: DriftSqlType.bool, - requiredDuringInsert: false, defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("show_in_channel" IN (0, 1))')); - static const VerificationMeta _shadowedMeta = - const VerificationMeta('shadowed'); + 'REFERENCES channels (cid) ON DELETE CASCADE')); + static const VerificationMeta _messageIdMeta = + const VerificationMeta('messageId'); @override - late final GeneratedColumn shadowed = GeneratedColumn( - 'shadowed', aliasedName, false, - type: DriftSqlType.bool, + late final GeneratedColumn messageId = GeneratedColumn( + 'message_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("shadowed" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _commandMeta = - const VerificationMeta('command'); - @override - late final GeneratedColumn command = GeneratedColumn( - 'command', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _localCreatedAtMeta = - const VerificationMeta('localCreatedAt'); - @override - late final GeneratedColumn localCreatedAt = - GeneratedColumn('local_created_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _remoteCreatedAtMeta = - const VerificationMeta('remoteCreatedAt'); - @override - late final GeneratedColumn remoteCreatedAt = - GeneratedColumn('remote_created_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _localUpdatedAtMeta = - const VerificationMeta('localUpdatedAt'); - @override - late final GeneratedColumn localUpdatedAt = - GeneratedColumn('local_updated_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _remoteUpdatedAtMeta = - const VerificationMeta('remoteUpdatedAt'); - @override - late final GeneratedColumn remoteUpdatedAt = - GeneratedColumn('remote_updated_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _localDeletedAtMeta = - const VerificationMeta('localDeletedAt'); - @override - late final GeneratedColumn localDeletedAt = - GeneratedColumn('local_deleted_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _remoteDeletedAtMeta = - const VerificationMeta('remoteDeletedAt'); - @override - late final GeneratedColumn remoteDeletedAt = - GeneratedColumn('remote_deleted_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _messageTextUpdatedAtMeta = - const VerificationMeta('messageTextUpdatedAt'); - @override - late final GeneratedColumn messageTextUpdatedAt = - GeneratedColumn('message_text_updated_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES messages (id) ON DELETE CASCADE')); static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); @override late final GeneratedColumn userId = GeneratedColumn( 'user_id', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _pinnedMeta = const VerificationMeta('pinned'); - @override - late final GeneratedColumn pinned = GeneratedColumn( - 'pinned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("pinned" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _pinnedAtMeta = - const VerificationMeta('pinnedAt'); - @override - late final GeneratedColumn pinnedAt = GeneratedColumn( - 'pinned_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _pinExpiresMeta = - const VerificationMeta('pinExpires'); - @override - late final GeneratedColumn pinExpires = GeneratedColumn( - 'pin_expires', aliasedName, true, + static const VerificationMeta _latitudeMeta = + const VerificationMeta('latitude'); + @override + late final GeneratedColumn latitude = GeneratedColumn( + 'latitude', aliasedName, false, + type: DriftSqlType.double, requiredDuringInsert: true); + static const VerificationMeta _longitudeMeta = + const VerificationMeta('longitude'); + @override + late final GeneratedColumn longitude = GeneratedColumn( + 'longitude', aliasedName, false, + type: DriftSqlType.double, requiredDuringInsert: true); + static const VerificationMeta _createdByDeviceIdMeta = + const VerificationMeta('createdByDeviceId'); + @override + late final GeneratedColumn createdByDeviceId = + GeneratedColumn('created_by_device_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _endAtMeta = const VerificationMeta('endAt'); + @override + late final GeneratedColumn endAt = GeneratedColumn( + 'end_at', aliasedName, true, type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _pinnedByUserIdMeta = - const VerificationMeta('pinnedByUserId'); - @override - late final GeneratedColumn pinnedByUserId = GeneratedColumn( - 'pinned_by_user_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _channelCidMeta = - const VerificationMeta('channelCid'); - @override - late final GeneratedColumn channelCid = GeneratedColumn( - 'channel_cid', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - @override - late final GeneratedColumnWithTypeConverter?, String> - i18n = GeneratedColumn('i18n', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $PinnedMessagesTable.$converteri18n); - @override - late final GeneratedColumnWithTypeConverter?, String> - restrictedVisibility = GeneratedColumn( - 'restricted_visibility', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $PinnedMessagesTable.$converterrestrictedVisibilityn); - static const VerificationMeta _draftMessageIdMeta = - const VerificationMeta('draftMessageId'); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); @override - late final GeneratedColumn draftMessageId = GeneratedColumn( - 'draft_message_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); @override - late final GeneratedColumnWithTypeConverter?, String> - extraData = GeneratedColumn('extra_data', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $PinnedMessagesTable.$converterextraDatan); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); @override List get $columns => [ - id, - messageText, - attachments, - state, - type, - mentionedUsers, - reactionGroups, - parentId, - quotedMessageId, - pollId, - replyCount, - showInChannel, - shadowed, - command, - localCreatedAt, - remoteCreatedAt, - localUpdatedAt, - remoteUpdatedAt, - localDeletedAt, - remoteDeletedAt, - messageTextUpdatedAt, - userId, - pinned, - pinnedAt, - pinExpires, - pinnedByUserId, channelCid, - i18n, - restrictedVisibility, - draftMessageId, - extraData + messageId, + userId, + latitude, + longitude, + createdByDeviceId, + endAt, + createdAt, + updatedAt ]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'pinned_messages'; + static const String $name = 'locations'; @override - VerificationContext validateIntegrity( - Insertable instance, + 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')) { + if (data.containsKey('channel_cid')) { context.handle( - _messageTextMeta, - messageText.isAcceptableOrUnknown( - data['message_text']!, _messageTextMeta)); - } - if (data.containsKey('state')) { - context.handle( - _stateMeta, state.isAcceptableOrUnknown(data['state']!, _stateMeta)); - } else if (isInserting) { - context.missing(_stateMeta); - } - if (data.containsKey('type')) { - context.handle( - _typeMeta, type.isAcceptableOrUnknown(data['type']!, _typeMeta)); - } - 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('poll_id')) { - context.handle(_pollIdMeta, - pollId.isAcceptableOrUnknown(data['poll_id']!, _pollIdMeta)); - } - 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('local_created_at')) { - context.handle( - _localCreatedAtMeta, - localCreatedAt.isAcceptableOrUnknown( - data['local_created_at']!, _localCreatedAtMeta)); - } - if (data.containsKey('remote_created_at')) { - context.handle( - _remoteCreatedAtMeta, - remoteCreatedAt.isAcceptableOrUnknown( - data['remote_created_at']!, _remoteCreatedAtMeta)); - } - if (data.containsKey('local_updated_at')) { - context.handle( - _localUpdatedAtMeta, - localUpdatedAt.isAcceptableOrUnknown( - data['local_updated_at']!, _localUpdatedAtMeta)); - } - if (data.containsKey('remote_updated_at')) { - context.handle( - _remoteUpdatedAtMeta, - remoteUpdatedAt.isAcceptableOrUnknown( - data['remote_updated_at']!, _remoteUpdatedAtMeta)); - } - if (data.containsKey('local_deleted_at')) { - context.handle( - _localDeletedAtMeta, - localDeletedAt.isAcceptableOrUnknown( - data['local_deleted_at']!, _localDeletedAtMeta)); - } - if (data.containsKey('remote_deleted_at')) { - context.handle( - _remoteDeletedAtMeta, - remoteDeletedAt.isAcceptableOrUnknown( - data['remote_deleted_at']!, _remoteDeletedAtMeta)); + _channelCidMeta, + channelCid.isAcceptableOrUnknown( + data['channel_cid']!, _channelCidMeta)); } - if (data.containsKey('message_text_updated_at')) { - context.handle( - _messageTextUpdatedAtMeta, - messageTextUpdatedAt.isAcceptableOrUnknown( - data['message_text_updated_at']!, _messageTextUpdatedAtMeta)); + if (data.containsKey('message_id')) { + context.handle(_messageIdMeta, + messageId.isAcceptableOrUnknown(data['message_id']!, _messageIdMeta)); } if (data.containsKey('user_id')) { context.handle(_userIdMeta, userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta)); } - if (data.containsKey('pinned')) { - context.handle(_pinnedMeta, - pinned.isAcceptableOrUnknown(data['pinned']!, _pinnedMeta)); + if (data.containsKey('latitude')) { + context.handle(_latitudeMeta, + latitude.isAcceptableOrUnknown(data['latitude']!, _latitudeMeta)); + } else if (isInserting) { + context.missing(_latitudeMeta); } - if (data.containsKey('pinned_at')) { - context.handle(_pinnedAtMeta, - pinnedAt.isAcceptableOrUnknown(data['pinned_at']!, _pinnedAtMeta)); + if (data.containsKey('longitude')) { + context.handle(_longitudeMeta, + longitude.isAcceptableOrUnknown(data['longitude']!, _longitudeMeta)); + } else if (isInserting) { + context.missing(_longitudeMeta); } - if (data.containsKey('pin_expires')) { + if (data.containsKey('created_by_device_id')) { context.handle( - _pinExpiresMeta, - pinExpires.isAcceptableOrUnknown( - data['pin_expires']!, _pinExpiresMeta)); + _createdByDeviceIdMeta, + createdByDeviceId.isAcceptableOrUnknown( + data['created_by_device_id']!, _createdByDeviceIdMeta)); + } else if (isInserting) { + context.missing(_createdByDeviceIdMeta); } - if (data.containsKey('pinned_by_user_id')) { + if (data.containsKey('end_at')) { context.handle( - _pinnedByUserIdMeta, - pinnedByUserId.isAcceptableOrUnknown( - data['pinned_by_user_id']!, _pinnedByUserIdMeta)); + _endAtMeta, endAt.isAcceptableOrUnknown(data['end_at']!, _endAtMeta)); } - if (data.containsKey('channel_cid')) { - context.handle( - _channelCidMeta, - channelCid.isAcceptableOrUnknown( - data['channel_cid']!, _channelCidMeta)); - } else if (isInserting) { - context.missing(_channelCidMeta); + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); } - if (data.containsKey('draft_message_id')) { - context.handle( - _draftMessageIdMeta, - draftMessageId.isAcceptableOrUnknown( - data['draft_message_id']!, _draftMessageIdMeta)); + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); } return context; } @override - Set get $primaryKey => {id}; + Set get $primaryKey => {messageId}; @override - PinnedMessageEntity map(Map data, {String? tablePrefix}) { + LocationEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return PinnedMessageEntity( - id: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}id'])!, - messageText: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}message_text']), - attachments: $PinnedMessagesTable.$converterattachments.fromSql( - attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}attachments'])!), - state: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}state'])!, - type: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}type'])!, - mentionedUsers: $PinnedMessagesTable.$convertermentionedUsers.fromSql( - attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}mentioned_users'])!), - reactionGroups: $PinnedMessagesTable.$converterreactionGroupsn.fromSql( - attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}reaction_groups'])), - parentId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}parent_id']), - quotedMessageId: attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}quoted_message_id']), - pollId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}poll_id']), - replyCount: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}reply_count']), - showInChannel: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}show_in_channel']), - shadowed: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}shadowed'])!, - command: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}command']), - localCreatedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}local_created_at']), - remoteCreatedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}remote_created_at']), - localUpdatedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}local_updated_at']), - remoteUpdatedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}remote_updated_at']), - localDeletedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}local_deleted_at']), - remoteDeletedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}remote_deleted_at']), - messageTextUpdatedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, - data['${effectivePrefix}message_text_updated_at']), + return LocationEntity( + channelCid: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}channel_cid']), + messageId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}message_id']), userId: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}user_id']), - pinned: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}pinned'])!, - pinnedAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}pinned_at']), - pinExpires: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}pin_expires']), - pinnedByUserId: attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}pinned_by_user_id']), - channelCid: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}channel_cid'])!, - i18n: $PinnedMessagesTable.$converteri18n.fromSql(attachedDatabase - .typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}i18n'])), - restrictedVisibility: $PinnedMessagesTable.$converterrestrictedVisibilityn - .fromSql(attachedDatabase.typeMapping.read(DriftSqlType.string, - data['${effectivePrefix}restricted_visibility'])), - draftMessageId: attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}draft_message_id']), - extraData: $PinnedMessagesTable.$converterextraDatan.fromSql( - attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), + latitude: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}latitude'])!, + longitude: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}longitude'])!, + createdByDeviceId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}created_by_device_id'])!, + endAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}end_at']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, ); } @override - $PinnedMessagesTable createAlias(String alias) { - return $PinnedMessagesTable(attachedDatabase, alias); + $LocationsTable createAlias(String alias) { + return $LocationsTable(attachedDatabase, alias); } - - static TypeConverter, String> $converterattachments = - ListConverter(); - static TypeConverter, String> $convertermentionedUsers = - ListConverter(); - static TypeConverter, String> - $converterreactionGroups = ReactionGroupsConverter(); - static TypeConverter?, String?> - $converterreactionGroupsn = - NullAwareTypeConverter.wrap($converterreactionGroups); - static TypeConverter?, String?> $converteri18n = - NullableMapConverter(); - static TypeConverter, String> $converterrestrictedVisibility = - ListConverter(); - static TypeConverter?, String?> $converterrestrictedVisibilityn = - NullAwareTypeConverter.wrap($converterrestrictedVisibility); - static TypeConverter, String> $converterextraData = - MapConverter(); - static TypeConverter?, String?> $converterextraDatan = - NullAwareTypeConverter.wrap($converterextraData); } -class PinnedMessageEntity extends DataClass - implements Insertable { - /// The message id - final String id; - - /// The text of this message - final String? messageText; - - /// The list of attachments, either provided by the user - /// or generated from a command or as a result of URL scraping. - final List attachments; - - /// The current state of the message. - final String state; - - /// The message type - final String type; +class LocationEntity extends DataClass implements Insertable { + /// The channel CID where the location is shared + final String? channelCid; - /// The list of user mentioned in the message - final List mentionedUsers; + /// The ID of the message that contains this shared location + final String? messageId; - /// A map describing the reaction group for every reaction - final Map? reactionGroups; + /// The ID of the user who shared the location + final String? userId; - /// The ID of the parent message, if the message is a thread reply. - final String? parentId; + /// The latitude of the shared location + final double latitude; - /// The ID of the quoted message, if the message is a quoted reply. - final String? quotedMessageId; + /// The longitude of the shared location + final double longitude; - /// The ID of the poll, if the message is a poll. - final String? pollId; + /// The ID of the device that created the location + final String createdByDeviceId; - /// Number of replies for this message. - final int? replyCount; + /// The date at which the shared location will end (for live locations) + /// If null, this is a static location + final DateTime? endAt; - /// Check if this message needs to show in the channel. - final bool? showInChannel; + /// The date at which the location was created + final DateTime createdAt; - /// If true the message is shadowed - final bool shadowed; - - /// A used command name. - final String? command; - - /// The DateTime on which the message was created on the client. - final DateTime? localCreatedAt; - - /// The DateTime on which the message was created on the server. - final DateTime? remoteCreatedAt; - - /// The DateTime on which the message was updated on the client. - final DateTime? localUpdatedAt; - - /// The DateTime on which the message was updated on the server. - final DateTime? remoteUpdatedAt; - - /// The DateTime on which the message was deleted on the client. - final DateTime? localDeletedAt; - - /// The DateTime on which the message was deleted on the server. - final DateTime? remoteDeletedAt; - - /// The DateTime at which the message text was edited - final DateTime? messageTextUpdatedAt; - - /// Id of the User who sent the message - final String? userId; - - /// Whether the message is pinned or not - final bool pinned; - - /// The DateTime at which the message was pinned - final DateTime? pinnedAt; - - /// The DateTime on which the message pin expires - final DateTime? pinExpires; - - /// Id of the User who pinned the message - final String? pinnedByUserId; - - /// The channel cid of which this message is part of - final String channelCid; - - /// A Map of [messageText] translations. - final Map? i18n; - - /// The list of user ids that should be able to see the message. - final List? restrictedVisibility; - - /// Id of the draft message if this message is a parent message. - final String? draftMessageId; - - /// Message custom extraData - final Map? extraData; - const PinnedMessageEntity( - {required this.id, - this.messageText, - required this.attachments, - required this.state, - required this.type, - required this.mentionedUsers, - this.reactionGroups, - this.parentId, - this.quotedMessageId, - this.pollId, - this.replyCount, - this.showInChannel, - required this.shadowed, - this.command, - this.localCreatedAt, - this.remoteCreatedAt, - this.localUpdatedAt, - this.remoteUpdatedAt, - this.localDeletedAt, - this.remoteDeletedAt, - this.messageTextUpdatedAt, + /// The date at which the location was last updated + final DateTime updatedAt; + const LocationEntity( + {this.channelCid, + this.messageId, this.userId, - required this.pinned, - this.pinnedAt, - this.pinExpires, - this.pinnedByUserId, - required this.channelCid, - this.i18n, - this.restrictedVisibility, - this.draftMessageId, - this.extraData}); + required this.latitude, + required this.longitude, + required this.createdByDeviceId, + this.endAt, + required this.createdAt, + required this.updatedAt}); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['id'] = Variable(id); - if (!nullToAbsent || messageText != null) { - map['message_text'] = Variable(messageText); - } - { - map['attachments'] = Variable( - $PinnedMessagesTable.$converterattachments.toSql(attachments)); - } - map['state'] = Variable(state); - map['type'] = Variable(type); - { - map['mentioned_users'] = Variable( - $PinnedMessagesTable.$convertermentionedUsers.toSql(mentionedUsers)); - } - if (!nullToAbsent || reactionGroups != null) { - map['reaction_groups'] = Variable( - $PinnedMessagesTable.$converterreactionGroupsn.toSql(reactionGroups)); - } - if (!nullToAbsent || parentId != null) { - map['parent_id'] = Variable(parentId); - } - if (!nullToAbsent || quotedMessageId != null) { - map['quoted_message_id'] = Variable(quotedMessageId); - } - if (!nullToAbsent || pollId != null) { - map['poll_id'] = Variable(pollId); - } - if (!nullToAbsent || replyCount != null) { - map['reply_count'] = Variable(replyCount); - } - if (!nullToAbsent || showInChannel != null) { - map['show_in_channel'] = Variable(showInChannel); - } - map['shadowed'] = Variable(shadowed); - if (!nullToAbsent || command != null) { - map['command'] = Variable(command); - } - if (!nullToAbsent || localCreatedAt != null) { - map['local_created_at'] = Variable(localCreatedAt); - } - if (!nullToAbsent || remoteCreatedAt != null) { - map['remote_created_at'] = Variable(remoteCreatedAt); - } - if (!nullToAbsent || localUpdatedAt != null) { - map['local_updated_at'] = Variable(localUpdatedAt); - } - if (!nullToAbsent || remoteUpdatedAt != null) { - map['remote_updated_at'] = Variable(remoteUpdatedAt); - } - if (!nullToAbsent || localDeletedAt != null) { - map['local_deleted_at'] = Variable(localDeletedAt); - } - if (!nullToAbsent || remoteDeletedAt != null) { - map['remote_deleted_at'] = Variable(remoteDeletedAt); + if (!nullToAbsent || channelCid != null) { + map['channel_cid'] = Variable(channelCid); } - if (!nullToAbsent || messageTextUpdatedAt != null) { - map['message_text_updated_at'] = Variable(messageTextUpdatedAt); + if (!nullToAbsent || messageId != null) { + map['message_id'] = Variable(messageId); } if (!nullToAbsent || userId != null) { map['user_id'] = Variable(userId); } - map['pinned'] = Variable(pinned); - if (!nullToAbsent || pinnedAt != null) { - map['pinned_at'] = Variable(pinnedAt); - } - if (!nullToAbsent || pinExpires != null) { - map['pin_expires'] = Variable(pinExpires); - } - if (!nullToAbsent || pinnedByUserId != null) { - map['pinned_by_user_id'] = Variable(pinnedByUserId); - } - map['channel_cid'] = Variable(channelCid); - if (!nullToAbsent || i18n != null) { - map['i18n'] = - Variable($PinnedMessagesTable.$converteri18n.toSql(i18n)); - } - if (!nullToAbsent || restrictedVisibility != null) { - map['restricted_visibility'] = Variable($PinnedMessagesTable - .$converterrestrictedVisibilityn - .toSql(restrictedVisibility)); - } - if (!nullToAbsent || draftMessageId != null) { - map['draft_message_id'] = Variable(draftMessageId); - } - if (!nullToAbsent || extraData != null) { - map['extra_data'] = Variable( - $PinnedMessagesTable.$converterextraDatan.toSql(extraData)); + map['latitude'] = Variable(latitude); + map['longitude'] = Variable(longitude); + map['created_by_device_id'] = Variable(createdByDeviceId); + if (!nullToAbsent || endAt != null) { + map['end_at'] = Variable(endAt); } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); return map; } - factory PinnedMessageEntity.fromJson(Map json, + factory LocationEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return PinnedMessageEntity( - id: serializer.fromJson(json['id']), - messageText: serializer.fromJson(json['messageText']), - attachments: serializer.fromJson>(json['attachments']), - state: serializer.fromJson(json['state']), - type: serializer.fromJson(json['type']), - mentionedUsers: serializer.fromJson>(json['mentionedUsers']), - reactionGroups: serializer - .fromJson?>(json['reactionGroups']), - parentId: serializer.fromJson(json['parentId']), - quotedMessageId: serializer.fromJson(json['quotedMessageId']), - pollId: serializer.fromJson(json['pollId']), - replyCount: serializer.fromJson(json['replyCount']), - showInChannel: serializer.fromJson(json['showInChannel']), - shadowed: serializer.fromJson(json['shadowed']), - command: serializer.fromJson(json['command']), - localCreatedAt: serializer.fromJson(json['localCreatedAt']), - remoteCreatedAt: serializer.fromJson(json['remoteCreatedAt']), - localUpdatedAt: serializer.fromJson(json['localUpdatedAt']), - remoteUpdatedAt: serializer.fromJson(json['remoteUpdatedAt']), - localDeletedAt: serializer.fromJson(json['localDeletedAt']), - remoteDeletedAt: serializer.fromJson(json['remoteDeletedAt']), - messageTextUpdatedAt: - serializer.fromJson(json['messageTextUpdatedAt']), + return LocationEntity( + channelCid: serializer.fromJson(json['channelCid']), + messageId: serializer.fromJson(json['messageId']), userId: serializer.fromJson(json['userId']), - pinned: serializer.fromJson(json['pinned']), - pinnedAt: serializer.fromJson(json['pinnedAt']), - pinExpires: serializer.fromJson(json['pinExpires']), - pinnedByUserId: serializer.fromJson(json['pinnedByUserId']), - channelCid: serializer.fromJson(json['channelCid']), - i18n: serializer.fromJson?>(json['i18n']), - restrictedVisibility: - serializer.fromJson?>(json['restrictedVisibility']), - draftMessageId: serializer.fromJson(json['draftMessageId']), - extraData: serializer.fromJson?>(json['extraData']), + latitude: serializer.fromJson(json['latitude']), + longitude: serializer.fromJson(json['longitude']), + createdByDeviceId: serializer.fromJson(json['createdByDeviceId']), + endAt: serializer.fromJson(json['endAt']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), ); } @override Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'id': serializer.toJson(id), - 'messageText': serializer.toJson(messageText), - 'attachments': serializer.toJson>(attachments), - 'state': serializer.toJson(state), - 'type': serializer.toJson(type), - 'mentionedUsers': serializer.toJson>(mentionedUsers), - 'reactionGroups': - serializer.toJson?>(reactionGroups), - 'parentId': serializer.toJson(parentId), - 'quotedMessageId': serializer.toJson(quotedMessageId), - 'pollId': serializer.toJson(pollId), - 'replyCount': serializer.toJson(replyCount), - 'showInChannel': serializer.toJson(showInChannel), - 'shadowed': serializer.toJson(shadowed), - 'command': serializer.toJson(command), - 'localCreatedAt': serializer.toJson(localCreatedAt), - 'remoteCreatedAt': serializer.toJson(remoteCreatedAt), - 'localUpdatedAt': serializer.toJson(localUpdatedAt), - 'remoteUpdatedAt': serializer.toJson(remoteUpdatedAt), - 'localDeletedAt': serializer.toJson(localDeletedAt), - 'remoteDeletedAt': serializer.toJson(remoteDeletedAt), - 'messageTextUpdatedAt': - serializer.toJson(messageTextUpdatedAt), + 'channelCid': serializer.toJson(channelCid), + 'messageId': serializer.toJson(messageId), 'userId': serializer.toJson(userId), - 'pinned': serializer.toJson(pinned), - 'pinnedAt': serializer.toJson(pinnedAt), - 'pinExpires': serializer.toJson(pinExpires), - 'pinnedByUserId': serializer.toJson(pinnedByUserId), - 'channelCid': serializer.toJson(channelCid), - 'i18n': serializer.toJson?>(i18n), - 'restrictedVisibility': - serializer.toJson?>(restrictedVisibility), - 'draftMessageId': serializer.toJson(draftMessageId), - 'extraData': serializer.toJson?>(extraData), + 'latitude': serializer.toJson(latitude), + 'longitude': serializer.toJson(longitude), + 'createdByDeviceId': serializer.toJson(createdByDeviceId), + 'endAt': serializer.toJson(endAt), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), }; } - PinnedMessageEntity copyWith( - {String? id, - Value messageText = const Value.absent(), - List? attachments, - String? state, - String? type, - List? mentionedUsers, - Value?> reactionGroups = - const Value.absent(), - Value parentId = const Value.absent(), - Value quotedMessageId = const Value.absent(), - Value pollId = const Value.absent(), - Value replyCount = const Value.absent(), - Value showInChannel = const Value.absent(), - bool? shadowed, - Value command = const Value.absent(), - Value localCreatedAt = const Value.absent(), - Value remoteCreatedAt = const Value.absent(), - Value localUpdatedAt = const Value.absent(), - Value remoteUpdatedAt = const Value.absent(), - Value localDeletedAt = const Value.absent(), - Value remoteDeletedAt = const Value.absent(), - Value messageTextUpdatedAt = const Value.absent(), + LocationEntity copyWith( + {Value channelCid = const Value.absent(), + Value messageId = const Value.absent(), Value userId = const Value.absent(), - bool? pinned, - Value pinnedAt = const Value.absent(), - Value pinExpires = const Value.absent(), - Value pinnedByUserId = const Value.absent(), - String? channelCid, - Value?> i18n = const Value.absent(), - Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), - Value?> extraData = const Value.absent()}) => - PinnedMessageEntity( - id: id ?? this.id, - messageText: messageText.present ? messageText.value : this.messageText, - attachments: attachments ?? this.attachments, - state: state ?? this.state, - type: type ?? this.type, - mentionedUsers: mentionedUsers ?? this.mentionedUsers, - reactionGroups: - reactionGroups.present ? reactionGroups.value : this.reactionGroups, - parentId: parentId.present ? parentId.value : this.parentId, - quotedMessageId: quotedMessageId.present - ? quotedMessageId.value - : this.quotedMessageId, - pollId: pollId.present ? pollId.value : this.pollId, - replyCount: replyCount.present ? replyCount.value : this.replyCount, - showInChannel: - showInChannel.present ? showInChannel.value : this.showInChannel, - shadowed: shadowed ?? this.shadowed, - command: command.present ? command.value : this.command, - localCreatedAt: - localCreatedAt.present ? localCreatedAt.value : this.localCreatedAt, - remoteCreatedAt: remoteCreatedAt.present - ? remoteCreatedAt.value - : this.remoteCreatedAt, - localUpdatedAt: - localUpdatedAt.present ? localUpdatedAt.value : this.localUpdatedAt, - remoteUpdatedAt: remoteUpdatedAt.present - ? remoteUpdatedAt.value - : this.remoteUpdatedAt, - localDeletedAt: - localDeletedAt.present ? localDeletedAt.value : this.localDeletedAt, - remoteDeletedAt: remoteDeletedAt.present - ? remoteDeletedAt.value - : this.remoteDeletedAt, - messageTextUpdatedAt: messageTextUpdatedAt.present - ? messageTextUpdatedAt.value - : this.messageTextUpdatedAt, + double? latitude, + double? longitude, + String? createdByDeviceId, + Value endAt = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt}) => + LocationEntity( + channelCid: channelCid.present ? channelCid.value : this.channelCid, + messageId: messageId.present ? messageId.value : this.messageId, userId: userId.present ? userId.value : this.userId, - pinned: pinned ?? this.pinned, - pinnedAt: pinnedAt.present ? pinnedAt.value : this.pinnedAt, - pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires, - pinnedByUserId: - pinnedByUserId.present ? pinnedByUserId.value : this.pinnedByUserId, - channelCid: channelCid ?? this.channelCid, - i18n: i18n.present ? i18n.value : this.i18n, - restrictedVisibility: restrictedVisibility.present - ? restrictedVisibility.value - : this.restrictedVisibility, - draftMessageId: - draftMessageId.present ? draftMessageId.value : this.draftMessageId, - extraData: extraData.present ? extraData.value : this.extraData, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + createdByDeviceId: createdByDeviceId ?? this.createdByDeviceId, + endAt: endAt.present ? endAt.value : this.endAt, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, ); - PinnedMessageEntity copyWithCompanion(PinnedMessagesCompanion data) { - return PinnedMessageEntity( - id: data.id.present ? data.id.value : this.id, - messageText: - data.messageText.present ? data.messageText.value : this.messageText, - attachments: - data.attachments.present ? data.attachments.value : this.attachments, - state: data.state.present ? data.state.value : this.state, - type: data.type.present ? data.type.value : this.type, - mentionedUsers: data.mentionedUsers.present - ? data.mentionedUsers.value - : this.mentionedUsers, - reactionGroups: data.reactionGroups.present - ? data.reactionGroups.value - : this.reactionGroups, - parentId: data.parentId.present ? data.parentId.value : this.parentId, - quotedMessageId: data.quotedMessageId.present - ? data.quotedMessageId.value - : this.quotedMessageId, - pollId: data.pollId.present ? data.pollId.value : this.pollId, - replyCount: - data.replyCount.present ? data.replyCount.value : this.replyCount, - showInChannel: data.showInChannel.present - ? data.showInChannel.value - : this.showInChannel, - shadowed: data.shadowed.present ? data.shadowed.value : this.shadowed, - command: data.command.present ? data.command.value : this.command, - localCreatedAt: data.localCreatedAt.present - ? data.localCreatedAt.value - : this.localCreatedAt, - remoteCreatedAt: data.remoteCreatedAt.present - ? data.remoteCreatedAt.value - : this.remoteCreatedAt, - localUpdatedAt: data.localUpdatedAt.present - ? data.localUpdatedAt.value - : this.localUpdatedAt, - remoteUpdatedAt: data.remoteUpdatedAt.present - ? data.remoteUpdatedAt.value - : this.remoteUpdatedAt, - localDeletedAt: data.localDeletedAt.present - ? data.localDeletedAt.value - : this.localDeletedAt, - remoteDeletedAt: data.remoteDeletedAt.present - ? data.remoteDeletedAt.value - : this.remoteDeletedAt, - messageTextUpdatedAt: data.messageTextUpdatedAt.present - ? data.messageTextUpdatedAt.value - : this.messageTextUpdatedAt, - userId: data.userId.present ? data.userId.value : this.userId, - pinned: data.pinned.present ? data.pinned.value : this.pinned, - pinnedAt: data.pinnedAt.present ? data.pinnedAt.value : this.pinnedAt, - pinExpires: - data.pinExpires.present ? data.pinExpires.value : this.pinExpires, - pinnedByUserId: data.pinnedByUserId.present - ? data.pinnedByUserId.value - : this.pinnedByUserId, + LocationEntity copyWithCompanion(LocationsCompanion data) { + return LocationEntity( channelCid: data.channelCid.present ? data.channelCid.value : this.channelCid, - i18n: data.i18n.present ? data.i18n.value : this.i18n, - restrictedVisibility: data.restrictedVisibility.present - ? data.restrictedVisibility.value - : this.restrictedVisibility, - draftMessageId: data.draftMessageId.present - ? data.draftMessageId.value - : this.draftMessageId, - extraData: data.extraData.present ? data.extraData.value : this.extraData, + messageId: data.messageId.present ? data.messageId.value : this.messageId, + userId: data.userId.present ? data.userId.value : this.userId, + latitude: data.latitude.present ? data.latitude.value : this.latitude, + longitude: data.longitude.present ? data.longitude.value : this.longitude, + createdByDeviceId: data.createdByDeviceId.present + ? data.createdByDeviceId.value + : this.createdByDeviceId, + endAt: data.endAt.present ? data.endAt.value : this.endAt, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, ); } @override String toString() { - return (StringBuffer('PinnedMessageEntity(') - ..write('id: $id, ') - ..write('messageText: $messageText, ') - ..write('attachments: $attachments, ') - ..write('state: $state, ') - ..write('type: $type, ') - ..write('mentionedUsers: $mentionedUsers, ') - ..write('reactionGroups: $reactionGroups, ') - ..write('parentId: $parentId, ') - ..write('quotedMessageId: $quotedMessageId, ') - ..write('pollId: $pollId, ') - ..write('replyCount: $replyCount, ') - ..write('showInChannel: $showInChannel, ') - ..write('shadowed: $shadowed, ') - ..write('command: $command, ') - ..write('localCreatedAt: $localCreatedAt, ') - ..write('remoteCreatedAt: $remoteCreatedAt, ') - ..write('localUpdatedAt: $localUpdatedAt, ') - ..write('remoteUpdatedAt: $remoteUpdatedAt, ') - ..write('localDeletedAt: $localDeletedAt, ') - ..write('remoteDeletedAt: $remoteDeletedAt, ') - ..write('messageTextUpdatedAt: $messageTextUpdatedAt, ') - ..write('userId: $userId, ') - ..write('pinned: $pinned, ') - ..write('pinnedAt: $pinnedAt, ') - ..write('pinExpires: $pinExpires, ') - ..write('pinnedByUserId: $pinnedByUserId, ') + return (StringBuffer('LocationEntity(') ..write('channelCid: $channelCid, ') - ..write('i18n: $i18n, ') - ..write('restrictedVisibility: $restrictedVisibility, ') - ..write('draftMessageId: $draftMessageId, ') - ..write('extraData: $extraData') + ..write('messageId: $messageId, ') + ..write('userId: $userId, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('createdByDeviceId: $createdByDeviceId, ') + ..write('endAt: $endAt, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') ..write(')')) .toString(); } @override - int get hashCode => Object.hashAll([ - id, - messageText, - attachments, - state, - type, - mentionedUsers, - reactionGroups, - parentId, - quotedMessageId, - pollId, - replyCount, - showInChannel, - shadowed, - command, - localCreatedAt, - remoteCreatedAt, - localUpdatedAt, - remoteUpdatedAt, - localDeletedAt, - remoteDeletedAt, - messageTextUpdatedAt, - userId, - pinned, - pinnedAt, - pinExpires, - pinnedByUserId, - channelCid, - i18n, - restrictedVisibility, - draftMessageId, - extraData - ]); + int get hashCode => Object.hash(channelCid, messageId, userId, latitude, + longitude, createdByDeviceId, endAt, createdAt, updatedAt); @override bool operator ==(Object other) => identical(this, other) || - (other is PinnedMessageEntity && - other.id == this.id && - other.messageText == this.messageText && - other.attachments == this.attachments && - other.state == this.state && - other.type == this.type && - other.mentionedUsers == this.mentionedUsers && - other.reactionGroups == this.reactionGroups && - other.parentId == this.parentId && - other.quotedMessageId == this.quotedMessageId && - other.pollId == this.pollId && - other.replyCount == this.replyCount && - other.showInChannel == this.showInChannel && - other.shadowed == this.shadowed && - other.command == this.command && - other.localCreatedAt == this.localCreatedAt && - other.remoteCreatedAt == this.remoteCreatedAt && - other.localUpdatedAt == this.localUpdatedAt && - other.remoteUpdatedAt == this.remoteUpdatedAt && - other.localDeletedAt == this.localDeletedAt && - other.remoteDeletedAt == this.remoteDeletedAt && - other.messageTextUpdatedAt == this.messageTextUpdatedAt && - other.userId == this.userId && - other.pinned == this.pinned && - other.pinnedAt == this.pinnedAt && - other.pinExpires == this.pinExpires && - other.pinnedByUserId == this.pinnedByUserId && + (other is LocationEntity && other.channelCid == this.channelCid && - other.i18n == this.i18n && - other.restrictedVisibility == this.restrictedVisibility && - other.draftMessageId == this.draftMessageId && - other.extraData == this.extraData); + other.messageId == this.messageId && + other.userId == this.userId && + other.latitude == this.latitude && + other.longitude == this.longitude && + other.createdByDeviceId == this.createdByDeviceId && + other.endAt == this.endAt && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt); } -class PinnedMessagesCompanion extends UpdateCompanion { - final Value id; - final Value messageText; - final Value> attachments; - final Value state; - final Value type; - final Value> mentionedUsers; - final Value?> reactionGroups; - final Value parentId; - final Value quotedMessageId; - final Value pollId; - final Value replyCount; - final Value showInChannel; - final Value shadowed; - final Value command; - final Value localCreatedAt; - final Value remoteCreatedAt; - final Value localUpdatedAt; - final Value remoteUpdatedAt; - final Value localDeletedAt; - final Value remoteDeletedAt; - final Value messageTextUpdatedAt; +class LocationsCompanion extends UpdateCompanion { + final Value channelCid; + final Value messageId; final Value userId; - final Value pinned; - final Value pinnedAt; - final Value pinExpires; - final Value pinnedByUserId; - final Value channelCid; - final Value?> i18n; - final Value?> restrictedVisibility; - final Value draftMessageId; - final Value?> extraData; + final Value latitude; + final Value longitude; + final Value createdByDeviceId; + final Value endAt; + final Value createdAt; + final Value updatedAt; final Value rowid; - const PinnedMessagesCompanion({ - this.id = const Value.absent(), - this.messageText = const Value.absent(), - this.attachments = const Value.absent(), - this.state = const Value.absent(), - this.type = const Value.absent(), - this.mentionedUsers = const Value.absent(), - this.reactionGroups = const Value.absent(), - this.parentId = const Value.absent(), - this.quotedMessageId = const Value.absent(), - this.pollId = const Value.absent(), - this.replyCount = const Value.absent(), - this.showInChannel = const Value.absent(), - this.shadowed = const Value.absent(), - this.command = const Value.absent(), - this.localCreatedAt = const Value.absent(), - this.remoteCreatedAt = const Value.absent(), - this.localUpdatedAt = const Value.absent(), - this.remoteUpdatedAt = const Value.absent(), - this.localDeletedAt = const Value.absent(), - this.remoteDeletedAt = const Value.absent(), - this.messageTextUpdatedAt = const Value.absent(), - this.userId = const Value.absent(), - this.pinned = const Value.absent(), - this.pinnedAt = const Value.absent(), - this.pinExpires = const Value.absent(), - this.pinnedByUserId = const Value.absent(), + const LocationsCompanion({ this.channelCid = const Value.absent(), - this.i18n = const Value.absent(), - this.restrictedVisibility = const Value.absent(), - this.draftMessageId = const Value.absent(), - this.extraData = const Value.absent(), + this.messageId = const Value.absent(), + this.userId = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.createdByDeviceId = const Value.absent(), + this.endAt = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.rowid = const Value.absent(), }); - PinnedMessagesCompanion.insert({ - required String id, - this.messageText = const Value.absent(), - required List attachments, - required String state, - this.type = const Value.absent(), - required List mentionedUsers, - this.reactionGroups = const Value.absent(), - this.parentId = const Value.absent(), - this.quotedMessageId = const Value.absent(), - this.pollId = const Value.absent(), - this.replyCount = const Value.absent(), - this.showInChannel = const Value.absent(), - this.shadowed = const Value.absent(), - this.command = const Value.absent(), - this.localCreatedAt = const Value.absent(), - this.remoteCreatedAt = const Value.absent(), - this.localUpdatedAt = const Value.absent(), - this.remoteUpdatedAt = const Value.absent(), - this.localDeletedAt = const Value.absent(), - this.remoteDeletedAt = const Value.absent(), - this.messageTextUpdatedAt = const Value.absent(), + LocationsCompanion.insert({ + this.channelCid = const Value.absent(), + this.messageId = const Value.absent(), this.userId = const Value.absent(), - this.pinned = const Value.absent(), - this.pinnedAt = const Value.absent(), - this.pinExpires = const Value.absent(), - this.pinnedByUserId = const Value.absent(), - required String channelCid, - this.i18n = const Value.absent(), - this.restrictedVisibility = const Value.absent(), - this.draftMessageId = const Value.absent(), - this.extraData = const Value.absent(), + required double latitude, + required double longitude, + required String createdByDeviceId, + this.endAt = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.rowid = const Value.absent(), - }) : id = Value(id), - attachments = Value(attachments), - state = Value(state), - mentionedUsers = Value(mentionedUsers), - channelCid = Value(channelCid); - static Insertable custom({ - Expression? id, - Expression? messageText, - Expression? attachments, - Expression? state, - Expression? type, - Expression? mentionedUsers, - Expression? reactionGroups, - Expression? parentId, - Expression? quotedMessageId, - Expression? pollId, - Expression? replyCount, - Expression? showInChannel, - Expression? shadowed, - Expression? command, - Expression? localCreatedAt, - Expression? remoteCreatedAt, - Expression? localUpdatedAt, - Expression? remoteUpdatedAt, - Expression? localDeletedAt, - Expression? remoteDeletedAt, - Expression? messageTextUpdatedAt, - Expression? userId, - Expression? pinned, - Expression? pinnedAt, - Expression? pinExpires, - Expression? pinnedByUserId, + }) : latitude = Value(latitude), + longitude = Value(longitude), + createdByDeviceId = Value(createdByDeviceId); + static Insertable custom({ Expression? channelCid, - Expression? i18n, - Expression? restrictedVisibility, - Expression? draftMessageId, - Expression? extraData, + Expression? messageId, + Expression? userId, + Expression? latitude, + Expression? longitude, + Expression? createdByDeviceId, + Expression? endAt, + Expression? createdAt, + Expression? updatedAt, Expression? rowid, }) { return RawValuesInsertable({ - if (id != null) 'id': id, - if (messageText != null) 'message_text': messageText, - if (attachments != null) 'attachments': attachments, - if (state != null) 'state': state, - if (type != null) 'type': type, - if (mentionedUsers != null) 'mentioned_users': mentionedUsers, - if (reactionGroups != null) 'reaction_groups': reactionGroups, - if (parentId != null) 'parent_id': parentId, - if (quotedMessageId != null) 'quoted_message_id': quotedMessageId, - if (pollId != null) 'poll_id': pollId, - if (replyCount != null) 'reply_count': replyCount, - if (showInChannel != null) 'show_in_channel': showInChannel, - if (shadowed != null) 'shadowed': shadowed, - if (command != null) 'command': command, - if (localCreatedAt != null) 'local_created_at': localCreatedAt, - if (remoteCreatedAt != null) 'remote_created_at': remoteCreatedAt, - if (localUpdatedAt != null) 'local_updated_at': localUpdatedAt, - if (remoteUpdatedAt != null) 'remote_updated_at': remoteUpdatedAt, - if (localDeletedAt != null) 'local_deleted_at': localDeletedAt, - if (remoteDeletedAt != null) 'remote_deleted_at': remoteDeletedAt, - if (messageTextUpdatedAt != null) - 'message_text_updated_at': messageTextUpdatedAt, - if (userId != null) 'user_id': userId, - if (pinned != null) 'pinned': pinned, - if (pinnedAt != null) 'pinned_at': pinnedAt, - if (pinExpires != null) 'pin_expires': pinExpires, - if (pinnedByUserId != null) 'pinned_by_user_id': pinnedByUserId, if (channelCid != null) 'channel_cid': channelCid, - if (i18n != null) 'i18n': i18n, - if (restrictedVisibility != null) - 'restricted_visibility': restrictedVisibility, - if (draftMessageId != null) 'draft_message_id': draftMessageId, - if (extraData != null) 'extra_data': extraData, + if (messageId != null) 'message_id': messageId, + if (userId != null) 'user_id': userId, + if (latitude != null) 'latitude': latitude, + if (longitude != null) 'longitude': longitude, + if (createdByDeviceId != null) 'created_by_device_id': createdByDeviceId, + if (endAt != null) 'end_at': endAt, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, if (rowid != null) 'rowid': rowid, }); } - PinnedMessagesCompanion copyWith( - {Value? id, - Value? messageText, - Value>? attachments, - Value? state, - Value? type, - Value>? mentionedUsers, - Value?>? reactionGroups, - Value? parentId, - Value? quotedMessageId, - Value? pollId, - Value? replyCount, - Value? showInChannel, - Value? shadowed, - Value? command, - Value? localCreatedAt, - Value? remoteCreatedAt, - Value? localUpdatedAt, - Value? remoteUpdatedAt, - Value? localDeletedAt, - Value? remoteDeletedAt, - Value? messageTextUpdatedAt, + LocationsCompanion copyWith( + {Value? channelCid, + Value? messageId, Value? userId, - Value? pinned, - Value? pinnedAt, - Value? pinExpires, - Value? pinnedByUserId, - Value? channelCid, - Value?>? i18n, - Value?>? restrictedVisibility, - Value? draftMessageId, - Value?>? extraData, + Value? latitude, + Value? longitude, + Value? createdByDeviceId, + Value? endAt, + Value? createdAt, + Value? updatedAt, Value? rowid}) { - return PinnedMessagesCompanion( - id: id ?? this.id, - messageText: messageText ?? this.messageText, - attachments: attachments ?? this.attachments, - state: state ?? this.state, - type: type ?? this.type, - mentionedUsers: mentionedUsers ?? this.mentionedUsers, - reactionGroups: reactionGroups ?? this.reactionGroups, - parentId: parentId ?? this.parentId, - quotedMessageId: quotedMessageId ?? this.quotedMessageId, - pollId: pollId ?? this.pollId, - replyCount: replyCount ?? this.replyCount, - showInChannel: showInChannel ?? this.showInChannel, - shadowed: shadowed ?? this.shadowed, - command: command ?? this.command, - localCreatedAt: localCreatedAt ?? this.localCreatedAt, - remoteCreatedAt: remoteCreatedAt ?? this.remoteCreatedAt, - localUpdatedAt: localUpdatedAt ?? this.localUpdatedAt, - remoteUpdatedAt: remoteUpdatedAt ?? this.remoteUpdatedAt, - localDeletedAt: localDeletedAt ?? this.localDeletedAt, - remoteDeletedAt: remoteDeletedAt ?? this.remoteDeletedAt, - messageTextUpdatedAt: messageTextUpdatedAt ?? this.messageTextUpdatedAt, - userId: userId ?? this.userId, - pinned: pinned ?? this.pinned, - pinnedAt: pinnedAt ?? this.pinnedAt, - pinExpires: pinExpires ?? this.pinExpires, - pinnedByUserId: pinnedByUserId ?? this.pinnedByUserId, + return LocationsCompanion( channelCid: channelCid ?? this.channelCid, - i18n: i18n ?? this.i18n, - restrictedVisibility: restrictedVisibility ?? this.restrictedVisibility, - draftMessageId: draftMessageId ?? this.draftMessageId, - extraData: extraData ?? this.extraData, + messageId: messageId ?? this.messageId, + userId: userId ?? this.userId, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + createdByDeviceId: createdByDeviceId ?? this.createdByDeviceId, + endAt: endAt ?? this.endAt, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, rowid: rowid ?? this.rowid, ); } @@ -4111,108 +3235,32 @@ class PinnedMessagesCompanion extends UpdateCompanion { @override Map toColumns(bool nullToAbsent) { final map = {}; - if (id.present) { - map['id'] = Variable(id.value); + if (channelCid.present) { + map['channel_cid'] = Variable(channelCid.value); } - if (messageText.present) { - map['message_text'] = Variable(messageText.value); + if (messageId.present) { + map['message_id'] = Variable(messageId.value); } - if (attachments.present) { - map['attachments'] = Variable( - $PinnedMessagesTable.$converterattachments.toSql(attachments.value)); + if (userId.present) { + map['user_id'] = Variable(userId.value); } - if (state.present) { - map['state'] = Variable(state.value); + if (latitude.present) { + map['latitude'] = Variable(latitude.value); } - if (type.present) { - map['type'] = Variable(type.value); + if (longitude.present) { + map['longitude'] = Variable(longitude.value); } - if (mentionedUsers.present) { - map['mentioned_users'] = Variable($PinnedMessagesTable - .$convertermentionedUsers - .toSql(mentionedUsers.value)); - } - if (reactionGroups.present) { - map['reaction_groups'] = Variable($PinnedMessagesTable - .$converterreactionGroupsn - .toSql(reactionGroups.value)); - } - if (parentId.present) { - map['parent_id'] = Variable(parentId.value); - } - if (quotedMessageId.present) { - map['quoted_message_id'] = Variable(quotedMessageId.value); - } - if (pollId.present) { - map['poll_id'] = Variable(pollId.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 (localCreatedAt.present) { - map['local_created_at'] = Variable(localCreatedAt.value); - } - if (remoteCreatedAt.present) { - map['remote_created_at'] = Variable(remoteCreatedAt.value); - } - if (localUpdatedAt.present) { - map['local_updated_at'] = Variable(localUpdatedAt.value); - } - if (remoteUpdatedAt.present) { - map['remote_updated_at'] = Variable(remoteUpdatedAt.value); - } - if (localDeletedAt.present) { - map['local_deleted_at'] = Variable(localDeletedAt.value); - } - if (remoteDeletedAt.present) { - map['remote_deleted_at'] = Variable(remoteDeletedAt.value); - } - if (messageTextUpdatedAt.present) { - map['message_text_updated_at'] = - Variable(messageTextUpdatedAt.value); - } - if (userId.present) { - map['user_id'] = Variable(userId.value); - } - if (pinned.present) { - map['pinned'] = Variable(pinned.value); - } - if (pinnedAt.present) { - map['pinned_at'] = Variable(pinnedAt.value); - } - if (pinExpires.present) { - map['pin_expires'] = Variable(pinExpires.value); - } - if (pinnedByUserId.present) { - map['pinned_by_user_id'] = Variable(pinnedByUserId.value); - } - if (channelCid.present) { - map['channel_cid'] = Variable(channelCid.value); - } - if (i18n.present) { - map['i18n'] = Variable( - $PinnedMessagesTable.$converteri18n.toSql(i18n.value)); + if (createdByDeviceId.present) { + map['created_by_device_id'] = Variable(createdByDeviceId.value); } - if (restrictedVisibility.present) { - map['restricted_visibility'] = Variable($PinnedMessagesTable - .$converterrestrictedVisibilityn - .toSql(restrictedVisibility.value)); + if (endAt.present) { + map['end_at'] = Variable(endAt.value); } - if (draftMessageId.present) { - map['draft_message_id'] = Variable(draftMessageId.value); + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); } - if (extraData.present) { - map['extra_data'] = Variable( - $PinnedMessagesTable.$converterextraDatan.toSql(extraData.value)); + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -4222,203 +3270,266 @@ class PinnedMessagesCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('PinnedMessagesCompanion(') - ..write('id: $id, ') - ..write('messageText: $messageText, ') - ..write('attachments: $attachments, ') - ..write('state: $state, ') - ..write('type: $type, ') - ..write('mentionedUsers: $mentionedUsers, ') - ..write('reactionGroups: $reactionGroups, ') - ..write('parentId: $parentId, ') - ..write('quotedMessageId: $quotedMessageId, ') - ..write('pollId: $pollId, ') - ..write('replyCount: $replyCount, ') - ..write('showInChannel: $showInChannel, ') - ..write('shadowed: $shadowed, ') - ..write('command: $command, ') - ..write('localCreatedAt: $localCreatedAt, ') - ..write('remoteCreatedAt: $remoteCreatedAt, ') - ..write('localUpdatedAt: $localUpdatedAt, ') - ..write('remoteUpdatedAt: $remoteUpdatedAt, ') - ..write('localDeletedAt: $localDeletedAt, ') - ..write('remoteDeletedAt: $remoteDeletedAt, ') - ..write('messageTextUpdatedAt: $messageTextUpdatedAt, ') - ..write('userId: $userId, ') - ..write('pinned: $pinned, ') - ..write('pinnedAt: $pinnedAt, ') - ..write('pinExpires: $pinExpires, ') - ..write('pinnedByUserId: $pinnedByUserId, ') + return (StringBuffer('LocationsCompanion(') ..write('channelCid: $channelCid, ') - ..write('i18n: $i18n, ') - ..write('restrictedVisibility: $restrictedVisibility, ') - ..write('draftMessageId: $draftMessageId, ') - ..write('extraData: $extraData, ') + ..write('messageId: $messageId, ') + ..write('userId: $userId, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('createdByDeviceId: $createdByDeviceId, ') + ..write('endAt: $endAt, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } -class $PollsTable extends Polls with TableInfo<$PollsTable, PollEntity> { +class $PinnedMessagesTable extends PinnedMessages + with TableInfo<$PinnedMessagesTable, PinnedMessageEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $PollsTable(this.attachedDatabase, [this._alias]); + $PinnedMessagesTable(this.attachedDatabase, [this._alias]); static const VerificationMeta _idMeta = const VerificationMeta('id'); @override late final GeneratedColumn id = GeneratedColumn( 'id', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _nameMeta = const VerificationMeta('name'); - @override - late final GeneratedColumn name = GeneratedColumn( - 'name', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _descriptionMeta = - const VerificationMeta('description'); + static const VerificationMeta _messageTextMeta = + const VerificationMeta('messageText'); @override - late final GeneratedColumn description = GeneratedColumn( - 'description', aliasedName, true, + late final GeneratedColumn messageText = GeneratedColumn( + 'message_text', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false); @override - late final GeneratedColumnWithTypeConverter, String> options = - GeneratedColumn('options', aliasedName, false, + late final GeneratedColumnWithTypeConverter, String> + attachments = GeneratedColumn('attachments', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true) - .withConverter>($PollsTable.$converteroptions); + .withConverter>( + $PinnedMessagesTable.$converterattachments); + static const VerificationMeta _stateMeta = const VerificationMeta('state'); @override - late final GeneratedColumnWithTypeConverter - votingVisibility = GeneratedColumn( - 'voting_visibility', aliasedName, false, - type: DriftSqlType.string, - requiredDuringInsert: false, - defaultValue: const Constant('public')) - .withConverter( - $PollsTable.$convertervotingVisibility); - static const VerificationMeta _enforceUniqueVoteMeta = - const VerificationMeta('enforceUniqueVote'); + late final GeneratedColumn state = GeneratedColumn( + 'state', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _typeMeta = const VerificationMeta('type'); @override - late final GeneratedColumn enforceUniqueVote = GeneratedColumn( - 'enforce_unique_vote', aliasedName, false, - type: DriftSqlType.bool, + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("enforce_unique_vote" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _maxVotesAllowedMeta = - const VerificationMeta('maxVotesAllowed'); + defaultValue: const Constant('regular')); @override - late final GeneratedColumn maxVotesAllowed = GeneratedColumn( - 'max_votes_allowed', aliasedName, true, - type: DriftSqlType.int, requiredDuringInsert: false); - static const VerificationMeta _allowUserSuggestedOptionsMeta = - const VerificationMeta('allowUserSuggestedOptions'); + late final GeneratedColumnWithTypeConverter, String> + mentionedUsers = GeneratedColumn( + 'mentioned_users', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter>( + $PinnedMessagesTable.$convertermentionedUsers); @override - late final GeneratedColumn allowUserSuggestedOptions = - GeneratedColumn('allow_user_suggested_options', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("allow_user_suggested_options" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _allowAnswersMeta = - const VerificationMeta('allowAnswers'); + late final GeneratedColumnWithTypeConverter?, + String> reactionGroups = GeneratedColumn( + 'reaction_groups', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $PinnedMessagesTable.$converterreactionGroupsn); + static const VerificationMeta _parentIdMeta = + const VerificationMeta('parentId'); @override - late final GeneratedColumn allowAnswers = GeneratedColumn( - 'allow_answers', aliasedName, false, + late final GeneratedColumn parentId = GeneratedColumn( + 'parent_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _quotedMessageIdMeta = + const VerificationMeta('quotedMessageId'); + @override + late final GeneratedColumn quotedMessageId = GeneratedColumn( + 'quoted_message_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _pollIdMeta = const VerificationMeta('pollId'); + @override + late final GeneratedColumn pollId = GeneratedColumn( + 'poll_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _replyCountMeta = + const VerificationMeta('replyCount'); + @override + late final GeneratedColumn replyCount = GeneratedColumn( + 'reply_count', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + static const VerificationMeta _showInChannelMeta = + const VerificationMeta('showInChannel'); + @override + late final GeneratedColumn showInChannel = GeneratedColumn( + 'show_in_channel', aliasedName, true, type: DriftSqlType.bool, requiredDuringInsert: false, defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("allow_answers" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _isClosedMeta = - const VerificationMeta('isClosed'); + 'CHECK ("show_in_channel" IN (0, 1))')); + static const VerificationMeta _shadowedMeta = + const VerificationMeta('shadowed'); @override - late final GeneratedColumn isClosed = GeneratedColumn( - 'is_closed', aliasedName, false, + late final GeneratedColumn shadowed = GeneratedColumn( + 'shadowed', aliasedName, false, type: DriftSqlType.bool, requiredDuringInsert: false, defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("is_closed" IN (0, 1))'), + GeneratedColumn.constraintIsAlways('CHECK ("shadowed" IN (0, 1))'), defaultValue: const Constant(false)); - static const VerificationMeta _answersCountMeta = - const VerificationMeta('answersCount'); + static const VerificationMeta _commandMeta = + const VerificationMeta('command'); @override - late final GeneratedColumn answersCount = GeneratedColumn( - 'answers_count', aliasedName, false, - type: DriftSqlType.int, - requiredDuringInsert: false, - defaultValue: const Constant(0)); + late final GeneratedColumn command = GeneratedColumn( + 'command', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _localCreatedAtMeta = + const VerificationMeta('localCreatedAt'); @override - late final GeneratedColumnWithTypeConverter, String> - voteCountsByOption = GeneratedColumn( - 'vote_counts_by_option', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true) - .withConverter>( - $PollsTable.$convertervoteCountsByOption); - static const VerificationMeta _voteCountMeta = - const VerificationMeta('voteCount'); + late final GeneratedColumn localCreatedAt = + GeneratedColumn('local_created_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _remoteCreatedAtMeta = + const VerificationMeta('remoteCreatedAt'); @override - late final GeneratedColumn voteCount = GeneratedColumn( - 'vote_count', aliasedName, false, - type: DriftSqlType.int, - requiredDuringInsert: false, - defaultValue: const Constant(0)); - static const VerificationMeta _createdByIdMeta = - const VerificationMeta('createdById'); + late final GeneratedColumn remoteCreatedAt = + GeneratedColumn('remote_created_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _localUpdatedAtMeta = + const VerificationMeta('localUpdatedAt'); @override - late final GeneratedColumn createdById = GeneratedColumn( - 'created_by_id', aliasedName, true, + late final GeneratedColumn localUpdatedAt = + GeneratedColumn('local_updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _remoteUpdatedAtMeta = + const VerificationMeta('remoteUpdatedAt'); + @override + late final GeneratedColumn remoteUpdatedAt = + GeneratedColumn('remote_updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _localDeletedAtMeta = + const VerificationMeta('localDeletedAt'); + @override + late final GeneratedColumn localDeletedAt = + GeneratedColumn('local_deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _remoteDeletedAtMeta = + const VerificationMeta('remoteDeletedAt'); + @override + late final GeneratedColumn remoteDeletedAt = + GeneratedColumn('remote_deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _messageTextUpdatedAtMeta = + const VerificationMeta('messageTextUpdatedAt'); + @override + late final GeneratedColumn messageTextUpdatedAt = + GeneratedColumn('message_text_updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); + @override + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _createdAtMeta = - const VerificationMeta('createdAt'); + static const VerificationMeta _pinnedMeta = const VerificationMeta('pinned'); @override - late final GeneratedColumn createdAt = GeneratedColumn( - 'created_at', aliasedName, false, - type: DriftSqlType.dateTime, + late final GeneratedColumn pinned = GeneratedColumn( + 'pinned', aliasedName, false, + type: DriftSqlType.bool, requiredDuringInsert: false, - defaultValue: currentDateAndTime); - static const VerificationMeta _updatedAtMeta = - const VerificationMeta('updatedAt'); + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("pinned" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _pinnedAtMeta = + const VerificationMeta('pinnedAt'); @override - late final GeneratedColumn updatedAt = GeneratedColumn( - 'updated_at', aliasedName, false, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: currentDateAndTime); + late final GeneratedColumn pinnedAt = GeneratedColumn( + 'pinned_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _pinExpiresMeta = + const VerificationMeta('pinExpires'); + @override + late final GeneratedColumn pinExpires = GeneratedColumn( + 'pin_expires', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _pinnedByUserIdMeta = + const VerificationMeta('pinnedByUserId'); + @override + late final GeneratedColumn pinnedByUserId = GeneratedColumn( + 'pinned_by_user_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _channelCidMeta = + const VerificationMeta('channelCid'); + @override + late final GeneratedColumn channelCid = GeneratedColumn( + 'channel_cid', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + late final GeneratedColumnWithTypeConverter?, String> + i18n = GeneratedColumn('i18n', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $PinnedMessagesTable.$converteri18n); + @override + late final GeneratedColumnWithTypeConverter?, String> + restrictedVisibility = GeneratedColumn( + 'restricted_visibility', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $PinnedMessagesTable.$converterrestrictedVisibilityn); + static const VerificationMeta _draftMessageIdMeta = + const VerificationMeta('draftMessageId'); + @override + late final GeneratedColumn draftMessageId = GeneratedColumn( + 'draft_message_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); @override late final GeneratedColumnWithTypeConverter?, String> extraData = GeneratedColumn('extra_data', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false) .withConverter?>( - $PollsTable.$converterextraDatan); + $PinnedMessagesTable.$converterextraDatan); @override List get $columns => [ id, - name, - description, - options, - votingVisibility, - enforceUniqueVote, - maxVotesAllowed, - allowUserSuggestedOptions, - allowAnswers, - isClosed, - answersCount, - voteCountsByOption, - voteCount, - createdById, - createdAt, - updatedAt, + messageText, + attachments, + state, + type, + mentionedUsers, + reactionGroups, + parentId, + quotedMessageId, + pollId, + replyCount, + showInChannel, + shadowed, + command, + localCreatedAt, + remoteCreatedAt, + localUpdatedAt, + remoteUpdatedAt, + localDeletedAt, + remoteDeletedAt, + messageTextUpdatedAt, + userId, + pinned, + pinnedAt, + pinExpires, + pinnedByUserId, + channelCid, + i18n, + restrictedVisibility, + draftMessageId, extraData ]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'polls'; + static const String $name = 'pinned_messages'; @override - VerificationContext validateIntegrity(Insertable instance, + VerificationContext validateIntegrity( + Insertable instance, {bool isInserting = false}) { final context = VerificationContext(); final data = instance.toColumns(true); @@ -4427,70 +3538,135 @@ class $PollsTable extends Polls with TableInfo<$PollsTable, PollEntity> { } else if (isInserting) { context.missing(_idMeta); } - if (data.containsKey('name')) { + if (data.containsKey('message_text')) { context.handle( - _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); - } else if (isInserting) { - context.missing(_nameMeta); + _messageTextMeta, + messageText.isAcceptableOrUnknown( + data['message_text']!, _messageTextMeta)); } - if (data.containsKey('description')) { + if (data.containsKey('state')) { context.handle( - _descriptionMeta, - description.isAcceptableOrUnknown( - data['description']!, _descriptionMeta)); + _stateMeta, state.isAcceptableOrUnknown(data['state']!, _stateMeta)); + } else if (isInserting) { + context.missing(_stateMeta); } - if (data.containsKey('enforce_unique_vote')) { + if (data.containsKey('type')) { context.handle( - _enforceUniqueVoteMeta, - enforceUniqueVote.isAcceptableOrUnknown( - data['enforce_unique_vote']!, _enforceUniqueVoteMeta)); + _typeMeta, type.isAcceptableOrUnknown(data['type']!, _typeMeta)); } - if (data.containsKey('max_votes_allowed')) { + if (data.containsKey('parent_id')) { + context.handle(_parentIdMeta, + parentId.isAcceptableOrUnknown(data['parent_id']!, _parentIdMeta)); + } + if (data.containsKey('quoted_message_id')) { context.handle( - _maxVotesAllowedMeta, - maxVotesAllowed.isAcceptableOrUnknown( - data['max_votes_allowed']!, _maxVotesAllowedMeta)); + _quotedMessageIdMeta, + quotedMessageId.isAcceptableOrUnknown( + data['quoted_message_id']!, _quotedMessageIdMeta)); } - if (data.containsKey('allow_user_suggested_options')) { + if (data.containsKey('poll_id')) { + context.handle(_pollIdMeta, + pollId.isAcceptableOrUnknown(data['poll_id']!, _pollIdMeta)); + } + if (data.containsKey('reply_count')) { context.handle( - _allowUserSuggestedOptionsMeta, - allowUserSuggestedOptions.isAcceptableOrUnknown( - data['allow_user_suggested_options']!, - _allowUserSuggestedOptionsMeta)); + _replyCountMeta, + replyCount.isAcceptableOrUnknown( + data['reply_count']!, _replyCountMeta)); } - if (data.containsKey('allow_answers')) { + if (data.containsKey('show_in_channel')) { context.handle( - _allowAnswersMeta, - allowAnswers.isAcceptableOrUnknown( - data['allow_answers']!, _allowAnswersMeta)); + _showInChannelMeta, + showInChannel.isAcceptableOrUnknown( + data['show_in_channel']!, _showInChannelMeta)); } - if (data.containsKey('is_closed')) { - context.handle(_isClosedMeta, - isClosed.isAcceptableOrUnknown(data['is_closed']!, _isClosedMeta)); + if (data.containsKey('shadowed')) { + context.handle(_shadowedMeta, + shadowed.isAcceptableOrUnknown(data['shadowed']!, _shadowedMeta)); } - if (data.containsKey('answers_count')) { - context.handle( - _answersCountMeta, - answersCount.isAcceptableOrUnknown( - data['answers_count']!, _answersCountMeta)); + if (data.containsKey('command')) { + context.handle(_commandMeta, + command.isAcceptableOrUnknown(data['command']!, _commandMeta)); } - if (data.containsKey('vote_count')) { - context.handle(_voteCountMeta, - voteCount.isAcceptableOrUnknown(data['vote_count']!, _voteCountMeta)); + if (data.containsKey('local_created_at')) { + context.handle( + _localCreatedAtMeta, + localCreatedAt.isAcceptableOrUnknown( + data['local_created_at']!, _localCreatedAtMeta)); } - if (data.containsKey('created_by_id')) { + if (data.containsKey('remote_created_at')) { context.handle( - _createdByIdMeta, - createdById.isAcceptableOrUnknown( - data['created_by_id']!, _createdByIdMeta)); + _remoteCreatedAtMeta, + remoteCreatedAt.isAcceptableOrUnknown( + data['remote_created_at']!, _remoteCreatedAtMeta)); } - if (data.containsKey('created_at')) { - context.handle(_createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + if (data.containsKey('local_updated_at')) { + context.handle( + _localUpdatedAtMeta, + localUpdatedAt.isAcceptableOrUnknown( + data['local_updated_at']!, _localUpdatedAtMeta)); } - if (data.containsKey('updated_at')) { - context.handle(_updatedAtMeta, - updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); + if (data.containsKey('remote_updated_at')) { + context.handle( + _remoteUpdatedAtMeta, + remoteUpdatedAt.isAcceptableOrUnknown( + data['remote_updated_at']!, _remoteUpdatedAtMeta)); + } + if (data.containsKey('local_deleted_at')) { + context.handle( + _localDeletedAtMeta, + localDeletedAt.isAcceptableOrUnknown( + data['local_deleted_at']!, _localDeletedAtMeta)); + } + if (data.containsKey('remote_deleted_at')) { + context.handle( + _remoteDeletedAtMeta, + remoteDeletedAt.isAcceptableOrUnknown( + data['remote_deleted_at']!, _remoteDeletedAtMeta)); + } + if (data.containsKey('message_text_updated_at')) { + context.handle( + _messageTextUpdatedAtMeta, + messageTextUpdatedAt.isAcceptableOrUnknown( + data['message_text_updated_at']!, _messageTextUpdatedAtMeta)); + } + if (data.containsKey('user_id')) { + context.handle(_userIdMeta, + userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta)); + } + if (data.containsKey('pinned')) { + context.handle(_pinnedMeta, + pinned.isAcceptableOrUnknown(data['pinned']!, _pinnedMeta)); + } + if (data.containsKey('pinned_at')) { + context.handle(_pinnedAtMeta, + pinnedAt.isAcceptableOrUnknown(data['pinned_at']!, _pinnedAtMeta)); + } + if (data.containsKey('pin_expires')) { + context.handle( + _pinExpiresMeta, + pinExpires.isAcceptableOrUnknown( + data['pin_expires']!, _pinExpiresMeta)); + } + if (data.containsKey('pinned_by_user_id')) { + context.handle( + _pinnedByUserIdMeta, + pinnedByUserId.isAcceptableOrUnknown( + data['pinned_by_user_id']!, _pinnedByUserIdMeta)); + } + if (data.containsKey('channel_cid')) { + context.handle( + _channelCidMeta, + channelCid.isAcceptableOrUnknown( + data['channel_cid']!, _channelCidMeta)); + } else if (isInserting) { + context.missing(_channelCidMeta); + } + if (data.containsKey('draft_message_id')) { + context.handle( + _draftMessageIdMeta, + draftMessageId.isAcceptableOrUnknown( + data['draft_message_id']!, _draftMessageIdMeta)); } return context; } @@ -4498,590 +3674,1023 @@ class $PollsTable extends Polls with TableInfo<$PollsTable, PollEntity> { @override Set get $primaryKey => {id}; @override - PollEntity map(Map data, {String? tablePrefix}) { + PinnedMessageEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return PollEntity( + return PinnedMessageEntity( id: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}id'])!, - name: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}name'])!, - description: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}description']), - options: $PollsTable.$converteroptions.fromSql(attachedDatabase - .typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}options'])!), - votingVisibility: $PollsTable.$convertervotingVisibility.fromSql( - attachedDatabase.typeMapping.read(DriftSqlType.string, - data['${effectivePrefix}voting_visibility'])!), - enforceUniqueVote: attachedDatabase.typeMapping.read( - DriftSqlType.bool, data['${effectivePrefix}enforce_unique_vote'])!, - maxVotesAllowed: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}max_votes_allowed']), - allowUserSuggestedOptions: attachedDatabase.typeMapping.read( - DriftSqlType.bool, - data['${effectivePrefix}allow_user_suggested_options'])!, - allowAnswers: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}allow_answers'])!, - isClosed: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}is_closed'])!, - answersCount: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}answers_count'])!, - voteCountsByOption: $PollsTable.$convertervoteCountsByOption.fromSql( - attachedDatabase.typeMapping.read(DriftSqlType.string, - data['${effectivePrefix}vote_counts_by_option'])!), - voteCount: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}vote_count'])!, - createdById: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}created_by_id']), - createdAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, - updatedAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, - extraData: $PollsTable.$converterextraDatan.fromSql(attachedDatabase + messageText: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}message_text']), + attachments: $PinnedMessagesTable.$converterattachments.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}attachments'])!), + state: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}state'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + mentionedUsers: $PinnedMessagesTable.$convertermentionedUsers.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}mentioned_users'])!), + reactionGroups: $PinnedMessagesTable.$converterreactionGroupsn.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}reaction_groups'])), + parentId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}parent_id']), + quotedMessageId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}quoted_message_id']), + pollId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}poll_id']), + replyCount: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}reply_count']), + showInChannel: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}show_in_channel']), + shadowed: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}shadowed'])!, + command: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}command']), + localCreatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}local_created_at']), + remoteCreatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}remote_created_at']), + localUpdatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}local_updated_at']), + remoteUpdatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}remote_updated_at']), + localDeletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}local_deleted_at']), + remoteDeletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}remote_deleted_at']), + messageTextUpdatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}message_text_updated_at']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}user_id']), + pinned: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}pinned'])!, + pinnedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}pinned_at']), + pinExpires: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}pin_expires']), + pinnedByUserId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}pinned_by_user_id']), + channelCid: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}channel_cid'])!, + i18n: $PinnedMessagesTable.$converteri18n.fromSql(attachedDatabase .typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), + .read(DriftSqlType.string, data['${effectivePrefix}i18n'])), + restrictedVisibility: $PinnedMessagesTable.$converterrestrictedVisibilityn + .fromSql(attachedDatabase.typeMapping.read(DriftSqlType.string, + data['${effectivePrefix}restricted_visibility'])), + draftMessageId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}draft_message_id']), + extraData: $PinnedMessagesTable.$converterextraDatan.fromSql( + attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), ); } @override - $PollsTable createAlias(String alias) { - return $PollsTable(attachedDatabase, alias); + $PinnedMessagesTable createAlias(String alias) { + return $PinnedMessagesTable(attachedDatabase, alias); } - static TypeConverter, String> $converteroptions = + static TypeConverter, String> $converterattachments = ListConverter(); - static TypeConverter $convertervotingVisibility = - const VotingVisibilityConverter(); - static TypeConverter, String> $convertervoteCountsByOption = - MapConverter(); + static TypeConverter, String> $convertermentionedUsers = + ListConverter(); + static TypeConverter, String> + $converterreactionGroups = ReactionGroupsConverter(); + static TypeConverter?, String?> + $converterreactionGroupsn = + NullAwareTypeConverter.wrap($converterreactionGroups); + static TypeConverter?, String?> $converteri18n = + NullableMapConverter(); + static TypeConverter, String> $converterrestrictedVisibility = + ListConverter(); + static TypeConverter?, String?> $converterrestrictedVisibilityn = + NullAwareTypeConverter.wrap($converterrestrictedVisibility); static TypeConverter, String> $converterextraData = MapConverter(); static TypeConverter?, String?> $converterextraDatan = NullAwareTypeConverter.wrap($converterextraData); } -class PollEntity extends DataClass implements Insertable { - /// The unique identifier of the poll. +class PinnedMessageEntity extends DataClass + implements Insertable { + /// The message id final String id; - /// The name of the poll. - final String name; + /// The text of this message + final String? messageText; - /// The description of the poll. - final String? description; + /// The list of attachments, either provided by the user + /// or generated from a command or as a result of URL scraping. + final List attachments; - /// The list of options available for the poll. - final List options; + /// The current state of the message. + final String state; - /// Represents the visibility of the voting process. - /// - /// Defaults to 'public'. - final VotingVisibility votingVisibility; + /// The message type + final String type; - /// If true, only unique votes are allowed. - /// - /// Defaults to false. - final bool enforceUniqueVote; + /// The list of user mentioned in the message + final List mentionedUsers; - /// The maximum number of votes allowed per user. - final int? maxVotesAllowed; + /// A map describing the reaction group for every reaction + final Map? reactionGroups; - /// If true, users can suggest their own options. - /// - /// Defaults to false. - final bool allowUserSuggestedOptions; + /// The ID of the parent message, if the message is a thread reply. + final String? parentId; - /// If true, users can provide their own answers/comments. - /// - /// Defaults to false. - final bool allowAnswers; + /// The ID of the quoted message, if the message is a quoted reply. + final String? quotedMessageId; - /// Indicates if the poll is closed. - final bool isClosed; + /// The ID of the poll, if the message is a poll. + final String? pollId; - /// The total number of answers received by the poll. - final int answersCount; + /// Number of replies for this message. + final int? replyCount; - /// Map of vote counts by option. - final Map voteCountsByOption; + /// Check if this message needs to show in the channel. + final bool? showInChannel; - /// The total number of votes received by the poll. - final int voteCount; + /// If true the message is shadowed + final bool shadowed; - /// The id of the user who created the poll. - final String? createdById; + /// A used command name. + final String? command; - /// The date when the poll was created. - final DateTime createdAt; + /// The DateTime on which the message was created on the client. + final DateTime? localCreatedAt; - /// The date when the poll was last updated. - final DateTime updatedAt; + /// The DateTime on which the message was created on the server. + final DateTime? remoteCreatedAt; - /// Map of custom poll extraData + /// The DateTime on which the message was updated on the client. + final DateTime? localUpdatedAt; + + /// The DateTime on which the message was updated on the server. + final DateTime? remoteUpdatedAt; + + /// The DateTime on which the message was deleted on the client. + final DateTime? localDeletedAt; + + /// The DateTime on which the message was deleted on the server. + final DateTime? remoteDeletedAt; + + /// The DateTime at which the message text was edited + final DateTime? messageTextUpdatedAt; + + /// Id of the User who sent the message + final String? userId; + + /// Whether the message is pinned or not + final bool pinned; + + /// The DateTime at which the message was pinned + final DateTime? pinnedAt; + + /// The DateTime on which the message pin expires + final DateTime? pinExpires; + + /// Id of the User who pinned the message + final String? pinnedByUserId; + + /// The channel cid of which this message is part of + final String channelCid; + + /// A Map of [messageText] translations. + final Map? i18n; + + /// The list of user ids that should be able to see the message. + final List? restrictedVisibility; + + /// Id of the draft message if this message is a parent message. + final String? draftMessageId; + + /// Message custom extraData final Map? extraData; - const PollEntity( + const PinnedMessageEntity( {required this.id, - required this.name, - this.description, - required this.options, - required this.votingVisibility, - required this.enforceUniqueVote, - this.maxVotesAllowed, - required this.allowUserSuggestedOptions, - required this.allowAnswers, - required this.isClosed, - required this.answersCount, - required this.voteCountsByOption, - required this.voteCount, - this.createdById, - required this.createdAt, - required this.updatedAt, + this.messageText, + required this.attachments, + required this.state, + required this.type, + required this.mentionedUsers, + this.reactionGroups, + this.parentId, + this.quotedMessageId, + this.pollId, + this.replyCount, + this.showInChannel, + required this.shadowed, + this.command, + this.localCreatedAt, + this.remoteCreatedAt, + this.localUpdatedAt, + this.remoteUpdatedAt, + this.localDeletedAt, + this.remoteDeletedAt, + this.messageTextUpdatedAt, + this.userId, + required this.pinned, + this.pinnedAt, + this.pinExpires, + this.pinnedByUserId, + required this.channelCid, + this.i18n, + this.restrictedVisibility, + this.draftMessageId, this.extraData}); @override Map toColumns(bool nullToAbsent) { final map = {}; map['id'] = Variable(id); - map['name'] = Variable(name); - if (!nullToAbsent || description != null) { - map['description'] = Variable(description); + if (!nullToAbsent || messageText != null) { + map['message_text'] = Variable(messageText); } { - map['options'] = - Variable($PollsTable.$converteroptions.toSql(options)); + map['attachments'] = Variable( + $PinnedMessagesTable.$converterattachments.toSql(attachments)); } + map['state'] = Variable(state); + map['type'] = Variable(type); { - map['voting_visibility'] = Variable( - $PollsTable.$convertervotingVisibility.toSql(votingVisibility)); + map['mentioned_users'] = Variable( + $PinnedMessagesTable.$convertermentionedUsers.toSql(mentionedUsers)); } - map['enforce_unique_vote'] = Variable(enforceUniqueVote); - if (!nullToAbsent || maxVotesAllowed != null) { - map['max_votes_allowed'] = Variable(maxVotesAllowed); + if (!nullToAbsent || reactionGroups != null) { + map['reaction_groups'] = Variable( + $PinnedMessagesTable.$converterreactionGroupsn.toSql(reactionGroups)); } - map['allow_user_suggested_options'] = - Variable(allowUserSuggestedOptions); - map['allow_answers'] = Variable(allowAnswers); - map['is_closed'] = Variable(isClosed); - map['answers_count'] = Variable(answersCount); - { - map['vote_counts_by_option'] = Variable( - $PollsTable.$convertervoteCountsByOption.toSql(voteCountsByOption)); + if (!nullToAbsent || parentId != null) { + map['parent_id'] = Variable(parentId); } - map['vote_count'] = Variable(voteCount); - if (!nullToAbsent || createdById != null) { - map['created_by_id'] = Variable(createdById); + if (!nullToAbsent || quotedMessageId != null) { + map['quoted_message_id'] = Variable(quotedMessageId); + } + if (!nullToAbsent || pollId != null) { + map['poll_id'] = Variable(pollId); + } + if (!nullToAbsent || replyCount != null) { + map['reply_count'] = Variable(replyCount); + } + if (!nullToAbsent || showInChannel != null) { + map['show_in_channel'] = Variable(showInChannel); + } + map['shadowed'] = Variable(shadowed); + if (!nullToAbsent || command != null) { + map['command'] = Variable(command); + } + if (!nullToAbsent || localCreatedAt != null) { + map['local_created_at'] = Variable(localCreatedAt); + } + if (!nullToAbsent || remoteCreatedAt != null) { + map['remote_created_at'] = Variable(remoteCreatedAt); + } + if (!nullToAbsent || localUpdatedAt != null) { + map['local_updated_at'] = Variable(localUpdatedAt); + } + if (!nullToAbsent || remoteUpdatedAt != null) { + map['remote_updated_at'] = Variable(remoteUpdatedAt); + } + if (!nullToAbsent || localDeletedAt != null) { + map['local_deleted_at'] = Variable(localDeletedAt); + } + if (!nullToAbsent || remoteDeletedAt != null) { + map['remote_deleted_at'] = Variable(remoteDeletedAt); + } + if (!nullToAbsent || messageTextUpdatedAt != null) { + map['message_text_updated_at'] = Variable(messageTextUpdatedAt); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['pinned'] = Variable(pinned); + if (!nullToAbsent || pinnedAt != null) { + map['pinned_at'] = Variable(pinnedAt); + } + if (!nullToAbsent || pinExpires != null) { + map['pin_expires'] = Variable(pinExpires); + } + if (!nullToAbsent || pinnedByUserId != null) { + map['pinned_by_user_id'] = Variable(pinnedByUserId); + } + map['channel_cid'] = Variable(channelCid); + if (!nullToAbsent || i18n != null) { + map['i18n'] = + Variable($PinnedMessagesTable.$converteri18n.toSql(i18n)); + } + if (!nullToAbsent || restrictedVisibility != null) { + map['restricted_visibility'] = Variable($PinnedMessagesTable + .$converterrestrictedVisibilityn + .toSql(restrictedVisibility)); + } + if (!nullToAbsent || draftMessageId != null) { + map['draft_message_id'] = Variable(draftMessageId); } - map['created_at'] = Variable(createdAt); - map['updated_at'] = Variable(updatedAt); if (!nullToAbsent || extraData != null) { - map['extra_data'] = - Variable($PollsTable.$converterextraDatan.toSql(extraData)); + map['extra_data'] = Variable( + $PinnedMessagesTable.$converterextraDatan.toSql(extraData)); } return map; } - factory PollEntity.fromJson(Map json, + factory PinnedMessageEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return PollEntity( + return PinnedMessageEntity( id: serializer.fromJson(json['id']), - name: serializer.fromJson(json['name']), - description: serializer.fromJson(json['description']), - options: serializer.fromJson>(json['options']), - votingVisibility: - serializer.fromJson(json['votingVisibility']), - enforceUniqueVote: serializer.fromJson(json['enforceUniqueVote']), - maxVotesAllowed: serializer.fromJson(json['maxVotesAllowed']), - allowUserSuggestedOptions: - serializer.fromJson(json['allowUserSuggestedOptions']), - allowAnswers: serializer.fromJson(json['allowAnswers']), - isClosed: serializer.fromJson(json['isClosed']), - answersCount: serializer.fromJson(json['answersCount']), - voteCountsByOption: - serializer.fromJson>(json['voteCountsByOption']), - voteCount: serializer.fromJson(json['voteCount']), - createdById: serializer.fromJson(json['createdById']), - createdAt: serializer.fromJson(json['createdAt']), - updatedAt: serializer.fromJson(json['updatedAt']), - extraData: serializer.fromJson?>(json['extraData']), - ); - } - @override - Map toJson({ValueSerializer? serializer}) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return { - 'id': serializer.toJson(id), - 'name': serializer.toJson(name), - 'description': serializer.toJson(description), - 'options': serializer.toJson>(options), - 'votingVisibility': serializer.toJson(votingVisibility), - 'enforceUniqueVote': serializer.toJson(enforceUniqueVote), - 'maxVotesAllowed': serializer.toJson(maxVotesAllowed), - 'allowUserSuggestedOptions': - serializer.toJson(allowUserSuggestedOptions), - 'allowAnswers': serializer.toJson(allowAnswers), - 'isClosed': serializer.toJson(isClosed), - 'answersCount': serializer.toJson(answersCount), - 'voteCountsByOption': - serializer.toJson>(voteCountsByOption), - 'voteCount': serializer.toJson(voteCount), - 'createdById': serializer.toJson(createdById), - 'createdAt': serializer.toJson(createdAt), - 'updatedAt': serializer.toJson(updatedAt), + messageText: serializer.fromJson(json['messageText']), + attachments: serializer.fromJson>(json['attachments']), + state: serializer.fromJson(json['state']), + type: serializer.fromJson(json['type']), + mentionedUsers: serializer.fromJson>(json['mentionedUsers']), + reactionGroups: serializer + .fromJson?>(json['reactionGroups']), + parentId: serializer.fromJson(json['parentId']), + quotedMessageId: serializer.fromJson(json['quotedMessageId']), + pollId: serializer.fromJson(json['pollId']), + replyCount: serializer.fromJson(json['replyCount']), + showInChannel: serializer.fromJson(json['showInChannel']), + shadowed: serializer.fromJson(json['shadowed']), + command: serializer.fromJson(json['command']), + localCreatedAt: serializer.fromJson(json['localCreatedAt']), + remoteCreatedAt: serializer.fromJson(json['remoteCreatedAt']), + localUpdatedAt: serializer.fromJson(json['localUpdatedAt']), + remoteUpdatedAt: serializer.fromJson(json['remoteUpdatedAt']), + localDeletedAt: serializer.fromJson(json['localDeletedAt']), + remoteDeletedAt: serializer.fromJson(json['remoteDeletedAt']), + messageTextUpdatedAt: + serializer.fromJson(json['messageTextUpdatedAt']), + userId: serializer.fromJson(json['userId']), + pinned: serializer.fromJson(json['pinned']), + pinnedAt: serializer.fromJson(json['pinnedAt']), + pinExpires: serializer.fromJson(json['pinExpires']), + pinnedByUserId: serializer.fromJson(json['pinnedByUserId']), + channelCid: serializer.fromJson(json['channelCid']), + i18n: serializer.fromJson?>(json['i18n']), + restrictedVisibility: + serializer.fromJson?>(json['restrictedVisibility']), + draftMessageId: serializer.fromJson(json['draftMessageId']), + extraData: serializer.fromJson?>(json['extraData']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'messageText': serializer.toJson(messageText), + 'attachments': serializer.toJson>(attachments), + 'state': serializer.toJson(state), + 'type': serializer.toJson(type), + 'mentionedUsers': serializer.toJson>(mentionedUsers), + 'reactionGroups': + serializer.toJson?>(reactionGroups), + 'parentId': serializer.toJson(parentId), + 'quotedMessageId': serializer.toJson(quotedMessageId), + 'pollId': serializer.toJson(pollId), + 'replyCount': serializer.toJson(replyCount), + 'showInChannel': serializer.toJson(showInChannel), + 'shadowed': serializer.toJson(shadowed), + 'command': serializer.toJson(command), + 'localCreatedAt': serializer.toJson(localCreatedAt), + 'remoteCreatedAt': serializer.toJson(remoteCreatedAt), + 'localUpdatedAt': serializer.toJson(localUpdatedAt), + 'remoteUpdatedAt': serializer.toJson(remoteUpdatedAt), + 'localDeletedAt': serializer.toJson(localDeletedAt), + 'remoteDeletedAt': serializer.toJson(remoteDeletedAt), + 'messageTextUpdatedAt': + serializer.toJson(messageTextUpdatedAt), + 'userId': serializer.toJson(userId), + 'pinned': serializer.toJson(pinned), + 'pinnedAt': serializer.toJson(pinnedAt), + 'pinExpires': serializer.toJson(pinExpires), + 'pinnedByUserId': serializer.toJson(pinnedByUserId), + 'channelCid': serializer.toJson(channelCid), + 'i18n': serializer.toJson?>(i18n), + 'restrictedVisibility': + serializer.toJson?>(restrictedVisibility), + 'draftMessageId': serializer.toJson(draftMessageId), 'extraData': serializer.toJson?>(extraData), }; } - PollEntity copyWith( + PinnedMessageEntity copyWith( {String? id, - String? name, - Value description = const Value.absent(), - List? options, - VotingVisibility? votingVisibility, - bool? enforceUniqueVote, - Value maxVotesAllowed = const Value.absent(), - bool? allowUserSuggestedOptions, - bool? allowAnswers, - bool? isClosed, - int? answersCount, - Map? voteCountsByOption, - int? voteCount, - Value createdById = const Value.absent(), - DateTime? createdAt, - DateTime? updatedAt, + Value messageText = const Value.absent(), + List? attachments, + String? state, + String? type, + List? mentionedUsers, + Value?> reactionGroups = + const Value.absent(), + Value parentId = const Value.absent(), + Value quotedMessageId = const Value.absent(), + Value pollId = const Value.absent(), + Value replyCount = const Value.absent(), + Value showInChannel = const Value.absent(), + bool? shadowed, + Value command = const Value.absent(), + Value localCreatedAt = const Value.absent(), + Value remoteCreatedAt = const Value.absent(), + Value localUpdatedAt = const Value.absent(), + Value remoteUpdatedAt = const Value.absent(), + Value localDeletedAt = const Value.absent(), + Value remoteDeletedAt = const Value.absent(), + Value messageTextUpdatedAt = const Value.absent(), + Value userId = const Value.absent(), + bool? pinned, + Value pinnedAt = const Value.absent(), + Value pinExpires = const Value.absent(), + Value pinnedByUserId = const Value.absent(), + String? channelCid, + Value?> i18n = const Value.absent(), + Value?> restrictedVisibility = const Value.absent(), + Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent()}) => - PollEntity( + PinnedMessageEntity( id: id ?? this.id, - name: name ?? this.name, - description: description.present ? description.value : this.description, - options: options ?? this.options, - votingVisibility: votingVisibility ?? this.votingVisibility, - enforceUniqueVote: enforceUniqueVote ?? this.enforceUniqueVote, - maxVotesAllowed: maxVotesAllowed.present - ? maxVotesAllowed.value - : this.maxVotesAllowed, - allowUserSuggestedOptions: - allowUserSuggestedOptions ?? this.allowUserSuggestedOptions, - allowAnswers: allowAnswers ?? this.allowAnswers, - isClosed: isClosed ?? this.isClosed, - answersCount: answersCount ?? this.answersCount, - voteCountsByOption: voteCountsByOption ?? this.voteCountsByOption, - voteCount: voteCount ?? this.voteCount, - createdById: createdById.present ? createdById.value : this.createdById, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, + messageText: messageText.present ? messageText.value : this.messageText, + attachments: attachments ?? this.attachments, + state: state ?? this.state, + type: type ?? this.type, + mentionedUsers: mentionedUsers ?? this.mentionedUsers, + reactionGroups: + reactionGroups.present ? reactionGroups.value : this.reactionGroups, + parentId: parentId.present ? parentId.value : this.parentId, + quotedMessageId: quotedMessageId.present + ? quotedMessageId.value + : this.quotedMessageId, + pollId: pollId.present ? pollId.value : this.pollId, + replyCount: replyCount.present ? replyCount.value : this.replyCount, + showInChannel: + showInChannel.present ? showInChannel.value : this.showInChannel, + shadowed: shadowed ?? this.shadowed, + command: command.present ? command.value : this.command, + localCreatedAt: + localCreatedAt.present ? localCreatedAt.value : this.localCreatedAt, + remoteCreatedAt: remoteCreatedAt.present + ? remoteCreatedAt.value + : this.remoteCreatedAt, + localUpdatedAt: + localUpdatedAt.present ? localUpdatedAt.value : this.localUpdatedAt, + remoteUpdatedAt: remoteUpdatedAt.present + ? remoteUpdatedAt.value + : this.remoteUpdatedAt, + localDeletedAt: + localDeletedAt.present ? localDeletedAt.value : this.localDeletedAt, + remoteDeletedAt: remoteDeletedAt.present + ? remoteDeletedAt.value + : this.remoteDeletedAt, + messageTextUpdatedAt: messageTextUpdatedAt.present + ? messageTextUpdatedAt.value + : this.messageTextUpdatedAt, + userId: userId.present ? userId.value : this.userId, + pinned: pinned ?? this.pinned, + pinnedAt: pinnedAt.present ? pinnedAt.value : this.pinnedAt, + pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires, + pinnedByUserId: + pinnedByUserId.present ? pinnedByUserId.value : this.pinnedByUserId, + channelCid: channelCid ?? this.channelCid, + i18n: i18n.present ? i18n.value : this.i18n, + restrictedVisibility: restrictedVisibility.present + ? restrictedVisibility.value + : this.restrictedVisibility, + draftMessageId: + draftMessageId.present ? draftMessageId.value : this.draftMessageId, extraData: extraData.present ? extraData.value : this.extraData, ); - PollEntity copyWithCompanion(PollsCompanion data) { - return PollEntity( + PinnedMessageEntity copyWithCompanion(PinnedMessagesCompanion data) { + return PinnedMessageEntity( id: data.id.present ? data.id.value : this.id, - name: data.name.present ? data.name.value : this.name, - description: - data.description.present ? data.description.value : this.description, - options: data.options.present ? data.options.value : this.options, - votingVisibility: data.votingVisibility.present - ? data.votingVisibility.value - : this.votingVisibility, - enforceUniqueVote: data.enforceUniqueVote.present - ? data.enforceUniqueVote.value - : this.enforceUniqueVote, - maxVotesAllowed: data.maxVotesAllowed.present - ? data.maxVotesAllowed.value - : this.maxVotesAllowed, - allowUserSuggestedOptions: data.allowUserSuggestedOptions.present - ? data.allowUserSuggestedOptions.value - : this.allowUserSuggestedOptions, - allowAnswers: data.allowAnswers.present - ? data.allowAnswers.value - : this.allowAnswers, - isClosed: data.isClosed.present ? data.isClosed.value : this.isClosed, - answersCount: data.answersCount.present - ? data.answersCount.value - : this.answersCount, - voteCountsByOption: data.voteCountsByOption.present - ? data.voteCountsByOption.value - : this.voteCountsByOption, - voteCount: data.voteCount.present ? data.voteCount.value : this.voteCount, - createdById: - data.createdById.present ? data.createdById.value : this.createdById, - createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, - updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, - extraData: data.extraData.present ? data.extraData.value : this.extraData, - ); - } - - @override - String toString() { - return (StringBuffer('PollEntity(') - ..write('id: $id, ') - ..write('name: $name, ') - ..write('description: $description, ') - ..write('options: $options, ') - ..write('votingVisibility: $votingVisibility, ') - ..write('enforceUniqueVote: $enforceUniqueVote, ') - ..write('maxVotesAllowed: $maxVotesAllowed, ') - ..write('allowUserSuggestedOptions: $allowUserSuggestedOptions, ') - ..write('allowAnswers: $allowAnswers, ') - ..write('isClosed: $isClosed, ') - ..write('answersCount: $answersCount, ') - ..write('voteCountsByOption: $voteCountsByOption, ') - ..write('voteCount: $voteCount, ') - ..write('createdById: $createdById, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('extraData: $extraData') - ..write(')')) - .toString(); - } - - @override - int get hashCode => Object.hash( - id, - name, - description, - options, - votingVisibility, - enforceUniqueVote, - maxVotesAllowed, - allowUserSuggestedOptions, - allowAnswers, - isClosed, - answersCount, - voteCountsByOption, - voteCount, - createdById, - createdAt, - updatedAt, - extraData); + messageText: + data.messageText.present ? data.messageText.value : this.messageText, + attachments: + data.attachments.present ? data.attachments.value : this.attachments, + state: data.state.present ? data.state.value : this.state, + type: data.type.present ? data.type.value : this.type, + mentionedUsers: data.mentionedUsers.present + ? data.mentionedUsers.value + : this.mentionedUsers, + reactionGroups: data.reactionGroups.present + ? data.reactionGroups.value + : this.reactionGroups, + parentId: data.parentId.present ? data.parentId.value : this.parentId, + quotedMessageId: data.quotedMessageId.present + ? data.quotedMessageId.value + : this.quotedMessageId, + pollId: data.pollId.present ? data.pollId.value : this.pollId, + replyCount: + data.replyCount.present ? data.replyCount.value : this.replyCount, + showInChannel: data.showInChannel.present + ? data.showInChannel.value + : this.showInChannel, + shadowed: data.shadowed.present ? data.shadowed.value : this.shadowed, + command: data.command.present ? data.command.value : this.command, + localCreatedAt: data.localCreatedAt.present + ? data.localCreatedAt.value + : this.localCreatedAt, + remoteCreatedAt: data.remoteCreatedAt.present + ? data.remoteCreatedAt.value + : this.remoteCreatedAt, + localUpdatedAt: data.localUpdatedAt.present + ? data.localUpdatedAt.value + : this.localUpdatedAt, + remoteUpdatedAt: data.remoteUpdatedAt.present + ? data.remoteUpdatedAt.value + : this.remoteUpdatedAt, + localDeletedAt: data.localDeletedAt.present + ? data.localDeletedAt.value + : this.localDeletedAt, + remoteDeletedAt: data.remoteDeletedAt.present + ? data.remoteDeletedAt.value + : this.remoteDeletedAt, + messageTextUpdatedAt: data.messageTextUpdatedAt.present + ? data.messageTextUpdatedAt.value + : this.messageTextUpdatedAt, + userId: data.userId.present ? data.userId.value : this.userId, + pinned: data.pinned.present ? data.pinned.value : this.pinned, + pinnedAt: data.pinnedAt.present ? data.pinnedAt.value : this.pinnedAt, + pinExpires: + data.pinExpires.present ? data.pinExpires.value : this.pinExpires, + pinnedByUserId: data.pinnedByUserId.present + ? data.pinnedByUserId.value + : this.pinnedByUserId, + channelCid: + data.channelCid.present ? data.channelCid.value : this.channelCid, + i18n: data.i18n.present ? data.i18n.value : this.i18n, + restrictedVisibility: data.restrictedVisibility.present + ? data.restrictedVisibility.value + : this.restrictedVisibility, + draftMessageId: data.draftMessageId.present + ? data.draftMessageId.value + : this.draftMessageId, + extraData: data.extraData.present ? data.extraData.value : this.extraData, + ); + } + + @override + String toString() { + return (StringBuffer('PinnedMessageEntity(') + ..write('id: $id, ') + ..write('messageText: $messageText, ') + ..write('attachments: $attachments, ') + ..write('state: $state, ') + ..write('type: $type, ') + ..write('mentionedUsers: $mentionedUsers, ') + ..write('reactionGroups: $reactionGroups, ') + ..write('parentId: $parentId, ') + ..write('quotedMessageId: $quotedMessageId, ') + ..write('pollId: $pollId, ') + ..write('replyCount: $replyCount, ') + ..write('showInChannel: $showInChannel, ') + ..write('shadowed: $shadowed, ') + ..write('command: $command, ') + ..write('localCreatedAt: $localCreatedAt, ') + ..write('remoteCreatedAt: $remoteCreatedAt, ') + ..write('localUpdatedAt: $localUpdatedAt, ') + ..write('remoteUpdatedAt: $remoteUpdatedAt, ') + ..write('localDeletedAt: $localDeletedAt, ') + ..write('remoteDeletedAt: $remoteDeletedAt, ') + ..write('messageTextUpdatedAt: $messageTextUpdatedAt, ') + ..write('userId: $userId, ') + ..write('pinned: $pinned, ') + ..write('pinnedAt: $pinnedAt, ') + ..write('pinExpires: $pinExpires, ') + ..write('pinnedByUserId: $pinnedByUserId, ') + ..write('channelCid: $channelCid, ') + ..write('i18n: $i18n, ') + ..write('restrictedVisibility: $restrictedVisibility, ') + ..write('draftMessageId: $draftMessageId, ') + ..write('extraData: $extraData') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + id, + messageText, + attachments, + state, + type, + mentionedUsers, + reactionGroups, + parentId, + quotedMessageId, + pollId, + replyCount, + showInChannel, + shadowed, + command, + localCreatedAt, + remoteCreatedAt, + localUpdatedAt, + remoteUpdatedAt, + localDeletedAt, + remoteDeletedAt, + messageTextUpdatedAt, + userId, + pinned, + pinnedAt, + pinExpires, + pinnedByUserId, + channelCid, + i18n, + restrictedVisibility, + draftMessageId, + extraData + ]); @override bool operator ==(Object other) => identical(this, other) || - (other is PollEntity && + (other is PinnedMessageEntity && other.id == this.id && - other.name == this.name && - other.description == this.description && - other.options == this.options && - other.votingVisibility == this.votingVisibility && - other.enforceUniqueVote == this.enforceUniqueVote && - other.maxVotesAllowed == this.maxVotesAllowed && - other.allowUserSuggestedOptions == this.allowUserSuggestedOptions && - other.allowAnswers == this.allowAnswers && - other.isClosed == this.isClosed && - other.answersCount == this.answersCount && - other.voteCountsByOption == this.voteCountsByOption && - other.voteCount == this.voteCount && - other.createdById == this.createdById && - other.createdAt == this.createdAt && - other.updatedAt == this.updatedAt && + other.messageText == this.messageText && + other.attachments == this.attachments && + other.state == this.state && + other.type == this.type && + other.mentionedUsers == this.mentionedUsers && + other.reactionGroups == this.reactionGroups && + other.parentId == this.parentId && + other.quotedMessageId == this.quotedMessageId && + other.pollId == this.pollId && + other.replyCount == this.replyCount && + other.showInChannel == this.showInChannel && + other.shadowed == this.shadowed && + other.command == this.command && + other.localCreatedAt == this.localCreatedAt && + other.remoteCreatedAt == this.remoteCreatedAt && + other.localUpdatedAt == this.localUpdatedAt && + other.remoteUpdatedAt == this.remoteUpdatedAt && + other.localDeletedAt == this.localDeletedAt && + other.remoteDeletedAt == this.remoteDeletedAt && + other.messageTextUpdatedAt == this.messageTextUpdatedAt && + other.userId == this.userId && + other.pinned == this.pinned && + other.pinnedAt == this.pinnedAt && + other.pinExpires == this.pinExpires && + other.pinnedByUserId == this.pinnedByUserId && + other.channelCid == this.channelCid && + other.i18n == this.i18n && + other.restrictedVisibility == this.restrictedVisibility && + other.draftMessageId == this.draftMessageId && other.extraData == this.extraData); } -class PollsCompanion extends UpdateCompanion { +class PinnedMessagesCompanion extends UpdateCompanion { final Value id; - final Value name; - final Value description; - final Value> options; - final Value votingVisibility; - final Value enforceUniqueVote; - final Value maxVotesAllowed; - final Value allowUserSuggestedOptions; - final Value allowAnswers; - final Value isClosed; - final Value answersCount; - final Value> voteCountsByOption; - final Value voteCount; - final Value createdById; - final Value createdAt; - final Value updatedAt; + final Value messageText; + final Value> attachments; + final Value state; + final Value type; + final Value> mentionedUsers; + final Value?> reactionGroups; + final Value parentId; + final Value quotedMessageId; + final Value pollId; + final Value replyCount; + final Value showInChannel; + final Value shadowed; + final Value command; + final Value localCreatedAt; + final Value remoteCreatedAt; + final Value localUpdatedAt; + final Value remoteUpdatedAt; + final Value localDeletedAt; + final Value remoteDeletedAt; + final Value messageTextUpdatedAt; + final Value userId; + final Value pinned; + final Value pinnedAt; + final Value pinExpires; + final Value pinnedByUserId; + final Value channelCid; + final Value?> i18n; + final Value?> restrictedVisibility; + final Value draftMessageId; final Value?> extraData; final Value rowid; - const PollsCompanion({ + const PinnedMessagesCompanion({ this.id = const Value.absent(), - this.name = const Value.absent(), - this.description = const Value.absent(), - this.options = const Value.absent(), - this.votingVisibility = const Value.absent(), - this.enforceUniqueVote = const Value.absent(), - this.maxVotesAllowed = const Value.absent(), - this.allowUserSuggestedOptions = const Value.absent(), - this.allowAnswers = const Value.absent(), - this.isClosed = const Value.absent(), - this.answersCount = const Value.absent(), - this.voteCountsByOption = const Value.absent(), - this.voteCount = const Value.absent(), - this.createdById = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), + this.messageText = const Value.absent(), + this.attachments = const Value.absent(), + this.state = const Value.absent(), + this.type = const Value.absent(), + this.mentionedUsers = const Value.absent(), + this.reactionGroups = const Value.absent(), + this.parentId = const Value.absent(), + this.quotedMessageId = const Value.absent(), + this.pollId = const Value.absent(), + this.replyCount = const Value.absent(), + this.showInChannel = const Value.absent(), + this.shadowed = const Value.absent(), + this.command = const Value.absent(), + this.localCreatedAt = const Value.absent(), + this.remoteCreatedAt = const Value.absent(), + this.localUpdatedAt = const Value.absent(), + this.remoteUpdatedAt = const Value.absent(), + this.localDeletedAt = const Value.absent(), + this.remoteDeletedAt = const Value.absent(), + this.messageTextUpdatedAt = const Value.absent(), + this.userId = const Value.absent(), + this.pinned = const Value.absent(), + this.pinnedAt = const Value.absent(), + this.pinExpires = const Value.absent(), + this.pinnedByUserId = const Value.absent(), + this.channelCid = const Value.absent(), + this.i18n = const Value.absent(), + this.restrictedVisibility = const Value.absent(), + this.draftMessageId = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); - PollsCompanion.insert({ + PinnedMessagesCompanion.insert({ required String id, - required String name, - this.description = const Value.absent(), - required List options, - this.votingVisibility = const Value.absent(), - this.enforceUniqueVote = const Value.absent(), - this.maxVotesAllowed = const Value.absent(), - this.allowUserSuggestedOptions = const Value.absent(), - this.allowAnswers = const Value.absent(), - this.isClosed = const Value.absent(), - this.answersCount = const Value.absent(), - required Map voteCountsByOption, - this.voteCount = const Value.absent(), - this.createdById = const Value.absent(), - this.createdAt = const Value.absent(), - this.updatedAt = const Value.absent(), + this.messageText = const Value.absent(), + required List attachments, + required String state, + this.type = const Value.absent(), + required List mentionedUsers, + this.reactionGroups = const Value.absent(), + this.parentId = const Value.absent(), + this.quotedMessageId = const Value.absent(), + this.pollId = const Value.absent(), + this.replyCount = const Value.absent(), + this.showInChannel = const Value.absent(), + this.shadowed = const Value.absent(), + this.command = const Value.absent(), + this.localCreatedAt = const Value.absent(), + this.remoteCreatedAt = const Value.absent(), + this.localUpdatedAt = const Value.absent(), + this.remoteUpdatedAt = const Value.absent(), + this.localDeletedAt = const Value.absent(), + this.remoteDeletedAt = const Value.absent(), + this.messageTextUpdatedAt = const Value.absent(), + this.userId = const Value.absent(), + this.pinned = const Value.absent(), + this.pinnedAt = const Value.absent(), + this.pinExpires = const Value.absent(), + this.pinnedByUserId = const Value.absent(), + required String channelCid, + this.i18n = const Value.absent(), + this.restrictedVisibility = const Value.absent(), + this.draftMessageId = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }) : id = Value(id), - name = Value(name), - options = Value(options), - voteCountsByOption = Value(voteCountsByOption); - static Insertable custom({ + attachments = Value(attachments), + state = Value(state), + mentionedUsers = Value(mentionedUsers), + channelCid = Value(channelCid); + static Insertable custom({ Expression? id, - Expression? name, - Expression? description, - Expression? options, - Expression? votingVisibility, - Expression? enforceUniqueVote, - Expression? maxVotesAllowed, - Expression? allowUserSuggestedOptions, - Expression? allowAnswers, - Expression? isClosed, - Expression? answersCount, - Expression? voteCountsByOption, - Expression? voteCount, - Expression? createdById, - Expression? createdAt, - Expression? updatedAt, + Expression? messageText, + Expression? attachments, + Expression? state, + Expression? type, + Expression? mentionedUsers, + Expression? reactionGroups, + Expression? parentId, + Expression? quotedMessageId, + Expression? pollId, + Expression? replyCount, + Expression? showInChannel, + Expression? shadowed, + Expression? command, + Expression? localCreatedAt, + Expression? remoteCreatedAt, + Expression? localUpdatedAt, + Expression? remoteUpdatedAt, + Expression? localDeletedAt, + Expression? remoteDeletedAt, + Expression? messageTextUpdatedAt, + Expression? userId, + Expression? pinned, + Expression? pinnedAt, + Expression? pinExpires, + Expression? pinnedByUserId, + Expression? channelCid, + Expression? i18n, + Expression? restrictedVisibility, + Expression? draftMessageId, Expression? extraData, Expression? rowid, }) { return RawValuesInsertable({ if (id != null) 'id': id, - if (name != null) 'name': name, - if (description != null) 'description': description, - if (options != null) 'options': options, - if (votingVisibility != null) 'voting_visibility': votingVisibility, - if (enforceUniqueVote != null) 'enforce_unique_vote': enforceUniqueVote, - if (maxVotesAllowed != null) 'max_votes_allowed': maxVotesAllowed, - if (allowUserSuggestedOptions != null) - 'allow_user_suggested_options': allowUserSuggestedOptions, - if (allowAnswers != null) 'allow_answers': allowAnswers, - if (isClosed != null) 'is_closed': isClosed, - if (answersCount != null) 'answers_count': answersCount, - if (voteCountsByOption != null) - 'vote_counts_by_option': voteCountsByOption, - if (voteCount != null) 'vote_count': voteCount, - if (createdById != null) 'created_by_id': createdById, - if (createdAt != null) 'created_at': createdAt, - if (updatedAt != null) 'updated_at': updatedAt, + if (messageText != null) 'message_text': messageText, + if (attachments != null) 'attachments': attachments, + if (state != null) 'state': state, + if (type != null) 'type': type, + if (mentionedUsers != null) 'mentioned_users': mentionedUsers, + if (reactionGroups != null) 'reaction_groups': reactionGroups, + if (parentId != null) 'parent_id': parentId, + if (quotedMessageId != null) 'quoted_message_id': quotedMessageId, + if (pollId != null) 'poll_id': pollId, + if (replyCount != null) 'reply_count': replyCount, + if (showInChannel != null) 'show_in_channel': showInChannel, + if (shadowed != null) 'shadowed': shadowed, + if (command != null) 'command': command, + if (localCreatedAt != null) 'local_created_at': localCreatedAt, + if (remoteCreatedAt != null) 'remote_created_at': remoteCreatedAt, + if (localUpdatedAt != null) 'local_updated_at': localUpdatedAt, + if (remoteUpdatedAt != null) 'remote_updated_at': remoteUpdatedAt, + if (localDeletedAt != null) 'local_deleted_at': localDeletedAt, + if (remoteDeletedAt != null) 'remote_deleted_at': remoteDeletedAt, + if (messageTextUpdatedAt != null) + 'message_text_updated_at': messageTextUpdatedAt, + if (userId != null) 'user_id': userId, + if (pinned != null) 'pinned': pinned, + if (pinnedAt != null) 'pinned_at': pinnedAt, + if (pinExpires != null) 'pin_expires': pinExpires, + if (pinnedByUserId != null) 'pinned_by_user_id': pinnedByUserId, + if (channelCid != null) 'channel_cid': channelCid, + if (i18n != null) 'i18n': i18n, + if (restrictedVisibility != null) + 'restricted_visibility': restrictedVisibility, + if (draftMessageId != null) 'draft_message_id': draftMessageId, if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, }); } - PollsCompanion copyWith( + PinnedMessagesCompanion copyWith( {Value? id, - Value? name, - Value? description, - Value>? options, - Value? votingVisibility, - Value? enforceUniqueVote, - Value? maxVotesAllowed, - Value? allowUserSuggestedOptions, - Value? allowAnswers, - Value? isClosed, - Value? answersCount, - Value>? voteCountsByOption, - Value? voteCount, - Value? createdById, - Value? createdAt, - Value? updatedAt, + Value? messageText, + Value>? attachments, + Value? state, + Value? type, + Value>? mentionedUsers, + Value?>? reactionGroups, + Value? parentId, + Value? quotedMessageId, + Value? pollId, + Value? replyCount, + Value? showInChannel, + Value? shadowed, + Value? command, + Value? localCreatedAt, + Value? remoteCreatedAt, + Value? localUpdatedAt, + Value? remoteUpdatedAt, + Value? localDeletedAt, + Value? remoteDeletedAt, + Value? messageTextUpdatedAt, + Value? userId, + Value? pinned, + Value? pinnedAt, + Value? pinExpires, + Value? pinnedByUserId, + Value? channelCid, + Value?>? i18n, + Value?>? restrictedVisibility, + Value? draftMessageId, Value?>? extraData, Value? rowid}) { - return PollsCompanion( + return PinnedMessagesCompanion( id: id ?? this.id, - name: name ?? this.name, - description: description ?? this.description, - options: options ?? this.options, - votingVisibility: votingVisibility ?? this.votingVisibility, - enforceUniqueVote: enforceUniqueVote ?? this.enforceUniqueVote, - maxVotesAllowed: maxVotesAllowed ?? this.maxVotesAllowed, - allowUserSuggestedOptions: - allowUserSuggestedOptions ?? this.allowUserSuggestedOptions, - allowAnswers: allowAnswers ?? this.allowAnswers, - isClosed: isClosed ?? this.isClosed, - answersCount: answersCount ?? this.answersCount, - voteCountsByOption: voteCountsByOption ?? this.voteCountsByOption, - voteCount: voteCount ?? this.voteCount, - createdById: createdById ?? this.createdById, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - extraData: extraData ?? this.extraData, - rowid: rowid ?? this.rowid, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (id.present) { - map['id'] = Variable(id.value); - } - if (name.present) { - map['name'] = Variable(name.value); + messageText: messageText ?? this.messageText, + attachments: attachments ?? this.attachments, + state: state ?? this.state, + type: type ?? this.type, + mentionedUsers: mentionedUsers ?? this.mentionedUsers, + reactionGroups: reactionGroups ?? this.reactionGroups, + parentId: parentId ?? this.parentId, + quotedMessageId: quotedMessageId ?? this.quotedMessageId, + pollId: pollId ?? this.pollId, + replyCount: replyCount ?? this.replyCount, + showInChannel: showInChannel ?? this.showInChannel, + shadowed: shadowed ?? this.shadowed, + command: command ?? this.command, + localCreatedAt: localCreatedAt ?? this.localCreatedAt, + remoteCreatedAt: remoteCreatedAt ?? this.remoteCreatedAt, + localUpdatedAt: localUpdatedAt ?? this.localUpdatedAt, + remoteUpdatedAt: remoteUpdatedAt ?? this.remoteUpdatedAt, + localDeletedAt: localDeletedAt ?? this.localDeletedAt, + remoteDeletedAt: remoteDeletedAt ?? this.remoteDeletedAt, + messageTextUpdatedAt: messageTextUpdatedAt ?? this.messageTextUpdatedAt, + userId: userId ?? this.userId, + pinned: pinned ?? this.pinned, + pinnedAt: pinnedAt ?? this.pinnedAt, + pinExpires: pinExpires ?? this.pinExpires, + pinnedByUserId: pinnedByUserId ?? this.pinnedByUserId, + channelCid: channelCid ?? this.channelCid, + i18n: i18n ?? this.i18n, + restrictedVisibility: restrictedVisibility ?? this.restrictedVisibility, + draftMessageId: draftMessageId ?? this.draftMessageId, + extraData: extraData ?? this.extraData, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); } - if (description.present) { - map['description'] = Variable(description.value); + if (messageText.present) { + map['message_text'] = Variable(messageText.value); } - if (options.present) { - map['options'] = - Variable($PollsTable.$converteroptions.toSql(options.value)); + if (attachments.present) { + map['attachments'] = Variable( + $PinnedMessagesTable.$converterattachments.toSql(attachments.value)); } - if (votingVisibility.present) { - map['voting_visibility'] = Variable( - $PollsTable.$convertervotingVisibility.toSql(votingVisibility.value)); + if (state.present) { + map['state'] = Variable(state.value); } - if (enforceUniqueVote.present) { - map['enforce_unique_vote'] = Variable(enforceUniqueVote.value); + if (type.present) { + map['type'] = Variable(type.value); } - if (maxVotesAllowed.present) { - map['max_votes_allowed'] = Variable(maxVotesAllowed.value); + if (mentionedUsers.present) { + map['mentioned_users'] = Variable($PinnedMessagesTable + .$convertermentionedUsers + .toSql(mentionedUsers.value)); } - if (allowUserSuggestedOptions.present) { - map['allow_user_suggested_options'] = - Variable(allowUserSuggestedOptions.value); + if (reactionGroups.present) { + map['reaction_groups'] = Variable($PinnedMessagesTable + .$converterreactionGroupsn + .toSql(reactionGroups.value)); } - if (allowAnswers.present) { - map['allow_answers'] = Variable(allowAnswers.value); + if (parentId.present) { + map['parent_id'] = Variable(parentId.value); } - if (isClosed.present) { - map['is_closed'] = Variable(isClosed.value); + if (quotedMessageId.present) { + map['quoted_message_id'] = Variable(quotedMessageId.value); } - if (answersCount.present) { - map['answers_count'] = Variable(answersCount.value); + if (pollId.present) { + map['poll_id'] = Variable(pollId.value); } - if (voteCountsByOption.present) { - map['vote_counts_by_option'] = Variable($PollsTable - .$convertervoteCountsByOption - .toSql(voteCountsByOption.value)); + if (replyCount.present) { + map['reply_count'] = Variable(replyCount.value); } - if (voteCount.present) { - map['vote_count'] = Variable(voteCount.value); + if (showInChannel.present) { + map['show_in_channel'] = Variable(showInChannel.value); } - if (createdById.present) { - map['created_by_id'] = Variable(createdById.value); + if (shadowed.present) { + map['shadowed'] = Variable(shadowed.value); } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); + if (command.present) { + map['command'] = Variable(command.value); } - if (updatedAt.present) { - map['updated_at'] = Variable(updatedAt.value); + if (localCreatedAt.present) { + map['local_created_at'] = Variable(localCreatedAt.value); + } + if (remoteCreatedAt.present) { + map['remote_created_at'] = Variable(remoteCreatedAt.value); + } + if (localUpdatedAt.present) { + map['local_updated_at'] = Variable(localUpdatedAt.value); + } + if (remoteUpdatedAt.present) { + map['remote_updated_at'] = Variable(remoteUpdatedAt.value); + } + if (localDeletedAt.present) { + map['local_deleted_at'] = Variable(localDeletedAt.value); + } + if (remoteDeletedAt.present) { + map['remote_deleted_at'] = Variable(remoteDeletedAt.value); + } + if (messageTextUpdatedAt.present) { + map['message_text_updated_at'] = + Variable(messageTextUpdatedAt.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (pinned.present) { + map['pinned'] = Variable(pinned.value); + } + if (pinnedAt.present) { + map['pinned_at'] = Variable(pinnedAt.value); + } + if (pinExpires.present) { + map['pin_expires'] = Variable(pinExpires.value); + } + if (pinnedByUserId.present) { + map['pinned_by_user_id'] = Variable(pinnedByUserId.value); + } + if (channelCid.present) { + map['channel_cid'] = Variable(channelCid.value); + } + if (i18n.present) { + map['i18n'] = Variable( + $PinnedMessagesTable.$converteri18n.toSql(i18n.value)); + } + if (restrictedVisibility.present) { + map['restricted_visibility'] = Variable($PinnedMessagesTable + .$converterrestrictedVisibilityn + .toSql(restrictedVisibility.value)); + } + if (draftMessageId.present) { + map['draft_message_id'] = Variable(draftMessageId.value); } if (extraData.present) { map['extra_data'] = Variable( - $PollsTable.$converterextraDatan.toSql(extraData.value)); + $PinnedMessagesTable.$converterextraDatan.toSql(extraData.value)); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -5091,23 +4700,37 @@ class PollsCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('PollsCompanion(') + return (StringBuffer('PinnedMessagesCompanion(') ..write('id: $id, ') - ..write('name: $name, ') - ..write('description: $description, ') - ..write('options: $options, ') - ..write('votingVisibility: $votingVisibility, ') - ..write('enforceUniqueVote: $enforceUniqueVote, ') - ..write('maxVotesAllowed: $maxVotesAllowed, ') - ..write('allowUserSuggestedOptions: $allowUserSuggestedOptions, ') - ..write('allowAnswers: $allowAnswers, ') - ..write('isClosed: $isClosed, ') - ..write('answersCount: $answersCount, ') - ..write('voteCountsByOption: $voteCountsByOption, ') - ..write('voteCount: $voteCount, ') - ..write('createdById: $createdById, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') + ..write('messageText: $messageText, ') + ..write('attachments: $attachments, ') + ..write('state: $state, ') + ..write('type: $type, ') + ..write('mentionedUsers: $mentionedUsers, ') + ..write('reactionGroups: $reactionGroups, ') + ..write('parentId: $parentId, ') + ..write('quotedMessageId: $quotedMessageId, ') + ..write('pollId: $pollId, ') + ..write('replyCount: $replyCount, ') + ..write('showInChannel: $showInChannel, ') + ..write('shadowed: $shadowed, ') + ..write('command: $command, ') + ..write('localCreatedAt: $localCreatedAt, ') + ..write('remoteCreatedAt: $remoteCreatedAt, ') + ..write('localUpdatedAt: $localUpdatedAt, ') + ..write('remoteUpdatedAt: $remoteUpdatedAt, ') + ..write('localDeletedAt: $localDeletedAt, ') + ..write('remoteDeletedAt: $remoteDeletedAt, ') + ..write('messageTextUpdatedAt: $messageTextUpdatedAt, ') + ..write('userId: $userId, ') + ..write('pinned: $pinned, ') + ..write('pinnedAt: $pinnedAt, ') + ..write('pinExpires: $pinExpires, ') + ..write('pinnedByUserId: $pinnedByUserId, ') + ..write('channelCid: $channelCid, ') + ..write('i18n: $i18n, ') + ..write('restrictedVisibility: $restrictedVisibility, ') + ..write('draftMessageId: $draftMessageId, ') ..write('extraData: $extraData, ') ..write('rowid: $rowid') ..write(')')) @@ -5115,87 +4738,229 @@ class PollsCompanion extends UpdateCompanion { } } -class $PollVotesTable extends PollVotes - with TableInfo<$PollVotesTable, PollVoteEntity> { +class $PollsTable extends Polls with TableInfo<$PollsTable, PollEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $PollVotesTable(this.attachedDatabase, [this._alias]); + $PollsTable(this.attachedDatabase, [this._alias]); static const VerificationMeta _idMeta = const VerificationMeta('id'); @override late final GeneratedColumn id = GeneratedColumn( - 'id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _pollIdMeta = const VerificationMeta('pollId'); - @override - late final GeneratedColumn pollId = GeneratedColumn( - 'poll_id', aliasedName, true, - type: DriftSqlType.string, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'REFERENCES polls (id) ON DELETE CASCADE')); - static const VerificationMeta _optionIdMeta = - const VerificationMeta('optionId'); + 'id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); @override - late final GeneratedColumn optionId = GeneratedColumn( - 'option_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _answerTextMeta = - const VerificationMeta('answerText'); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _descriptionMeta = + const VerificationMeta('description'); @override - late final GeneratedColumn answerText = GeneratedColumn( - 'answer_text', aliasedName, true, + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _createdAtMeta = - const VerificationMeta('createdAt'); @override - late final GeneratedColumn createdAt = GeneratedColumn( - 'created_at', aliasedName, false, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: currentDateAndTime); - static const VerificationMeta _updatedAtMeta = - const VerificationMeta('updatedAt'); + late final GeneratedColumnWithTypeConverter, String> options = + GeneratedColumn('options', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter>($PollsTable.$converteroptions); @override - late final GeneratedColumn updatedAt = GeneratedColumn( - 'updated_at', aliasedName, false, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: currentDateAndTime); - static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); + late final GeneratedColumnWithTypeConverter + votingVisibility = GeneratedColumn( + 'voting_visibility', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('public')) + .withConverter( + $PollsTable.$convertervotingVisibility); + static const VerificationMeta _enforceUniqueVoteMeta = + const VerificationMeta('enforceUniqueVote'); @override - late final GeneratedColumn userId = GeneratedColumn( - 'user_id', aliasedName, true, + late final GeneratedColumn enforceUniqueVote = GeneratedColumn( + 'enforce_unique_vote', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("enforce_unique_vote" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _maxVotesAllowedMeta = + const VerificationMeta('maxVotesAllowed'); + @override + late final GeneratedColumn maxVotesAllowed = GeneratedColumn( + 'max_votes_allowed', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + static const VerificationMeta _allowUserSuggestedOptionsMeta = + const VerificationMeta('allowUserSuggestedOptions'); + @override + late final GeneratedColumn allowUserSuggestedOptions = + GeneratedColumn('allow_user_suggested_options', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("allow_user_suggested_options" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _allowAnswersMeta = + const VerificationMeta('allowAnswers'); + @override + late final GeneratedColumn allowAnswers = GeneratedColumn( + 'allow_answers', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("allow_answers" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _isClosedMeta = + const VerificationMeta('isClosed'); + @override + late final GeneratedColumn isClosed = GeneratedColumn( + 'is_closed', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("is_closed" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _answersCountMeta = + const VerificationMeta('answersCount'); + @override + late final GeneratedColumn answersCount = GeneratedColumn( + 'answers_count', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(0)); + @override + late final GeneratedColumnWithTypeConverter, String> + voteCountsByOption = GeneratedColumn( + 'vote_counts_by_option', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter>( + $PollsTable.$convertervoteCountsByOption); + static const VerificationMeta _voteCountMeta = + const VerificationMeta('voteCount'); + @override + late final GeneratedColumn voteCount = GeneratedColumn( + 'vote_count', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(0)); + static const VerificationMeta _createdByIdMeta = + const VerificationMeta('createdById'); + @override + late final GeneratedColumn createdById = GeneratedColumn( + 'created_by_id', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); @override - List get $columns => - [id, pollId, optionId, answerText, createdAt, updatedAt, userId]; + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); + @override + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + late final GeneratedColumnWithTypeConverter?, String> + extraData = GeneratedColumn('extra_data', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $PollsTable.$converterextraDatan); + @override + List get $columns => [ + id, + name, + description, + options, + votingVisibility, + enforceUniqueVote, + maxVotesAllowed, + allowUserSuggestedOptions, + allowAnswers, + isClosed, + answersCount, + voteCountsByOption, + voteCount, + createdById, + createdAt, + updatedAt, + extraData + ]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'poll_votes'; + static const String $name = 'polls'; @override - VerificationContext validateIntegrity(Insertable instance, + 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('poll_id')) { - context.handle(_pollIdMeta, - pollId.isAcceptableOrUnknown(data['poll_id']!, _pollIdMeta)); + if (data.containsKey('name')) { + context.handle( + _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); + } else if (isInserting) { + context.missing(_nameMeta); } - if (data.containsKey('option_id')) { - context.handle(_optionIdMeta, - optionId.isAcceptableOrUnknown(data['option_id']!, _optionIdMeta)); + if (data.containsKey('description')) { + context.handle( + _descriptionMeta, + description.isAcceptableOrUnknown( + data['description']!, _descriptionMeta)); } - if (data.containsKey('answer_text')) { + if (data.containsKey('enforce_unique_vote')) { context.handle( - _answerTextMeta, - answerText.isAcceptableOrUnknown( - data['answer_text']!, _answerTextMeta)); + _enforceUniqueVoteMeta, + enforceUniqueVote.isAcceptableOrUnknown( + data['enforce_unique_vote']!, _enforceUniqueVoteMeta)); + } + if (data.containsKey('max_votes_allowed')) { + context.handle( + _maxVotesAllowedMeta, + maxVotesAllowed.isAcceptableOrUnknown( + data['max_votes_allowed']!, _maxVotesAllowedMeta)); + } + if (data.containsKey('allow_user_suggested_options')) { + context.handle( + _allowUserSuggestedOptionsMeta, + allowUserSuggestedOptions.isAcceptableOrUnknown( + data['allow_user_suggested_options']!, + _allowUserSuggestedOptionsMeta)); + } + if (data.containsKey('allow_answers')) { + context.handle( + _allowAnswersMeta, + allowAnswers.isAcceptableOrUnknown( + data['allow_answers']!, _allowAnswersMeta)); + } + if (data.containsKey('is_closed')) { + context.handle(_isClosedMeta, + isClosed.isAcceptableOrUnknown(data['is_closed']!, _isClosedMeta)); + } + if (data.containsKey('answers_count')) { + context.handle( + _answersCountMeta, + answersCount.isAcceptableOrUnknown( + data['answers_count']!, _answersCountMeta)); + } + if (data.containsKey('vote_count')) { + context.handle(_voteCountMeta, + voteCount.isAcceptableOrUnknown(data['vote_count']!, _voteCountMeta)); + } + if (data.containsKey('created_by_id')) { + context.handle( + _createdByIdMeta, + createdById.isAcceptableOrUnknown( + data['created_by_id']!, _createdByIdMeta)); } if (data.containsKey('created_at')) { context.handle(_createdAtMeta, @@ -5205,255 +4970,533 @@ class $PollVotesTable extends PollVotes context.handle(_updatedAtMeta, updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); } - if (data.containsKey('user_id')) { - context.handle(_userIdMeta, - userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta)); - } return context; } @override - Set get $primaryKey => {id, pollId}; + Set get $primaryKey => {id}; @override - PollVoteEntity map(Map data, {String? tablePrefix}) { + PollEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return PollVoteEntity( + return PollEntity( id: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}id']), - pollId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}poll_id']), - optionId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}option_id']), - answerText: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}answer_text']), + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + options: $PollsTable.$converteroptions.fromSql(attachedDatabase + .typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}options'])!), + votingVisibility: $PollsTable.$convertervotingVisibility.fromSql( + attachedDatabase.typeMapping.read(DriftSqlType.string, + data['${effectivePrefix}voting_visibility'])!), + enforceUniqueVote: attachedDatabase.typeMapping.read( + DriftSqlType.bool, data['${effectivePrefix}enforce_unique_vote'])!, + maxVotesAllowed: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}max_votes_allowed']), + allowUserSuggestedOptions: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}allow_user_suggested_options'])!, + allowAnswers: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}allow_answers'])!, + isClosed: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}is_closed'])!, + answersCount: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}answers_count'])!, + voteCountsByOption: $PollsTable.$convertervoteCountsByOption.fromSql( + attachedDatabase.typeMapping.read(DriftSqlType.string, + data['${effectivePrefix}vote_counts_by_option'])!), + voteCount: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}vote_count'])!, + createdById: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}created_by_id']), createdAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, updatedAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, - userId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}user_id']), + extraData: $PollsTable.$converterextraDatan.fromSql(attachedDatabase + .typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), ); } @override - $PollVotesTable createAlias(String alias) { - return $PollVotesTable(attachedDatabase, alias); + $PollsTable createAlias(String alias) { + return $PollsTable(attachedDatabase, alias); } -} -class PollVoteEntity extends DataClass implements Insertable { - /// The unique identifier of the poll vote. - final String? id; + static TypeConverter, String> $converteroptions = + ListConverter(); + static TypeConverter $convertervotingVisibility = + const VotingVisibilityConverter(); + static TypeConverter, String> $convertervoteCountsByOption = + MapConverter(); + static TypeConverter, String> $converterextraData = + MapConverter(); + static TypeConverter?, String?> $converterextraDatan = + NullAwareTypeConverter.wrap($converterextraData); +} - /// The unique identifier of the poll the vote belongs to. - final String? pollId; +class PollEntity extends DataClass implements Insertable { + /// The unique identifier of the poll. + final String id; - /// The unique identifier of the option selected in the poll. + /// The name of the poll. + final String name; + + /// The description of the poll. + final String? description; + + /// The list of options available for the poll. + final List options; + + /// Represents the visibility of the voting process. /// - /// Nullable if the user provided an answer. - final String? optionId; + /// Defaults to 'public'. + final VotingVisibility votingVisibility; - /// The text of the answer provided in the poll. + /// If true, only unique votes are allowed. /// - /// Nullable if the user selected an option. - final String? answerText; + /// Defaults to false. + final bool enforceUniqueVote; - /// The date when the poll vote was created. + /// The maximum number of votes allowed per user. + final int? maxVotesAllowed; + + /// If true, users can suggest their own options. + /// + /// Defaults to false. + final bool allowUserSuggestedOptions; + + /// If true, users can provide their own answers/comments. + /// + /// Defaults to false. + final bool allowAnswers; + + /// Indicates if the poll is closed. + final bool isClosed; + + /// The total number of answers received by the poll. + final int answersCount; + + /// Map of vote counts by option. + final Map voteCountsByOption; + + /// The total number of votes received by the poll. + final int voteCount; + + /// The id of the user who created the poll. + final String? createdById; + + /// The date when the poll was created. final DateTime createdAt; - /// The date when the poll vote was last updated. + /// The date when the poll was last updated. final DateTime updatedAt; - /// The unique identifier of the user who voted. - /// - /// Nullable if the poll is anonymous. - final String? userId; - const PollVoteEntity( - {this.id, - this.pollId, - this.optionId, - this.answerText, + /// Map of custom poll extraData + final Map? extraData; + const PollEntity( + {required this.id, + required this.name, + this.description, + required this.options, + required this.votingVisibility, + required this.enforceUniqueVote, + this.maxVotesAllowed, + required this.allowUserSuggestedOptions, + required this.allowAnswers, + required this.isClosed, + required this.answersCount, + required this.voteCountsByOption, + required this.voteCount, + this.createdById, required this.createdAt, required this.updatedAt, - this.userId}); + this.extraData}); @override Map toColumns(bool nullToAbsent) { final map = {}; - if (!nullToAbsent || id != null) { - map['id'] = Variable(id); + map['id'] = Variable(id); + map['name'] = Variable(name); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); } - if (!nullToAbsent || pollId != null) { - map['poll_id'] = Variable(pollId); + { + map['options'] = + Variable($PollsTable.$converteroptions.toSql(options)); } - if (!nullToAbsent || optionId != null) { - map['option_id'] = Variable(optionId); + { + map['voting_visibility'] = Variable( + $PollsTable.$convertervotingVisibility.toSql(votingVisibility)); } - if (!nullToAbsent || answerText != null) { - map['answer_text'] = Variable(answerText); + map['enforce_unique_vote'] = Variable(enforceUniqueVote); + if (!nullToAbsent || maxVotesAllowed != null) { + map['max_votes_allowed'] = Variable(maxVotesAllowed); + } + map['allow_user_suggested_options'] = + Variable(allowUserSuggestedOptions); + map['allow_answers'] = Variable(allowAnswers); + map['is_closed'] = Variable(isClosed); + map['answers_count'] = Variable(answersCount); + { + map['vote_counts_by_option'] = Variable( + $PollsTable.$convertervoteCountsByOption.toSql(voteCountsByOption)); + } + map['vote_count'] = Variable(voteCount); + if (!nullToAbsent || createdById != null) { + map['created_by_id'] = Variable(createdById); } map['created_at'] = Variable(createdAt); map['updated_at'] = Variable(updatedAt); - if (!nullToAbsent || userId != null) { - map['user_id'] = Variable(userId); + if (!nullToAbsent || extraData != null) { + map['extra_data'] = + Variable($PollsTable.$converterextraDatan.toSql(extraData)); } return map; } - factory PollVoteEntity.fromJson(Map json, + factory PollEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return PollVoteEntity( - id: serializer.fromJson(json['id']), - pollId: serializer.fromJson(json['pollId']), - optionId: serializer.fromJson(json['optionId']), - answerText: serializer.fromJson(json['answerText']), + return PollEntity( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + options: serializer.fromJson>(json['options']), + votingVisibility: + serializer.fromJson(json['votingVisibility']), + enforceUniqueVote: serializer.fromJson(json['enforceUniqueVote']), + maxVotesAllowed: serializer.fromJson(json['maxVotesAllowed']), + allowUserSuggestedOptions: + serializer.fromJson(json['allowUserSuggestedOptions']), + allowAnswers: serializer.fromJson(json['allowAnswers']), + isClosed: serializer.fromJson(json['isClosed']), + answersCount: serializer.fromJson(json['answersCount']), + voteCountsByOption: + serializer.fromJson>(json['voteCountsByOption']), + voteCount: serializer.fromJson(json['voteCount']), + createdById: serializer.fromJson(json['createdById']), createdAt: serializer.fromJson(json['createdAt']), updatedAt: serializer.fromJson(json['updatedAt']), - userId: serializer.fromJson(json['userId']), + extraData: serializer.fromJson?>(json['extraData']), ); } @override Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'id': serializer.toJson(id), - 'pollId': serializer.toJson(pollId), - 'optionId': serializer.toJson(optionId), - 'answerText': serializer.toJson(answerText), + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'options': serializer.toJson>(options), + 'votingVisibility': serializer.toJson(votingVisibility), + 'enforceUniqueVote': serializer.toJson(enforceUniqueVote), + 'maxVotesAllowed': serializer.toJson(maxVotesAllowed), + 'allowUserSuggestedOptions': + serializer.toJson(allowUserSuggestedOptions), + 'allowAnswers': serializer.toJson(allowAnswers), + 'isClosed': serializer.toJson(isClosed), + 'answersCount': serializer.toJson(answersCount), + 'voteCountsByOption': + serializer.toJson>(voteCountsByOption), + 'voteCount': serializer.toJson(voteCount), + 'createdById': serializer.toJson(createdById), 'createdAt': serializer.toJson(createdAt), 'updatedAt': serializer.toJson(updatedAt), - 'userId': serializer.toJson(userId), + 'extraData': serializer.toJson?>(extraData), }; } - PollVoteEntity copyWith( - {Value id = const Value.absent(), - Value pollId = const Value.absent(), - Value optionId = const Value.absent(), - Value answerText = const Value.absent(), + PollEntity copyWith( + {String? id, + String? name, + Value description = const Value.absent(), + List? options, + VotingVisibility? votingVisibility, + bool? enforceUniqueVote, + Value maxVotesAllowed = const Value.absent(), + bool? allowUserSuggestedOptions, + bool? allowAnswers, + bool? isClosed, + int? answersCount, + Map? voteCountsByOption, + int? voteCount, + Value createdById = const Value.absent(), DateTime? createdAt, DateTime? updatedAt, - Value userId = const Value.absent()}) => - PollVoteEntity( - id: id.present ? id.value : this.id, - pollId: pollId.present ? pollId.value : this.pollId, - optionId: optionId.present ? optionId.value : this.optionId, - answerText: answerText.present ? answerText.value : this.answerText, + Value?> extraData = const Value.absent()}) => + PollEntity( + id: id ?? this.id, + name: name ?? this.name, + description: description.present ? description.value : this.description, + options: options ?? this.options, + votingVisibility: votingVisibility ?? this.votingVisibility, + enforceUniqueVote: enforceUniqueVote ?? this.enforceUniqueVote, + maxVotesAllowed: maxVotesAllowed.present + ? maxVotesAllowed.value + : this.maxVotesAllowed, + allowUserSuggestedOptions: + allowUserSuggestedOptions ?? this.allowUserSuggestedOptions, + allowAnswers: allowAnswers ?? this.allowAnswers, + isClosed: isClosed ?? this.isClosed, + answersCount: answersCount ?? this.answersCount, + voteCountsByOption: voteCountsByOption ?? this.voteCountsByOption, + voteCount: voteCount ?? this.voteCount, + createdById: createdById.present ? createdById.value : this.createdById, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, - userId: userId.present ? userId.value : this.userId, + extraData: extraData.present ? extraData.value : this.extraData, ); - PollVoteEntity copyWithCompanion(PollVotesCompanion data) { - return PollVoteEntity( + PollEntity copyWithCompanion(PollsCompanion data) { + return PollEntity( id: data.id.present ? data.id.value : this.id, - pollId: data.pollId.present ? data.pollId.value : this.pollId, - optionId: data.optionId.present ? data.optionId.value : this.optionId, - answerText: - data.answerText.present ? data.answerText.value : this.answerText, - createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, - updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, - userId: data.userId.present ? data.userId.value : this.userId, - ); - } - - @override - String toString() { - return (StringBuffer('PollVoteEntity(') - ..write('id: $id, ') - ..write('pollId: $pollId, ') - ..write('optionId: $optionId, ') - ..write('answerText: $answerText, ') - ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('userId: $userId') + name: data.name.present ? data.name.value : this.name, + description: + data.description.present ? data.description.value : this.description, + options: data.options.present ? data.options.value : this.options, + votingVisibility: data.votingVisibility.present + ? data.votingVisibility.value + : this.votingVisibility, + enforceUniqueVote: data.enforceUniqueVote.present + ? data.enforceUniqueVote.value + : this.enforceUniqueVote, + maxVotesAllowed: data.maxVotesAllowed.present + ? data.maxVotesAllowed.value + : this.maxVotesAllowed, + allowUserSuggestedOptions: data.allowUserSuggestedOptions.present + ? data.allowUserSuggestedOptions.value + : this.allowUserSuggestedOptions, + allowAnswers: data.allowAnswers.present + ? data.allowAnswers.value + : this.allowAnswers, + isClosed: data.isClosed.present ? data.isClosed.value : this.isClosed, + answersCount: data.answersCount.present + ? data.answersCount.value + : this.answersCount, + voteCountsByOption: data.voteCountsByOption.present + ? data.voteCountsByOption.value + : this.voteCountsByOption, + voteCount: data.voteCount.present ? data.voteCount.value : this.voteCount, + createdById: + data.createdById.present ? data.createdById.value : this.createdById, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + extraData: data.extraData.present ? data.extraData.value : this.extraData, + ); + } + + @override + String toString() { + return (StringBuffer('PollEntity(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('options: $options, ') + ..write('votingVisibility: $votingVisibility, ') + ..write('enforceUniqueVote: $enforceUniqueVote, ') + ..write('maxVotesAllowed: $maxVotesAllowed, ') + ..write('allowUserSuggestedOptions: $allowUserSuggestedOptions, ') + ..write('allowAnswers: $allowAnswers, ') + ..write('isClosed: $isClosed, ') + ..write('answersCount: $answersCount, ') + ..write('voteCountsByOption: $voteCountsByOption, ') + ..write('voteCount: $voteCount, ') + ..write('createdById: $createdById, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('extraData: $extraData') ..write(')')) .toString(); } @override int get hashCode => Object.hash( - id, pollId, optionId, answerText, createdAt, updatedAt, userId); + id, + name, + description, + options, + votingVisibility, + enforceUniqueVote, + maxVotesAllowed, + allowUserSuggestedOptions, + allowAnswers, + isClosed, + answersCount, + voteCountsByOption, + voteCount, + createdById, + createdAt, + updatedAt, + extraData); @override bool operator ==(Object other) => identical(this, other) || - (other is PollVoteEntity && + (other is PollEntity && other.id == this.id && - other.pollId == this.pollId && - other.optionId == this.optionId && - other.answerText == this.answerText && + other.name == this.name && + other.description == this.description && + other.options == this.options && + other.votingVisibility == this.votingVisibility && + other.enforceUniqueVote == this.enforceUniqueVote && + other.maxVotesAllowed == this.maxVotesAllowed && + other.allowUserSuggestedOptions == this.allowUserSuggestedOptions && + other.allowAnswers == this.allowAnswers && + other.isClosed == this.isClosed && + other.answersCount == this.answersCount && + other.voteCountsByOption == this.voteCountsByOption && + other.voteCount == this.voteCount && + other.createdById == this.createdById && other.createdAt == this.createdAt && other.updatedAt == this.updatedAt && - other.userId == this.userId); + other.extraData == this.extraData); } -class PollVotesCompanion extends UpdateCompanion { - final Value id; - final Value pollId; - final Value optionId; - final Value answerText; +class PollsCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value description; + final Value> options; + final Value votingVisibility; + final Value enforceUniqueVote; + final Value maxVotesAllowed; + final Value allowUserSuggestedOptions; + final Value allowAnswers; + final Value isClosed; + final Value answersCount; + final Value> voteCountsByOption; + final Value voteCount; + final Value createdById; final Value createdAt; final Value updatedAt; - final Value userId; + final Value?> extraData; final Value rowid; - const PollVotesCompanion({ + const PollsCompanion({ this.id = const Value.absent(), - this.pollId = const Value.absent(), - this.optionId = const Value.absent(), - this.answerText = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.options = const Value.absent(), + this.votingVisibility = const Value.absent(), + this.enforceUniqueVote = const Value.absent(), + this.maxVotesAllowed = const Value.absent(), + this.allowUserSuggestedOptions = const Value.absent(), + this.allowAnswers = const Value.absent(), + this.isClosed = const Value.absent(), + this.answersCount = const Value.absent(), + this.voteCountsByOption = const Value.absent(), + this.voteCount = const Value.absent(), + this.createdById = const Value.absent(), this.createdAt = const Value.absent(), this.updatedAt = const Value.absent(), - this.userId = const Value.absent(), + this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); - PollVotesCompanion.insert({ - this.id = const Value.absent(), - this.pollId = const Value.absent(), - this.optionId = const Value.absent(), - this.answerText = const Value.absent(), + PollsCompanion.insert({ + required String id, + required String name, + this.description = const Value.absent(), + required List options, + this.votingVisibility = const Value.absent(), + this.enforceUniqueVote = const Value.absent(), + this.maxVotesAllowed = const Value.absent(), + this.allowUserSuggestedOptions = const Value.absent(), + this.allowAnswers = const Value.absent(), + this.isClosed = const Value.absent(), + this.answersCount = const Value.absent(), + required Map voteCountsByOption, + this.voteCount = const Value.absent(), + this.createdById = const Value.absent(), this.createdAt = const Value.absent(), this.updatedAt = const Value.absent(), - this.userId = const Value.absent(), + this.extraData = const Value.absent(), this.rowid = const Value.absent(), - }); - static Insertable custom({ + }) : id = Value(id), + name = Value(name), + options = Value(options), + voteCountsByOption = Value(voteCountsByOption); + static Insertable custom({ Expression? id, - Expression? pollId, - Expression? optionId, - Expression? answerText, + Expression? name, + Expression? description, + Expression? options, + Expression? votingVisibility, + Expression? enforceUniqueVote, + Expression? maxVotesAllowed, + Expression? allowUserSuggestedOptions, + Expression? allowAnswers, + Expression? isClosed, + Expression? answersCount, + Expression? voteCountsByOption, + Expression? voteCount, + Expression? createdById, Expression? createdAt, Expression? updatedAt, - Expression? userId, + Expression? extraData, Expression? rowid, }) { return RawValuesInsertable({ if (id != null) 'id': id, - if (pollId != null) 'poll_id': pollId, - if (optionId != null) 'option_id': optionId, - if (answerText != null) 'answer_text': answerText, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (options != null) 'options': options, + if (votingVisibility != null) 'voting_visibility': votingVisibility, + if (enforceUniqueVote != null) 'enforce_unique_vote': enforceUniqueVote, + if (maxVotesAllowed != null) 'max_votes_allowed': maxVotesAllowed, + if (allowUserSuggestedOptions != null) + 'allow_user_suggested_options': allowUserSuggestedOptions, + if (allowAnswers != null) 'allow_answers': allowAnswers, + if (isClosed != null) 'is_closed': isClosed, + if (answersCount != null) 'answers_count': answersCount, + if (voteCountsByOption != null) + 'vote_counts_by_option': voteCountsByOption, + if (voteCount != null) 'vote_count': voteCount, + if (createdById != null) 'created_by_id': createdById, if (createdAt != null) 'created_at': createdAt, if (updatedAt != null) 'updated_at': updatedAt, - if (userId != null) 'user_id': userId, + if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, }); } - PollVotesCompanion copyWith( - {Value? id, - Value? pollId, - Value? optionId, - Value? answerText, + PollsCompanion copyWith( + {Value? id, + Value? name, + Value? description, + Value>? options, + Value? votingVisibility, + Value? enforceUniqueVote, + Value? maxVotesAllowed, + Value? allowUserSuggestedOptions, + Value? allowAnswers, + Value? isClosed, + Value? answersCount, + Value>? voteCountsByOption, + Value? voteCount, + Value? createdById, Value? createdAt, Value? updatedAt, - Value? userId, + Value?>? extraData, Value? rowid}) { - return PollVotesCompanion( + return PollsCompanion( id: id ?? this.id, - pollId: pollId ?? this.pollId, - optionId: optionId ?? this.optionId, - answerText: answerText ?? this.answerText, + name: name ?? this.name, + description: description ?? this.description, + options: options ?? this.options, + votingVisibility: votingVisibility ?? this.votingVisibility, + enforceUniqueVote: enforceUniqueVote ?? this.enforceUniqueVote, + maxVotesAllowed: maxVotesAllowed ?? this.maxVotesAllowed, + allowUserSuggestedOptions: + allowUserSuggestedOptions ?? this.allowUserSuggestedOptions, + allowAnswers: allowAnswers ?? this.allowAnswers, + isClosed: isClosed ?? this.isClosed, + answersCount: answersCount ?? this.answersCount, + voteCountsByOption: voteCountsByOption ?? this.voteCountsByOption, + voteCount: voteCount ?? this.voteCount, + createdById: createdById ?? this.createdById, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, - userId: userId ?? this.userId, + extraData: extraData ?? this.extraData, rowid: rowid ?? this.rowid, ); } @@ -5464,14 +5507,49 @@ class PollVotesCompanion extends UpdateCompanion { if (id.present) { map['id'] = Variable(id.value); } - if (pollId.present) { - map['poll_id'] = Variable(pollId.value); + if (name.present) { + map['name'] = Variable(name.value); } - if (optionId.present) { - map['option_id'] = Variable(optionId.value); + if (description.present) { + map['description'] = Variable(description.value); } - if (answerText.present) { - map['answer_text'] = Variable(answerText.value); + if (options.present) { + map['options'] = + Variable($PollsTable.$converteroptions.toSql(options.value)); + } + if (votingVisibility.present) { + map['voting_visibility'] = Variable( + $PollsTable.$convertervotingVisibility.toSql(votingVisibility.value)); + } + if (enforceUniqueVote.present) { + map['enforce_unique_vote'] = Variable(enforceUniqueVote.value); + } + if (maxVotesAllowed.present) { + map['max_votes_allowed'] = Variable(maxVotesAllowed.value); + } + if (allowUserSuggestedOptions.present) { + map['allow_user_suggested_options'] = + Variable(allowUserSuggestedOptions.value); + } + if (allowAnswers.present) { + map['allow_answers'] = Variable(allowAnswers.value); + } + if (isClosed.present) { + map['is_closed'] = Variable(isClosed.value); + } + if (answersCount.present) { + map['answers_count'] = Variable(answersCount.value); + } + if (voteCountsByOption.present) { + map['vote_counts_by_option'] = Variable($PollsTable + .$convertervoteCountsByOption + .toSql(voteCountsByOption.value)); + } + if (voteCount.present) { + map['vote_count'] = Variable(voteCount.value); + } + if (createdById.present) { + map['created_by_id'] = Variable(createdById.value); } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); @@ -5479,8 +5557,9 @@ class PollVotesCompanion extends UpdateCompanion { if (updatedAt.present) { map['updated_at'] = Variable(updatedAt.value); } - if (userId.present) { - map['user_id'] = Variable(userId.value); + if (extraData.present) { + map['extra_data'] = Variable( + $PollsTable.$converterextraDatan.toSql(extraData.value)); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -5490,45 +5569,61 @@ class PollVotesCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('PollVotesCompanion(') + return (StringBuffer('PollsCompanion(') ..write('id: $id, ') - ..write('pollId: $pollId, ') - ..write('optionId: $optionId, ') - ..write('answerText: $answerText, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('options: $options, ') + ..write('votingVisibility: $votingVisibility, ') + ..write('enforceUniqueVote: $enforceUniqueVote, ') + ..write('maxVotesAllowed: $maxVotesAllowed, ') + ..write('allowUserSuggestedOptions: $allowUserSuggestedOptions, ') + ..write('allowAnswers: $allowAnswers, ') + ..write('isClosed: $isClosed, ') + ..write('answersCount: $answersCount, ') + ..write('voteCountsByOption: $voteCountsByOption, ') + ..write('voteCount: $voteCount, ') + ..write('createdById: $createdById, ') ..write('createdAt: $createdAt, ') ..write('updatedAt: $updatedAt, ') - ..write('userId: $userId, ') + ..write('extraData: $extraData, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } -class $PinnedMessageReactionsTable extends PinnedMessageReactions - with TableInfo<$PinnedMessageReactionsTable, PinnedMessageReactionEntity> { +class $PollVotesTable extends PollVotes + with TableInfo<$PollVotesTable, PollVoteEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $PinnedMessageReactionsTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); + $PollVotesTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); @override - late final GeneratedColumn userId = GeneratedColumn( - 'user_id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _messageIdMeta = - const VerificationMeta('messageId'); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _pollIdMeta = const VerificationMeta('pollId'); @override - late final GeneratedColumn messageId = GeneratedColumn( - 'message_id', aliasedName, false, + late final GeneratedColumn pollId = GeneratedColumn( + 'poll_id', aliasedName, true, type: DriftSqlType.string, - requiredDuringInsert: true, + requiredDuringInsert: false, defaultConstraints: GeneratedColumn.constraintIsAlways( - 'REFERENCES pinned_messages (id) ON DELETE CASCADE')); - static const VerificationMeta _typeMeta = const VerificationMeta('type'); + 'REFERENCES polls (id) ON DELETE CASCADE')); + static const VerificationMeta _optionIdMeta = + const VerificationMeta('optionId'); @override - late final GeneratedColumn type = GeneratedColumn( - 'type', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn optionId = GeneratedColumn( + 'option_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _answerTextMeta = + const VerificationMeta('answerText'); + @override + late final GeneratedColumn answerText = GeneratedColumn( + 'answer_text', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); @override @@ -5537,281 +5632,306 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions type: DriftSqlType.dateTime, requiredDuringInsert: false, defaultValue: currentDateAndTime); - static const VerificationMeta _scoreMeta = const VerificationMeta('score'); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); @override - late final GeneratedColumn score = GeneratedColumn( - 'score', aliasedName, false, - type: DriftSqlType.int, + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: false, - defaultValue: const Constant(0)); + defaultValue: currentDateAndTime); + static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); @override - late final GeneratedColumnWithTypeConverter?, String> - extraData = GeneratedColumn('extra_data', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $PinnedMessageReactionsTable.$converterextraDatan); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); @override List get $columns => - [userId, messageId, type, createdAt, score, extraData]; + [id, pollId, optionId, answerText, createdAt, updatedAt, userId]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'pinned_message_reactions'; + static const String $name = 'poll_votes'; @override - VerificationContext validateIntegrity( - Insertable instance, + 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('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); } - if (data.containsKey('message_id')) { - context.handle(_messageIdMeta, - messageId.isAcceptableOrUnknown(data['message_id']!, _messageIdMeta)); - } else if (isInserting) { - context.missing(_messageIdMeta); + if (data.containsKey('poll_id')) { + context.handle(_pollIdMeta, + pollId.isAcceptableOrUnknown(data['poll_id']!, _pollIdMeta)); } - if (data.containsKey('type')) { + if (data.containsKey('option_id')) { + context.handle(_optionIdMeta, + optionId.isAcceptableOrUnknown(data['option_id']!, _optionIdMeta)); + } + if (data.containsKey('answer_text')) { context.handle( - _typeMeta, type.isAcceptableOrUnknown(data['type']!, _typeMeta)); - } else if (isInserting) { - context.missing(_typeMeta); + _answerTextMeta, + answerText.isAcceptableOrUnknown( + data['answer_text']!, _answerTextMeta)); } if (data.containsKey('created_at')) { context.handle(_createdAtMeta, createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); } - if (data.containsKey('score')) { - context.handle( - _scoreMeta, score.isAcceptableOrUnknown(data['score']!, _scoreMeta)); + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); + } + if (data.containsKey('user_id')) { + context.handle(_userIdMeta, + userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta)); } return context; } @override - Set get $primaryKey => {messageId, type, userId}; + Set get $primaryKey => {id, pollId}; @override - PinnedMessageReactionEntity map(Map data, - {String? tablePrefix}) { + PollVoteEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return PinnedMessageReactionEntity( - userId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, - messageId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}message_id'])!, - type: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + return PollVoteEntity( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id']), + pollId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}poll_id']), + optionId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}option_id']), + answerText: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}answer_text']), createdAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, - score: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}score'])!, - extraData: $PinnedMessageReactionsTable.$converterextraDatan.fromSql( - attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + userId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}user_id']), ); } @override - $PinnedMessageReactionsTable createAlias(String alias) { - return $PinnedMessageReactionsTable(attachedDatabase, alias); + $PollVotesTable createAlias(String alias) { + return $PollVotesTable(attachedDatabase, alias); } - - static TypeConverter, String> $converterextraData = - MapConverter(); - static TypeConverter?, String?> $converterextraDatan = - NullAwareTypeConverter.wrap($converterextraData); } -class PinnedMessageReactionEntity extends DataClass - implements Insertable { - /// The id of the user that sent the reaction - final String userId; +class PollVoteEntity extends DataClass implements Insertable { + /// The unique identifier of the poll vote. + final String? id; - /// The messageId to which the reaction belongs - final String messageId; + /// The unique identifier of the poll the vote belongs to. + final String? pollId; - /// The type of the reaction - final String type; + /// The unique identifier of the option selected in the poll. + /// + /// Nullable if the user provided an answer. + final String? optionId; - /// The DateTime on which the reaction is created + /// The text of the answer provided in the poll. + /// + /// Nullable if the user selected an option. + final String? answerText; + + /// The date when the poll vote was created. final DateTime createdAt; - /// The score of the reaction (ie. number of reactions sent) - final int score; + /// The date when the poll vote was last updated. + final DateTime updatedAt; - /// Reaction custom extraData - final Map? extraData; - const PinnedMessageReactionEntity( - {required this.userId, - required this.messageId, - required this.type, + /// The unique identifier of the user who voted. + /// + /// Nullable if the poll is anonymous. + final String? userId; + const PollVoteEntity( + {this.id, + this.pollId, + this.optionId, + this.answerText, required this.createdAt, - required this.score, - this.extraData}); + required this.updatedAt, + this.userId}); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['user_id'] = Variable(userId); - map['message_id'] = Variable(messageId); - map['type'] = Variable(type); - map['created_at'] = Variable(createdAt); - map['score'] = Variable(score); - if (!nullToAbsent || extraData != null) { - map['extra_data'] = Variable( - $PinnedMessageReactionsTable.$converterextraDatan.toSql(extraData)); + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || pollId != null) { + map['poll_id'] = Variable(pollId); + } + if (!nullToAbsent || optionId != null) { + map['option_id'] = Variable(optionId); + } + if (!nullToAbsent || answerText != null) { + map['answer_text'] = Variable(answerText); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); } return map; } - factory PinnedMessageReactionEntity.fromJson(Map json, + factory PollVoteEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return PinnedMessageReactionEntity( - userId: serializer.fromJson(json['userId']), - messageId: serializer.fromJson(json['messageId']), - type: serializer.fromJson(json['type']), + return PollVoteEntity( + id: serializer.fromJson(json['id']), + pollId: serializer.fromJson(json['pollId']), + optionId: serializer.fromJson(json['optionId']), + answerText: serializer.fromJson(json['answerText']), createdAt: serializer.fromJson(json['createdAt']), - score: serializer.fromJson(json['score']), - extraData: serializer.fromJson?>(json['extraData']), + updatedAt: serializer.fromJson(json['updatedAt']), + userId: serializer.fromJson(json['userId']), ); } @override Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'userId': serializer.toJson(userId), - 'messageId': serializer.toJson(messageId), - 'type': serializer.toJson(type), + 'id': serializer.toJson(id), + 'pollId': serializer.toJson(pollId), + 'optionId': serializer.toJson(optionId), + 'answerText': serializer.toJson(answerText), 'createdAt': serializer.toJson(createdAt), - 'score': serializer.toJson(score), - 'extraData': serializer.toJson?>(extraData), + 'updatedAt': serializer.toJson(updatedAt), + 'userId': serializer.toJson(userId), }; } - PinnedMessageReactionEntity copyWith( - {String? userId, - String? messageId, - String? type, + PollVoteEntity copyWith( + {Value id = const Value.absent(), + Value pollId = const Value.absent(), + Value optionId = const Value.absent(), + Value answerText = const Value.absent(), DateTime? createdAt, - int? score, - Value?> extraData = const Value.absent()}) => - PinnedMessageReactionEntity( - userId: userId ?? this.userId, - messageId: messageId ?? this.messageId, - type: type ?? this.type, + DateTime? updatedAt, + Value userId = const Value.absent()}) => + PollVoteEntity( + id: id.present ? id.value : this.id, + pollId: pollId.present ? pollId.value : this.pollId, + optionId: optionId.present ? optionId.value : this.optionId, + answerText: answerText.present ? answerText.value : this.answerText, createdAt: createdAt ?? this.createdAt, - score: score ?? this.score, - extraData: extraData.present ? extraData.value : this.extraData, + updatedAt: updatedAt ?? this.updatedAt, + userId: userId.present ? userId.value : this.userId, ); - PinnedMessageReactionEntity copyWithCompanion( - PinnedMessageReactionsCompanion data) { - return PinnedMessageReactionEntity( - userId: data.userId.present ? data.userId.value : this.userId, - messageId: data.messageId.present ? data.messageId.value : this.messageId, - type: data.type.present ? data.type.value : this.type, + PollVoteEntity copyWithCompanion(PollVotesCompanion data) { + return PollVoteEntity( + id: data.id.present ? data.id.value : this.id, + pollId: data.pollId.present ? data.pollId.value : this.pollId, + optionId: data.optionId.present ? data.optionId.value : this.optionId, + answerText: + data.answerText.present ? data.answerText.value : this.answerText, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, - score: data.score.present ? data.score.value : this.score, - extraData: data.extraData.present ? data.extraData.value : this.extraData, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + userId: data.userId.present ? data.userId.value : this.userId, ); } @override String toString() { - return (StringBuffer('PinnedMessageReactionEntity(') - ..write('userId: $userId, ') - ..write('messageId: $messageId, ') - ..write('type: $type, ') + return (StringBuffer('PollVoteEntity(') + ..write('id: $id, ') + ..write('pollId: $pollId, ') + ..write('optionId: $optionId, ') + ..write('answerText: $answerText, ') ..write('createdAt: $createdAt, ') - ..write('score: $score, ') - ..write('extraData: $extraData') + ..write('updatedAt: $updatedAt, ') + ..write('userId: $userId') ..write(')')) .toString(); } @override - int get hashCode => - Object.hash(userId, messageId, type, createdAt, score, extraData); + int get hashCode => Object.hash( + id, pollId, optionId, answerText, createdAt, updatedAt, userId); @override bool operator ==(Object other) => identical(this, other) || - (other is PinnedMessageReactionEntity && - other.userId == this.userId && - other.messageId == this.messageId && - other.type == this.type && + (other is PollVoteEntity && + other.id == this.id && + other.pollId == this.pollId && + other.optionId == this.optionId && + other.answerText == this.answerText && other.createdAt == this.createdAt && - other.score == this.score && - other.extraData == this.extraData); + other.updatedAt == this.updatedAt && + other.userId == this.userId); } -class PinnedMessageReactionsCompanion - extends UpdateCompanion { - final Value userId; - final Value messageId; - final Value type; +class PollVotesCompanion extends UpdateCompanion { + final Value id; + final Value pollId; + final Value optionId; + final Value answerText; final Value createdAt; - final Value score; - final Value?> extraData; + final Value updatedAt; + final Value userId; final Value rowid; - const PinnedMessageReactionsCompanion({ - this.userId = const Value.absent(), - this.messageId = const Value.absent(), - this.type = const Value.absent(), + const PollVotesCompanion({ + this.id = const Value.absent(), + this.pollId = const Value.absent(), + this.optionId = const Value.absent(), + this.answerText = const Value.absent(), this.createdAt = const Value.absent(), - this.score = const Value.absent(), - this.extraData = const Value.absent(), + this.updatedAt = const Value.absent(), + this.userId = const Value.absent(), this.rowid = const Value.absent(), }); - PinnedMessageReactionsCompanion.insert({ - required String userId, - required String messageId, - required String type, + PollVotesCompanion.insert({ + this.id = const Value.absent(), + this.pollId = const Value.absent(), + this.optionId = const Value.absent(), + this.answerText = const Value.absent(), this.createdAt = const Value.absent(), - this.score = const Value.absent(), - this.extraData = const Value.absent(), + this.updatedAt = const Value.absent(), + this.userId = const Value.absent(), this.rowid = const Value.absent(), - }) : userId = Value(userId), - messageId = Value(messageId), - type = Value(type); - static Insertable custom({ - Expression? userId, - Expression? messageId, - Expression? type, + }); + static Insertable custom({ + Expression? id, + Expression? pollId, + Expression? optionId, + Expression? answerText, Expression? createdAt, - Expression? score, - Expression? extraData, + Expression? updatedAt, + Expression? userId, Expression? rowid, }) { return RawValuesInsertable({ - if (userId != null) 'user_id': userId, - if (messageId != null) 'message_id': messageId, - if (type != null) 'type': type, + if (id != null) 'id': id, + if (pollId != null) 'poll_id': pollId, + if (optionId != null) 'option_id': optionId, + if (answerText != null) 'answer_text': answerText, if (createdAt != null) 'created_at': createdAt, - if (score != null) 'score': score, - if (extraData != null) 'extra_data': extraData, + if (updatedAt != null) 'updated_at': updatedAt, + if (userId != null) 'user_id': userId, if (rowid != null) 'rowid': rowid, }); } - PinnedMessageReactionsCompanion copyWith( - {Value? userId, - Value? messageId, - Value? type, + PollVotesCompanion copyWith( + {Value? id, + Value? pollId, + Value? optionId, + Value? answerText, Value? createdAt, - Value? score, - Value?>? extraData, + Value? updatedAt, + Value? userId, Value? rowid}) { - return PinnedMessageReactionsCompanion( - userId: userId ?? this.userId, - messageId: messageId ?? this.messageId, - type: type ?? this.type, + return PollVotesCompanion( + id: id ?? this.id, + pollId: pollId ?? this.pollId, + optionId: optionId ?? this.optionId, + answerText: answerText ?? this.answerText, createdAt: createdAt ?? this.createdAt, - score: score ?? this.score, - extraData: extraData ?? this.extraData, + updatedAt: updatedAt ?? this.updatedAt, + userId: userId ?? this.userId, rowid: rowid ?? this.rowid, ); } @@ -5819,25 +5939,26 @@ class PinnedMessageReactionsCompanion @override Map toColumns(bool nullToAbsent) { final map = {}; - if (userId.present) { - map['user_id'] = Variable(userId.value); + if (id.present) { + map['id'] = Variable(id.value); } - if (messageId.present) { - map['message_id'] = Variable(messageId.value); + if (pollId.present) { + map['poll_id'] = Variable(pollId.value); } - if (type.present) { - map['type'] = Variable(type.value); + if (optionId.present) { + map['option_id'] = Variable(optionId.value); + } + if (answerText.present) { + map['answer_text'] = Variable(answerText.value); } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); } - if (score.present) { - map['score'] = Variable(score.value); + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); } - if (extraData.present) { - map['extra_data'] = Variable($PinnedMessageReactionsTable - .$converterextraDatan - .toSql(extraData.value)); + if (userId.present) { + map['user_id'] = Variable(userId.value); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -5847,25 +5968,26 @@ class PinnedMessageReactionsCompanion @override String toString() { - return (StringBuffer('PinnedMessageReactionsCompanion(') - ..write('userId: $userId, ') - ..write('messageId: $messageId, ') - ..write('type: $type, ') + return (StringBuffer('PollVotesCompanion(') + ..write('id: $id, ') + ..write('pollId: $pollId, ') + ..write('optionId: $optionId, ') + ..write('answerText: $answerText, ') ..write('createdAt: $createdAt, ') - ..write('score: $score, ') - ..write('extraData: $extraData, ') + ..write('updatedAt: $updatedAt, ') + ..write('userId: $userId, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } -class $ReactionsTable extends Reactions - with TableInfo<$ReactionsTable, ReactionEntity> { +class $PinnedMessageReactionsTable extends PinnedMessageReactions + with TableInfo<$PinnedMessageReactionsTable, PinnedMessageReactionEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $ReactionsTable(this.attachedDatabase, [this._alias]); + $PinnedMessageReactionsTable(this.attachedDatabase, [this._alias]); static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); @override late final GeneratedColumn userId = GeneratedColumn( @@ -5879,7 +6001,7 @@ class $ReactionsTable extends Reactions type: DriftSqlType.string, requiredDuringInsert: true, defaultConstraints: GeneratedColumn.constraintIsAlways( - 'REFERENCES messages (id) ON DELETE CASCADE')); + 'REFERENCES pinned_messages (id) ON DELETE CASCADE')); static const VerificationMeta _typeMeta = const VerificationMeta('type'); @override late final GeneratedColumn type = GeneratedColumn( @@ -5905,7 +6027,7 @@ class $ReactionsTable extends Reactions extraData = GeneratedColumn('extra_data', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false) .withConverter?>( - $ReactionsTable.$converterextraDatan); + $PinnedMessageReactionsTable.$converterextraDatan); @override List get $columns => [userId, messageId, type, createdAt, score, extraData]; @@ -5913,9 +6035,10 @@ class $ReactionsTable extends Reactions String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'reactions'; + static const String $name = 'pinned_message_reactions'; @override - VerificationContext validateIntegrity(Insertable instance, + VerificationContext validateIntegrity( + Insertable instance, {bool isInserting = false}) { final context = VerificationContext(); final data = instance.toColumns(true); @@ -5951,9 +6074,10 @@ class $ReactionsTable extends Reactions @override Set get $primaryKey => {messageId, type, userId}; @override - ReactionEntity map(Map data, {String? tablePrefix}) { + PinnedMessageReactionEntity map(Map data, + {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return ReactionEntity( + return PinnedMessageReactionEntity( userId: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, messageId: attachedDatabase.typeMapping @@ -5964,15 +6088,15 @@ class $ReactionsTable extends Reactions .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, score: attachedDatabase.typeMapping .read(DriftSqlType.int, data['${effectivePrefix}score'])!, - extraData: $ReactionsTable.$converterextraDatan.fromSql(attachedDatabase - .typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), + extraData: $PinnedMessageReactionsTable.$converterextraDatan.fromSql( + attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), ); } @override - $ReactionsTable createAlias(String alias) { - return $ReactionsTable(attachedDatabase, alias); + $PinnedMessageReactionsTable createAlias(String alias) { + return $PinnedMessageReactionsTable(attachedDatabase, alias); } static TypeConverter, String> $converterextraData = @@ -5981,7 +6105,8 @@ class $ReactionsTable extends Reactions NullAwareTypeConverter.wrap($converterextraData); } -class ReactionEntity extends DataClass implements Insertable { +class PinnedMessageReactionEntity extends DataClass + implements Insertable { /// The id of the user that sent the reaction final String userId; @@ -5999,7 +6124,7 @@ class ReactionEntity extends DataClass implements Insertable { /// Reaction custom extraData final Map? extraData; - const ReactionEntity( + const PinnedMessageReactionEntity( {required this.userId, required this.messageId, required this.type, @@ -6016,15 +6141,15 @@ class ReactionEntity extends DataClass implements Insertable { map['score'] = Variable(score); if (!nullToAbsent || extraData != null) { map['extra_data'] = Variable( - $ReactionsTable.$converterextraDatan.toSql(extraData)); + $PinnedMessageReactionsTable.$converterextraDatan.toSql(extraData)); } return map; } - factory ReactionEntity.fromJson(Map json, + factory PinnedMessageReactionEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return ReactionEntity( + return PinnedMessageReactionEntity( userId: serializer.fromJson(json['userId']), messageId: serializer.fromJson(json['messageId']), type: serializer.fromJson(json['type']), @@ -6046,14 +6171,14 @@ class ReactionEntity extends DataClass implements Insertable { }; } - ReactionEntity copyWith( + PinnedMessageReactionEntity copyWith( {String? userId, String? messageId, String? type, DateTime? createdAt, int? score, Value?> extraData = const Value.absent()}) => - ReactionEntity( + PinnedMessageReactionEntity( userId: userId ?? this.userId, messageId: messageId ?? this.messageId, type: type ?? this.type, @@ -6061,8 +6186,9 @@ class ReactionEntity extends DataClass implements Insertable { score: score ?? this.score, extraData: extraData.present ? extraData.value : this.extraData, ); - ReactionEntity copyWithCompanion(ReactionsCompanion data) { - return ReactionEntity( + PinnedMessageReactionEntity copyWithCompanion( + PinnedMessageReactionsCompanion data) { + return PinnedMessageReactionEntity( userId: data.userId.present ? data.userId.value : this.userId, messageId: data.messageId.present ? data.messageId.value : this.messageId, type: data.type.present ? data.type.value : this.type, @@ -6074,7 +6200,7 @@ class ReactionEntity extends DataClass implements Insertable { @override String toString() { - return (StringBuffer('ReactionEntity(') + return (StringBuffer('PinnedMessageReactionEntity(') ..write('userId: $userId, ') ..write('messageId: $messageId, ') ..write('type: $type, ') @@ -6091,7 +6217,7 @@ class ReactionEntity extends DataClass implements Insertable { @override bool operator ==(Object other) => identical(this, other) || - (other is ReactionEntity && + (other is PinnedMessageReactionEntity && other.userId == this.userId && other.messageId == this.messageId && other.type == this.type && @@ -6100,7 +6226,8 @@ class ReactionEntity extends DataClass implements Insertable { other.extraData == this.extraData); } -class ReactionsCompanion extends UpdateCompanion { +class PinnedMessageReactionsCompanion + extends UpdateCompanion { final Value userId; final Value messageId; final Value type; @@ -6108,7 +6235,7 @@ class ReactionsCompanion extends UpdateCompanion { final Value score; final Value?> extraData; final Value rowid; - const ReactionsCompanion({ + const PinnedMessageReactionsCompanion({ this.userId = const Value.absent(), this.messageId = const Value.absent(), this.type = const Value.absent(), @@ -6117,7 +6244,7 @@ class ReactionsCompanion extends UpdateCompanion { this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); - ReactionsCompanion.insert({ + PinnedMessageReactionsCompanion.insert({ required String userId, required String messageId, required String type, @@ -6128,7 +6255,7 @@ class ReactionsCompanion extends UpdateCompanion { }) : userId = Value(userId), messageId = Value(messageId), type = Value(type); - static Insertable custom({ + static Insertable custom({ Expression? userId, Expression? messageId, Expression? type, @@ -6148,7 +6275,7 @@ class ReactionsCompanion extends UpdateCompanion { }); } - ReactionsCompanion copyWith( + PinnedMessageReactionsCompanion copyWith( {Value? userId, Value? messageId, Value? type, @@ -6156,7 +6283,7 @@ class ReactionsCompanion extends UpdateCompanion { Value? score, Value?>? extraData, Value? rowid}) { - return ReactionsCompanion( + return PinnedMessageReactionsCompanion( userId: userId ?? this.userId, messageId: messageId ?? this.messageId, type: type ?? this.type, @@ -6186,8 +6313,9 @@ class ReactionsCompanion extends UpdateCompanion { map['score'] = Variable(score.value); } if (extraData.present) { - map['extra_data'] = Variable( - $ReactionsTable.$converterextraDatan.toSql(extraData.value)); + map['extra_data'] = Variable($PinnedMessageReactionsTable + .$converterextraDatan + .toSql(extraData.value)); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -6197,7 +6325,7 @@ class ReactionsCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('ReactionsCompanion(') + return (StringBuffer('PinnedMessageReactionsCompanion(') ..write('userId: $userId, ') ..write('messageId: $messageId, ') ..write('type: $type, ') @@ -6210,451 +6338,308 @@ class ReactionsCompanion extends UpdateCompanion { } } -class $UsersTable extends Users with TableInfo<$UsersTable, UserEntity> { +class $ReactionsTable extends Reactions + with TableInfo<$ReactionsTable, ReactionEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $UsersTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _idMeta = const VerificationMeta('id'); + $ReactionsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); @override - late final GeneratedColumn id = GeneratedColumn( - 'id', aliasedName, false, + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _roleMeta = const VerificationMeta('role'); + static const VerificationMeta _messageIdMeta = + const VerificationMeta('messageId'); @override - late final GeneratedColumn role = GeneratedColumn( - 'role', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _languageMeta = - const VerificationMeta('language'); + late final GeneratedColumn messageId = GeneratedColumn( + 'message_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES messages (id) ON DELETE CASCADE')); + static const VerificationMeta _typeMeta = const VerificationMeta('type'); @override - late final GeneratedColumn language = GeneratedColumn( - 'language', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); static const VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); @override late final GeneratedColumn createdAt = GeneratedColumn( - 'created_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _updatedAtMeta = - const VerificationMeta('updatedAt'); - @override - late final GeneratedColumn updatedAt = GeneratedColumn( - 'updated_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _lastActiveMeta = - const VerificationMeta('lastActive'); - @override - late final GeneratedColumn lastActive = GeneratedColumn( - 'last_active', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _onlineMeta = const VerificationMeta('online'); - @override - late final GeneratedColumn online = GeneratedColumn( - 'online', aliasedName, false, - type: DriftSqlType.bool, + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("online" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _bannedMeta = const VerificationMeta('banned'); + defaultValue: currentDateAndTime); + static const VerificationMeta _scoreMeta = const VerificationMeta('score'); @override - late final GeneratedColumn banned = GeneratedColumn( - 'banned', aliasedName, false, - type: DriftSqlType.bool, + late final GeneratedColumn score = GeneratedColumn( + 'score', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("banned" IN (0, 1))'), - defaultValue: const Constant(false)); + defaultValue: const Constant(0)); @override - late final GeneratedColumnWithTypeConverter?, String> - teamsRole = GeneratedColumn('teams_role', aliasedName, true, + late final GeneratedColumnWithTypeConverter?, String> + extraData = GeneratedColumn('extra_data', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $UsersTable.$converterteamsRolen); - @override - late final GeneratedColumnWithTypeConverter, String> - extraData = GeneratedColumn('extra_data', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true) - .withConverter>($UsersTable.$converterextraData); + .withConverter?>( + $ReactionsTable.$converterextraDatan); @override - List get $columns => [ - id, - role, - language, - createdAt, - updatedAt, - lastActive, - online, - banned, - teamsRole, - extraData - ]; + List get $columns => + [userId, messageId, type, createdAt, score, extraData]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'users'; + static const String $name = 'reactions'; @override - VerificationContext validateIntegrity(Insertable instance, + 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)); + if (data.containsKey('user_id')) { + context.handle(_userIdMeta, + userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta)); } else if (isInserting) { - context.missing(_idMeta); + context.missing(_userIdMeta); } - if (data.containsKey('role')) { - context.handle( - _roleMeta, role.isAcceptableOrUnknown(data['role']!, _roleMeta)); + if (data.containsKey('message_id')) { + context.handle(_messageIdMeta, + messageId.isAcceptableOrUnknown(data['message_id']!, _messageIdMeta)); + } else if (isInserting) { + context.missing(_messageIdMeta); } - if (data.containsKey('language')) { - context.handle(_languageMeta, - language.isAcceptableOrUnknown(data['language']!, _languageMeta)); + 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)); } - if (data.containsKey('updated_at')) { - context.handle(_updatedAtMeta, - updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); - } - if (data.containsKey('last_active')) { + if (data.containsKey('score')) { 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)); + _scoreMeta, score.isAcceptableOrUnknown(data['score']!, _scoreMeta)); } return context; } @override - Set get $primaryKey => {id}; + Set get $primaryKey => {messageId, type, userId}; @override - UserEntity map(Map data, {String? tablePrefix}) { + ReactionEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return UserEntity( - id: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}id'])!, - role: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}role']), - language: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}language']), + return ReactionEntity( + userId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, + messageId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}message_id'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, createdAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at']), - updatedAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at']), - lastActive: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}last_active']), - online: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}online'])!, - banned: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}banned'])!, - teamsRole: $UsersTable.$converterteamsRolen.fromSql(attachedDatabase - .typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}teams_role'])), - extraData: $UsersTable.$converterextraData.fromSql(attachedDatabase + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + score: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}score'])!, + extraData: $ReactionsTable.$converterextraDatan.fromSql(attachedDatabase .typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])!), + .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), ); } @override - $UsersTable createAlias(String alias) { - return $UsersTable(attachedDatabase, alias); + $ReactionsTable createAlias(String alias) { + return $ReactionsTable(attachedDatabase, alias); } - static TypeConverter, String> $converterteamsRole = - MapConverter(); - static TypeConverter?, String?> $converterteamsRolen = - NullAwareTypeConverter.wrap($converterteamsRole); static TypeConverter, String> $converterextraData = MapConverter(); -} - -class UserEntity extends DataClass implements Insertable { - /// User id - final String id; - - /// User role - final String? role; - - /// The language this user prefers. - final String? language; - - /// Date of user creation - final DateTime? createdAt; + static TypeConverter?, String?> $converterextraDatan = + NullAwareTypeConverter.wrap($converterextraData); +} - /// Date of last user update - final DateTime? updatedAt; +class ReactionEntity extends DataClass implements Insertable { + /// The id of the user that sent the reaction + final String userId; - /// Date of last user connection - final DateTime? lastActive; + /// The messageId to which the reaction belongs + final String messageId; - /// True if user is online - final bool online; + /// The type of the reaction + final String type; - /// True if user is banned from the chat - final bool banned; + /// The DateTime on which the reaction is created + final DateTime createdAt; - /// The roles for the user in the teams. - /// - /// eg: `{'teamId': 'role', 'teamId2': 'role2'}` - final Map? teamsRole; + /// The score of the reaction (ie. number of reactions sent) + final int score; - /// Map of custom user extraData - final Map extraData; - const UserEntity( - {required this.id, - this.role, - this.language, - this.createdAt, - this.updatedAt, - this.lastActive, - required this.online, - required this.banned, - this.teamsRole, - required this.extraData}); + /// Reaction custom extraData + final Map? extraData; + const ReactionEntity( + {required this.userId, + required this.messageId, + required this.type, + required this.createdAt, + required this.score, + this.extraData}); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['id'] = Variable(id); - if (!nullToAbsent || role != null) { - map['role'] = Variable(role); - } - if (!nullToAbsent || language != null) { - map['language'] = Variable(language); - } - 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); - } - map['online'] = Variable(online); - map['banned'] = Variable(banned); - if (!nullToAbsent || teamsRole != null) { - map['teams_role'] = - Variable($UsersTable.$converterteamsRolen.toSql(teamsRole)); - } - { - map['extra_data'] = - Variable($UsersTable.$converterextraData.toSql(extraData)); + map['user_id'] = Variable(userId); + map['message_id'] = Variable(messageId); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['score'] = Variable(score); + if (!nullToAbsent || extraData != null) { + map['extra_data'] = Variable( + $ReactionsTable.$converterextraDatan.toSql(extraData)); } return map; } - factory UserEntity.fromJson(Map json, + factory ReactionEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return UserEntity( - id: serializer.fromJson(json['id']), - role: serializer.fromJson(json['role']), - language: serializer.fromJson(json['language']), - 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']), - teamsRole: serializer.fromJson?>(json['teamsRole']), - extraData: serializer.fromJson>(json['extraData']), + 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 ??= driftRuntimeOptions.defaultSerializer; return { - 'id': serializer.toJson(id), - 'role': serializer.toJson(role), - 'language': serializer.toJson(language), - 'createdAt': serializer.toJson(createdAt), - 'updatedAt': serializer.toJson(updatedAt), - 'lastActive': serializer.toJson(lastActive), - 'online': serializer.toJson(online), - 'banned': serializer.toJson(banned), - 'teamsRole': serializer.toJson?>(teamsRole), - 'extraData': serializer.toJson>(extraData), + 'userId': serializer.toJson(userId), + 'messageId': serializer.toJson(messageId), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'score': serializer.toJson(score), + 'extraData': serializer.toJson?>(extraData), }; } - UserEntity copyWith( - {String? id, - Value role = const Value.absent(), - Value language = const Value.absent(), - Value createdAt = const Value.absent(), - Value updatedAt = const Value.absent(), - Value lastActive = const Value.absent(), - bool? online, - bool? banned, - Value?> teamsRole = const Value.absent(), - Map? extraData}) => - UserEntity( - id: id ?? this.id, - role: role.present ? role.value : this.role, - language: language.present ? language.value : this.language, - createdAt: createdAt.present ? createdAt.value : this.createdAt, - updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, - lastActive: lastActive.present ? lastActive.value : this.lastActive, - online: online ?? this.online, - banned: banned ?? this.banned, - teamsRole: teamsRole.present ? teamsRole.value : this.teamsRole, - extraData: extraData ?? this.extraData, + ReactionEntity copyWith( + {String? userId, + String? messageId, + String? type, + DateTime? createdAt, + int? score, + Value?> extraData = const Value.absent()}) => + ReactionEntity( + userId: userId ?? this.userId, + messageId: messageId ?? this.messageId, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + score: score ?? this.score, + extraData: extraData.present ? extraData.value : this.extraData, ); - UserEntity copyWithCompanion(UsersCompanion data) { - return UserEntity( - id: data.id.present ? data.id.value : this.id, - role: data.role.present ? data.role.value : this.role, - language: data.language.present ? data.language.value : this.language, + ReactionEntity copyWithCompanion(ReactionsCompanion data) { + return ReactionEntity( + userId: data.userId.present ? data.userId.value : this.userId, + messageId: data.messageId.present ? data.messageId.value : this.messageId, + type: data.type.present ? data.type.value : this.type, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, - updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, - lastActive: - data.lastActive.present ? data.lastActive.value : this.lastActive, - online: data.online.present ? data.online.value : this.online, - banned: data.banned.present ? data.banned.value : this.banned, - teamsRole: data.teamsRole.present ? data.teamsRole.value : this.teamsRole, + score: data.score.present ? data.score.value : this.score, extraData: data.extraData.present ? data.extraData.value : this.extraData, ); } @override String toString() { - return (StringBuffer('UserEntity(') - ..write('id: $id, ') - ..write('role: $role, ') - ..write('language: $language, ') + return (StringBuffer('ReactionEntity(') + ..write('userId: $userId, ') + ..write('messageId: $messageId, ') + ..write('type: $type, ') ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('lastActive: $lastActive, ') - ..write('online: $online, ') - ..write('banned: $banned, ') - ..write('teamsRole: $teamsRole, ') + ..write('score: $score, ') ..write('extraData: $extraData') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(id, role, language, createdAt, updatedAt, - lastActive, online, banned, teamsRole, extraData); + int get hashCode => + Object.hash(userId, messageId, type, createdAt, score, extraData); @override bool operator ==(Object other) => identical(this, other) || - (other is UserEntity && - other.id == this.id && - other.role == this.role && - other.language == this.language && + (other is ReactionEntity && + other.userId == this.userId && + other.messageId == this.messageId && + other.type == this.type && other.createdAt == this.createdAt && - other.updatedAt == this.updatedAt && - other.lastActive == this.lastActive && - other.online == this.online && - other.banned == this.banned && - other.teamsRole == this.teamsRole && + other.score == this.score && other.extraData == this.extraData); } -class UsersCompanion extends UpdateCompanion { - final Value id; - final Value role; - final Value language; - final Value createdAt; - final Value updatedAt; - final Value lastActive; - final Value online; - final Value banned; - final Value?> teamsRole; - final Value> extraData; +class ReactionsCompanion extends UpdateCompanion { + final Value userId; + final Value messageId; + final Value type; + final Value createdAt; + final Value score; + final Value?> extraData; final Value rowid; - const UsersCompanion({ - this.id = const Value.absent(), - this.role = const Value.absent(), - this.language = const Value.absent(), + const ReactionsCompanion({ + this.userId = const Value.absent(), + this.messageId = const Value.absent(), + this.type = 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.teamsRole = const Value.absent(), + this.score = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); - UsersCompanion.insert({ - required String id, - this.role = const Value.absent(), - this.language = const Value.absent(), + ReactionsCompanion.insert({ + required String userId, + required String messageId, + required String type, 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.teamsRole = const Value.absent(), - required Map extraData, + this.score = const Value.absent(), + this.extraData = const Value.absent(), this.rowid = const Value.absent(), - }) : id = Value(id), - extraData = Value(extraData); - static Insertable custom({ - Expression? id, - Expression? role, - Expression? language, + }) : userId = Value(userId), + messageId = Value(messageId), + type = Value(type); + static Insertable custom({ + Expression? userId, + Expression? messageId, + Expression? type, Expression? createdAt, - Expression? updatedAt, - Expression? lastActive, - Expression? online, - Expression? banned, - Expression? teamsRole, + Expression? score, Expression? extraData, Expression? rowid, }) { return RawValuesInsertable({ - if (id != null) 'id': id, - if (role != null) 'role': role, - if (language != null) 'language': language, + if (userId != null) 'user_id': userId, + if (messageId != null) 'message_id': messageId, + if (type != null) 'type': type, 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 (teamsRole != null) 'teams_role': teamsRole, + if (score != null) 'score': score, if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, }); } - UsersCompanion copyWith( - {Value? id, - Value? role, - Value? language, - Value? createdAt, - Value? updatedAt, - Value? lastActive, - Value? online, - Value? banned, - Value?>? teamsRole, - Value>? extraData, + ReactionsCompanion copyWith( + {Value? userId, + Value? messageId, + Value? type, + Value? createdAt, + Value? score, + Value?>? extraData, Value? rowid}) { - return UsersCompanion( - id: id ?? this.id, - role: role ?? this.role, - language: language ?? this.language, + return ReactionsCompanion( + userId: userId ?? this.userId, + messageId: messageId ?? this.messageId, + type: type ?? this.type, createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - lastActive: lastActive ?? this.lastActive, - online: online ?? this.online, - banned: banned ?? this.banned, - teamsRole: teamsRole ?? this.teamsRole, + score: score ?? this.score, extraData: extraData ?? this.extraData, rowid: rowid ?? this.rowid, ); @@ -6663,37 +6648,24 @@ class UsersCompanion extends UpdateCompanion { @override Map toColumns(bool nullToAbsent) { final map = {}; - if (id.present) { - map['id'] = Variable(id.value); + if (userId.present) { + map['user_id'] = Variable(userId.value); } - if (role.present) { - map['role'] = Variable(role.value); + if (messageId.present) { + map['message_id'] = Variable(messageId.value); } - if (language.present) { - map['language'] = Variable(language.value); + if (type.present) { + map['type'] = Variable(type.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 (teamsRole.present) { - map['teams_role'] = Variable( - $UsersTable.$converterteamsRolen.toSql(teamsRole.value)); + if (score.present) { + map['score'] = Variable(score.value); } if (extraData.present) { map['extra_data'] = Variable( - $UsersTable.$converterextraData.toSql(extraData.value)); + $ReactionsTable.$converterextraDatan.toSql(extraData.value)); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -6703,16 +6675,12 @@ class UsersCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('UsersCompanion(') - ..write('id: $id, ') - ..write('role: $role, ') - ..write('language: $language, ') + return (StringBuffer('ReactionsCompanion(') + ..write('userId: $userId, ') + ..write('messageId: $messageId, ') + ..write('type: $type, ') ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt, ') - ..write('lastActive: $lastActive, ') - ..write('online: $online, ') - ..write('banned: $banned, ') - ..write('teamsRole: $teamsRole, ') + ..write('score: $score, ') ..write('extraData: $extraData, ') ..write('rowid: $rowid') ..write(')')) @@ -6720,53 +6688,53 @@ class UsersCompanion extends UpdateCompanion { } } -class $MembersTable extends Members - with TableInfo<$MembersTable, MemberEntity> { +class $UsersTable extends Users with TableInfo<$UsersTable, UserEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $MembersTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); + $UsersTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); @override - late final GeneratedColumn userId = GeneratedColumn( - 'user_id', aliasedName, false, + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _channelCidMeta = - const VerificationMeta('channelCid'); + static const VerificationMeta _roleMeta = const VerificationMeta('role'); @override - late final GeneratedColumn channelCid = GeneratedColumn( - 'channel_cid', aliasedName, false, - type: DriftSqlType.string, - requiredDuringInsert: true, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'REFERENCES channels (cid) ON DELETE CASCADE')); - static const VerificationMeta _channelRoleMeta = - const VerificationMeta('channelRole'); + late final GeneratedColumn role = GeneratedColumn( + 'role', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _languageMeta = + const VerificationMeta('language'); @override - late final GeneratedColumn channelRole = GeneratedColumn( - 'channel_role', aliasedName, true, + late final GeneratedColumn language = GeneratedColumn( + 'language', aliasedName, true, type: DriftSqlType.string, requiredDuringInsert: false); - static const VerificationMeta _inviteAcceptedAtMeta = - const VerificationMeta('inviteAcceptedAt'); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); @override - late final GeneratedColumn inviteAcceptedAt = - GeneratedColumn('invite_accepted_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _inviteRejectedAtMeta = - const VerificationMeta('inviteRejectedAt'); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); @override - late final GeneratedColumn inviteRejectedAt = - GeneratedColumn('invite_rejected_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _invitedMeta = - const VerificationMeta('invited'); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _lastActiveMeta = + const VerificationMeta('lastActive'); @override - late final GeneratedColumn invited = GeneratedColumn( - 'invited', aliasedName, false, + late final GeneratedColumn lastActive = GeneratedColumn( + 'last_active', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _onlineMeta = const VerificationMeta('online'); + @override + late final GeneratedColumn online = GeneratedColumn( + 'online', aliasedName, false, type: DriftSqlType.bool, requiredDuringInsert: false, defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("invited" IN (0, 1))'), + GeneratedColumn.constraintIsAlways('CHECK ("online" IN (0, 1))'), defaultValue: const Constant(false)); static const VerificationMeta _bannedMeta = const VerificationMeta('banned'); @override @@ -6777,152 +6745,52 @@ class $MembersTable extends Members defaultConstraints: GeneratedColumn.constraintIsAlways('CHECK ("banned" IN (0, 1))'), defaultValue: const Constant(false)); - static const VerificationMeta _shadowBannedMeta = - const VerificationMeta('shadowBanned'); - @override - late final GeneratedColumn shadowBanned = GeneratedColumn( - 'shadow_banned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("shadow_banned" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _pinnedAtMeta = - const VerificationMeta('pinnedAt'); @override - late final GeneratedColumn pinnedAt = GeneratedColumn( - 'pinned_at', aliasedName, true, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: const Constant(null)); - static const VerificationMeta _archivedAtMeta = - const VerificationMeta('archivedAt'); + late final GeneratedColumnWithTypeConverter?, String> + teamsRole = GeneratedColumn('teams_role', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $UsersTable.$converterteamsRolen); @override - late final GeneratedColumn archivedAt = GeneratedColumn( - 'archived_at', aliasedName, true, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: const Constant(null)); - static const VerificationMeta _isModeratorMeta = - const VerificationMeta('isModerator'); + late final GeneratedColumnWithTypeConverter, String> + extraData = GeneratedColumn('extra_data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter>($UsersTable.$converterextraData); @override - late final GeneratedColumn isModerator = GeneratedColumn( - 'is_moderator', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("is_moderator" IN (0, 1))'), - defaultValue: const Constant(false)); + List get $columns => [ + id, + role, + language, + createdAt, + updatedAt, + lastActive, + online, + banned, + teamsRole, + extraData + ]; @override - late final GeneratedColumnWithTypeConverter?, String> - extraData = GeneratedColumn('extra_data', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $MembersTable.$converterextraDatan); - static const VerificationMeta _createdAtMeta = - const VerificationMeta('createdAt'); + String get aliasedName => _alias ?? actualTableName; @override - late final GeneratedColumn createdAt = GeneratedColumn( - 'created_at', aliasedName, false, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: currentDateAndTime); - static const VerificationMeta _updatedAtMeta = - const VerificationMeta('updatedAt'); + String get actualTableName => $name; + static const String $name = 'users'; @override - late final GeneratedColumn updatedAt = GeneratedColumn( - 'updated_at', aliasedName, false, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: currentDateAndTime); - @override - List get $columns => [ - userId, - channelCid, - channelRole, - inviteAcceptedAt, - inviteRejectedAt, - invited, - banned, - shadowBanned, - pinnedAt, - archivedAt, - isModerator, - extraData, - createdAt, - updatedAt - ]; - @override - String get aliasedName => _alias ?? actualTableName; - @override - String get actualTableName => $name; - static const String $name = 'members'; - @override - VerificationContext validateIntegrity(Insertable instance, + 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)); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); } else if (isInserting) { - context.missing(_channelCidMeta); - } - if (data.containsKey('channel_role')) { - context.handle( - _channelRoleMeta, - channelRole.isAcceptableOrUnknown( - data['channel_role']!, _channelRoleMeta)); - } - 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('pinned_at')) { - context.handle(_pinnedAtMeta, - pinnedAt.isAcceptableOrUnknown(data['pinned_at']!, _pinnedAtMeta)); + context.missing(_idMeta); } - if (data.containsKey('archived_at')) { + if (data.containsKey('role')) { context.handle( - _archivedAtMeta, - archivedAt.isAcceptableOrUnknown( - data['archived_at']!, _archivedAtMeta)); + _roleMeta, role.isAcceptableOrUnknown(data['role']!, _roleMeta)); } - if (data.containsKey('is_moderator')) { - context.handle( - _isModeratorMeta, - isModerator.isAcceptableOrUnknown( - data['is_moderator']!, _isModeratorMeta)); + if (data.containsKey('language')) { + context.handle(_languageMeta, + language.isAcceptableOrUnknown(data['language']!, _languageMeta)); } if (data.containsKey('created_at')) { context.handle(_createdAtMeta, @@ -6932,430 +6800,340 @@ class $MembersTable extends Members 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)); + } return context; } @override - Set get $primaryKey => {userId, channelCid}; + Set get $primaryKey => {id}; @override - MemberEntity map(Map data, {String? tablePrefix}) { + UserEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return MemberEntity( - userId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, - channelCid: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}channel_cid'])!, - channelRole: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}channel_role']), - inviteAcceptedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}invite_accepted_at']), - inviteRejectedAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, data['${effectivePrefix}invite_rejected_at']), - invited: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}invited'])!, + return UserEntity( + id: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}id'])!, + role: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}role']), + language: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}language']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at']), + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at']), + lastActive: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}last_active']), + online: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}online'])!, banned: attachedDatabase.typeMapping .read(DriftSqlType.bool, data['${effectivePrefix}banned'])!, - shadowBanned: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}shadow_banned'])!, - pinnedAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}pinned_at']), - archivedAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}archived_at']), - isModerator: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}is_moderator'])!, - extraData: $MembersTable.$converterextraDatan.fromSql(attachedDatabase + teamsRole: $UsersTable.$converterteamsRolen.fromSql(attachedDatabase .typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), - createdAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, - updatedAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + .read(DriftSqlType.string, data['${effectivePrefix}teams_role'])), + extraData: $UsersTable.$converterextraData.fromSql(attachedDatabase + .typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])!), ); } @override - $MembersTable createAlias(String alias) { - return $MembersTable(attachedDatabase, alias); + $UsersTable createAlias(String alias) { + return $UsersTable(attachedDatabase, alias); } + static TypeConverter, String> $converterteamsRole = + MapConverter(); + static TypeConverter?, String?> $converterteamsRolen = + NullAwareTypeConverter.wrap($converterteamsRole); static TypeConverter, String> $converterextraData = MapConverter(); - static TypeConverter?, String?> $converterextraDatan = - NullAwareTypeConverter.wrap($converterextraData); } -class MemberEntity extends DataClass implements Insertable { - /// The interested user id - final String userId; - - /// The channel cid of which this user is part of - final String channelCid; - - /// The role of the user in the channel - final String? channelRole; - - /// The date on which the user accepted the invite to the channel - final DateTime? inviteAcceptedAt; - - /// The date on which the user rejected the invite to the channel - final DateTime? inviteRejectedAt; +class UserEntity extends DataClass implements Insertable { + /// User id + final String id; - /// True if the user has been invited to the channel - final bool invited; + /// User role + final String? role; - /// True if the member is banned from the channel - final bool banned; + /// The language this user prefers. + final String? language; - /// True if the member is shadow banned from the channel - final bool shadowBanned; + /// Date of user creation + final DateTime? createdAt; - /// The date at which the channel was pinned by the member - final DateTime? pinnedAt; + /// Date of last user update + final DateTime? updatedAt; - /// The date at which the channel was archived by the member - final DateTime? archivedAt; + /// Date of last user connection + final DateTime? lastActive; - /// True if the user is a moderator of the channel - final bool isModerator; + /// True if user is online + final bool online; - /// Map of custom member extraData - final Map? extraData; + /// True if user is banned from the chat + final bool banned; - /// The date of creation - final DateTime createdAt; + /// The roles for the user in the teams. + /// + /// eg: `{'teamId': 'role', 'teamId2': 'role2'}` + final Map? teamsRole; - /// The last date of update - final DateTime updatedAt; - const MemberEntity( - {required this.userId, - required this.channelCid, - this.channelRole, - this.inviteAcceptedAt, - this.inviteRejectedAt, - required this.invited, + /// Map of custom user extraData + final Map extraData; + const UserEntity( + {required this.id, + this.role, + this.language, + this.createdAt, + this.updatedAt, + this.lastActive, + required this.online, required this.banned, - required this.shadowBanned, - this.pinnedAt, - this.archivedAt, - required this.isModerator, - this.extraData, - required this.createdAt, - required this.updatedAt}); + this.teamsRole, + required this.extraData}); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['user_id'] = Variable(userId); - map['channel_cid'] = Variable(channelCid); - if (!nullToAbsent || channelRole != null) { - map['channel_role'] = Variable(channelRole); - } - if (!nullToAbsent || inviteAcceptedAt != null) { - map['invite_accepted_at'] = Variable(inviteAcceptedAt); + map['id'] = Variable(id); + if (!nullToAbsent || role != null) { + map['role'] = Variable(role); } - if (!nullToAbsent || inviteRejectedAt != null) { - map['invite_rejected_at'] = Variable(inviteRejectedAt); + if (!nullToAbsent || language != null) { + map['language'] = Variable(language); } - map['invited'] = Variable(invited); - map['banned'] = Variable(banned); - map['shadow_banned'] = Variable(shadowBanned); - if (!nullToAbsent || pinnedAt != null) { - map['pinned_at'] = Variable(pinnedAt); + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); } - if (!nullToAbsent || archivedAt != null) { - map['archived_at'] = Variable(archivedAt); + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); } - map['is_moderator'] = Variable(isModerator); - if (!nullToAbsent || extraData != null) { + if (!nullToAbsent || lastActive != null) { + map['last_active'] = Variable(lastActive); + } + map['online'] = Variable(online); + map['banned'] = Variable(banned); + if (!nullToAbsent || teamsRole != null) { + map['teams_role'] = + Variable($UsersTable.$converterteamsRolen.toSql(teamsRole)); + } + { map['extra_data'] = - Variable($MembersTable.$converterextraDatan.toSql(extraData)); + Variable($UsersTable.$converterextraData.toSql(extraData)); } - map['created_at'] = Variable(createdAt); - map['updated_at'] = Variable(updatedAt); return map; } - factory MemberEntity.fromJson(Map json, + factory UserEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return MemberEntity( - userId: serializer.fromJson(json['userId']), - channelCid: serializer.fromJson(json['channelCid']), - channelRole: serializer.fromJson(json['channelRole']), - inviteAcceptedAt: - serializer.fromJson(json['inviteAcceptedAt']), - inviteRejectedAt: - serializer.fromJson(json['inviteRejectedAt']), - invited: serializer.fromJson(json['invited']), + return UserEntity( + id: serializer.fromJson(json['id']), + role: serializer.fromJson(json['role']), + language: serializer.fromJson(json['language']), + 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']), - shadowBanned: serializer.fromJson(json['shadowBanned']), - pinnedAt: serializer.fromJson(json['pinnedAt']), - archivedAt: serializer.fromJson(json['archivedAt']), - isModerator: serializer.fromJson(json['isModerator']), - extraData: serializer.fromJson?>(json['extraData']), - createdAt: serializer.fromJson(json['createdAt']), - updatedAt: serializer.fromJson(json['updatedAt']), + teamsRole: serializer.fromJson?>(json['teamsRole']), + extraData: serializer.fromJson>(json['extraData']), ); } @override Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'userId': serializer.toJson(userId), - 'channelCid': serializer.toJson(channelCid), - 'channelRole': serializer.toJson(channelRole), - 'inviteAcceptedAt': serializer.toJson(inviteAcceptedAt), - 'inviteRejectedAt': serializer.toJson(inviteRejectedAt), - 'invited': serializer.toJson(invited), + 'id': serializer.toJson(id), + 'role': serializer.toJson(role), + 'language': serializer.toJson(language), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'lastActive': serializer.toJson(lastActive), + 'online': serializer.toJson(online), 'banned': serializer.toJson(banned), - 'shadowBanned': serializer.toJson(shadowBanned), - 'pinnedAt': serializer.toJson(pinnedAt), - 'archivedAt': serializer.toJson(archivedAt), - 'isModerator': serializer.toJson(isModerator), - 'extraData': serializer.toJson?>(extraData), - 'createdAt': serializer.toJson(createdAt), - 'updatedAt': serializer.toJson(updatedAt), + 'teamsRole': serializer.toJson?>(teamsRole), + 'extraData': serializer.toJson>(extraData), }; } - MemberEntity copyWith( - {String? userId, - String? channelCid, - Value channelRole = const Value.absent(), - Value inviteAcceptedAt = const Value.absent(), - Value inviteRejectedAt = const Value.absent(), - bool? invited, + UserEntity copyWith( + {String? id, + Value role = const Value.absent(), + Value language = const Value.absent(), + Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), + Value lastActive = const Value.absent(), + bool? online, bool? banned, - bool? shadowBanned, - Value pinnedAt = const Value.absent(), - Value archivedAt = const Value.absent(), - bool? isModerator, - Value?> extraData = const Value.absent(), - DateTime? createdAt, - DateTime? updatedAt}) => - MemberEntity( - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - channelRole: channelRole.present ? channelRole.value : this.channelRole, - inviteAcceptedAt: inviteAcceptedAt.present - ? inviteAcceptedAt.value - : this.inviteAcceptedAt, - inviteRejectedAt: inviteRejectedAt.present - ? inviteRejectedAt.value - : this.inviteRejectedAt, - invited: invited ?? this.invited, + Value?> teamsRole = const Value.absent(), + Map? extraData}) => + UserEntity( + id: id ?? this.id, + role: role.present ? role.value : this.role, + language: language.present ? language.value : this.language, + createdAt: createdAt.present ? createdAt.value : this.createdAt, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + lastActive: lastActive.present ? lastActive.value : this.lastActive, + online: online ?? this.online, banned: banned ?? this.banned, - shadowBanned: shadowBanned ?? this.shadowBanned, - pinnedAt: pinnedAt.present ? pinnedAt.value : this.pinnedAt, - archivedAt: archivedAt.present ? archivedAt.value : this.archivedAt, - isModerator: isModerator ?? this.isModerator, - extraData: extraData.present ? extraData.value : this.extraData, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, + teamsRole: teamsRole.present ? teamsRole.value : this.teamsRole, + extraData: extraData ?? this.extraData, ); - MemberEntity copyWithCompanion(MembersCompanion data) { - return MemberEntity( - userId: data.userId.present ? data.userId.value : this.userId, - channelCid: - data.channelCid.present ? data.channelCid.value : this.channelCid, - channelRole: - data.channelRole.present ? data.channelRole.value : this.channelRole, - inviteAcceptedAt: data.inviteAcceptedAt.present - ? data.inviteAcceptedAt.value - : this.inviteAcceptedAt, - inviteRejectedAt: data.inviteRejectedAt.present - ? data.inviteRejectedAt.value - : this.inviteRejectedAt, - invited: data.invited.present ? data.invited.value : this.invited, - banned: data.banned.present ? data.banned.value : this.banned, - shadowBanned: data.shadowBanned.present - ? data.shadowBanned.value - : this.shadowBanned, - pinnedAt: data.pinnedAt.present ? data.pinnedAt.value : this.pinnedAt, - archivedAt: - data.archivedAt.present ? data.archivedAt.value : this.archivedAt, - isModerator: - data.isModerator.present ? data.isModerator.value : this.isModerator, - extraData: data.extraData.present ? data.extraData.value : this.extraData, + UserEntity copyWithCompanion(UsersCompanion data) { + return UserEntity( + id: data.id.present ? data.id.value : this.id, + role: data.role.present ? data.role.value : this.role, + language: data.language.present ? data.language.value : this.language, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + lastActive: + data.lastActive.present ? data.lastActive.value : this.lastActive, + online: data.online.present ? data.online.value : this.online, + banned: data.banned.present ? data.banned.value : this.banned, + teamsRole: data.teamsRole.present ? data.teamsRole.value : this.teamsRole, + extraData: data.extraData.present ? data.extraData.value : this.extraData, ); } @override String toString() { - return (StringBuffer('MemberEntity(') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('channelRole: $channelRole, ') - ..write('inviteAcceptedAt: $inviteAcceptedAt, ') - ..write('inviteRejectedAt: $inviteRejectedAt, ') - ..write('invited: $invited, ') - ..write('banned: $banned, ') - ..write('shadowBanned: $shadowBanned, ') - ..write('pinnedAt: $pinnedAt, ') - ..write('archivedAt: $archivedAt, ') - ..write('isModerator: $isModerator, ') - ..write('extraData: $extraData, ') + return (StringBuffer('UserEntity(') + ..write('id: $id, ') + ..write('role: $role, ') + ..write('language: $language, ') ..write('createdAt: $createdAt, ') - ..write('updatedAt: $updatedAt') + ..write('updatedAt: $updatedAt, ') + ..write('lastActive: $lastActive, ') + ..write('online: $online, ') + ..write('banned: $banned, ') + ..write('teamsRole: $teamsRole, ') + ..write('extraData: $extraData') ..write(')')) .toString(); } @override - int get hashCode => Object.hash( - userId, - channelCid, - channelRole, - inviteAcceptedAt, - inviteRejectedAt, - invited, - banned, - shadowBanned, - pinnedAt, - archivedAt, - isModerator, - extraData, - createdAt, - updatedAt); + int get hashCode => Object.hash(id, role, language, createdAt, updatedAt, + lastActive, online, banned, teamsRole, extraData); @override bool operator ==(Object other) => identical(this, other) || - (other is MemberEntity && - other.userId == this.userId && - other.channelCid == this.channelCid && - other.channelRole == this.channelRole && - other.inviteAcceptedAt == this.inviteAcceptedAt && - other.inviteRejectedAt == this.inviteRejectedAt && - other.invited == this.invited && - other.banned == this.banned && - other.shadowBanned == this.shadowBanned && - other.pinnedAt == this.pinnedAt && - other.archivedAt == this.archivedAt && - other.isModerator == this.isModerator && - other.extraData == this.extraData && + (other is UserEntity && + other.id == this.id && + other.role == this.role && + other.language == this.language && other.createdAt == this.createdAt && - other.updatedAt == this.updatedAt); + other.updatedAt == this.updatedAt && + other.lastActive == this.lastActive && + other.online == this.online && + other.banned == this.banned && + other.teamsRole == this.teamsRole && + other.extraData == this.extraData); } -class MembersCompanion extends UpdateCompanion { - final Value userId; - final Value channelCid; - final Value channelRole; - final Value inviteAcceptedAt; - final Value inviteRejectedAt; - final Value invited; +class UsersCompanion extends UpdateCompanion { + final Value id; + final Value role; + final Value language; + final Value createdAt; + final Value updatedAt; + final Value lastActive; + final Value online; final Value banned; - final Value shadowBanned; - final Value pinnedAt; - final Value archivedAt; - final Value isModerator; - final Value?> extraData; - final Value createdAt; - final Value updatedAt; - final Value rowid; - const MembersCompanion({ - this.userId = const Value.absent(), - this.channelCid = const Value.absent(), - this.channelRole = 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.pinnedAt = const Value.absent(), - this.archivedAt = const Value.absent(), - this.isModerator = const Value.absent(), - this.extraData = const Value.absent(), + final Value?> teamsRole; + final Value> extraData; + final Value rowid; + const UsersCompanion({ + this.id = const Value.absent(), + this.role = const Value.absent(), + this.language = const Value.absent(), this.createdAt = const Value.absent(), this.updatedAt = const Value.absent(), - this.rowid = const Value.absent(), - }); - MembersCompanion.insert({ - required String userId, - required String channelCid, - this.channelRole = const Value.absent(), - this.inviteAcceptedAt = const Value.absent(), - this.inviteRejectedAt = const Value.absent(), - this.invited = const Value.absent(), + this.lastActive = const Value.absent(), + this.online = const Value.absent(), this.banned = const Value.absent(), - this.shadowBanned = const Value.absent(), - this.pinnedAt = const Value.absent(), - this.archivedAt = const Value.absent(), - this.isModerator = const Value.absent(), + this.teamsRole = const Value.absent(), this.extraData = const Value.absent(), + this.rowid = const Value.absent(), + }); + UsersCompanion.insert({ + required String id, + this.role = const Value.absent(), + this.language = 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.teamsRole = const Value.absent(), + required Map extraData, this.rowid = const Value.absent(), - }) : userId = Value(userId), - channelCid = Value(channelCid); - static Insertable custom({ - Expression? userId, - Expression? channelCid, - Expression? channelRole, - Expression? inviteAcceptedAt, - Expression? inviteRejectedAt, - Expression? invited, - Expression? banned, - Expression? shadowBanned, - Expression? pinnedAt, - Expression? archivedAt, - Expression? isModerator, - Expression? extraData, + }) : id = Value(id), + extraData = Value(extraData); + static Insertable custom({ + Expression? id, + Expression? role, + Expression? language, Expression? createdAt, Expression? updatedAt, + Expression? lastActive, + Expression? online, + Expression? banned, + Expression? teamsRole, + Expression? extraData, Expression? rowid, }) { return RawValuesInsertable({ - if (userId != null) 'user_id': userId, - if (channelCid != null) 'channel_cid': channelCid, - if (channelRole != null) 'channel_role': channelRole, - 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 (pinnedAt != null) 'pinned_at': pinnedAt, - if (archivedAt != null) 'archived_at': archivedAt, - if (isModerator != null) 'is_moderator': isModerator, - if (extraData != null) 'extra_data': extraData, + if (id != null) 'id': id, + if (role != null) 'role': role, + if (language != null) 'language': language, 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 (teamsRole != null) 'teams_role': teamsRole, + if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, }); } - MembersCompanion copyWith( - {Value? userId, - Value? channelCid, - Value? channelRole, - Value? inviteAcceptedAt, - Value? inviteRejectedAt, - Value? invited, + UsersCompanion copyWith( + {Value? id, + Value? role, + Value? language, + Value? createdAt, + Value? updatedAt, + Value? lastActive, + Value? online, Value? banned, - Value? shadowBanned, - Value? pinnedAt, - Value? archivedAt, - Value? isModerator, - Value?>? extraData, - Value? createdAt, - Value? updatedAt, + Value?>? teamsRole, + Value>? extraData, Value? rowid}) { - return MembersCompanion( - userId: userId ?? this.userId, - channelCid: channelCid ?? this.channelCid, - channelRole: channelRole ?? this.channelRole, - inviteAcceptedAt: inviteAcceptedAt ?? this.inviteAcceptedAt, - inviteRejectedAt: inviteRejectedAt ?? this.inviteRejectedAt, - invited: invited ?? this.invited, - banned: banned ?? this.banned, - shadowBanned: shadowBanned ?? this.shadowBanned, - pinnedAt: pinnedAt ?? this.pinnedAt, - archivedAt: archivedAt ?? this.archivedAt, - isModerator: isModerator ?? this.isModerator, - extraData: extraData ?? this.extraData, + return UsersCompanion( + id: id ?? this.id, + role: role ?? this.role, + language: language ?? this.language, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, + lastActive: lastActive ?? this.lastActive, + online: online ?? this.online, + banned: banned ?? this.banned, + teamsRole: teamsRole ?? this.teamsRole, + extraData: extraData ?? this.extraData, rowid: rowid ?? this.rowid, ); } @@ -7363,48 +7141,37 @@ class MembersCompanion extends UpdateCompanion { @override Map toColumns(bool nullToAbsent) { final map = {}; - if (userId.present) { - map['user_id'] = Variable(userId.value); + if (id.present) { + map['id'] = Variable(id.value); } - if (channelCid.present) { - map['channel_cid'] = Variable(channelCid.value); + if (role.present) { + map['role'] = Variable(role.value); } - if (channelRole.present) { - map['channel_role'] = Variable(channelRole.value); + if (language.present) { + map['language'] = Variable(language.value); } - if (inviteAcceptedAt.present) { - map['invite_accepted_at'] = Variable(inviteAcceptedAt.value); + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); } - if (inviteRejectedAt.present) { - map['invite_rejected_at'] = Variable(inviteRejectedAt.value); + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); } - if (invited.present) { - map['invited'] = Variable(invited.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 (shadowBanned.present) { - map['shadow_banned'] = Variable(shadowBanned.value); - } - if (pinnedAt.present) { - map['pinned_at'] = Variable(pinnedAt.value); - } - if (archivedAt.present) { - map['archived_at'] = Variable(archivedAt.value); - } - if (isModerator.present) { - map['is_moderator'] = Variable(isModerator.value); + if (teamsRole.present) { + map['teams_role'] = Variable( + $UsersTable.$converterteamsRolen.toSql(teamsRole.value)); } if (extraData.present) { map['extra_data'] = Variable( - $MembersTable.$converterextraDatan.toSql(extraData.value)); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (updatedAt.present) { - map['updated_at'] = Variable(updatedAt.value); + $UsersTable.$converterextraData.toSql(extraData.value)); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -7414,38 +7181,29 @@ class MembersCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('MembersCompanion(') - ..write('userId: $userId, ') - ..write('channelCid: $channelCid, ') - ..write('channelRole: $channelRole, ') - ..write('inviteAcceptedAt: $inviteAcceptedAt, ') - ..write('inviteRejectedAt: $inviteRejectedAt, ') - ..write('invited: $invited, ') - ..write('banned: $banned, ') - ..write('shadowBanned: $shadowBanned, ') - ..write('pinnedAt: $pinnedAt, ') - ..write('archivedAt: $archivedAt, ') - ..write('isModerator: $isModerator, ') - ..write('extraData: $extraData, ') + return (StringBuffer('UsersCompanion(') + ..write('id: $id, ') + ..write('role: $role, ') + ..write('language: $language, ') ..write('createdAt: $createdAt, ') ..write('updatedAt: $updatedAt, ') + ..write('lastActive: $lastActive, ') + ..write('online: $online, ') + ..write('banned: $banned, ') + ..write('teamsRole: $teamsRole, ') + ..write('extraData: $extraData, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } -class $ReadsTable extends Reads with TableInfo<$ReadsTable, ReadEntity> { +class $MembersTable extends Members + with TableInfo<$MembersTable, MemberEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $ReadsTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _lastReadMeta = - const VerificationMeta('lastRead'); - @override - late final GeneratedColumn lastRead = GeneratedColumn( - 'last_read', aliasedName, false, - type: DriftSqlType.dateTime, requiredDuringInsert: true); + $MembersTable(this.attachedDatabase, [this._alias]); static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); @override late final GeneratedColumn userId = GeneratedColumn( @@ -7460,39 +7218,128 @@ class $ReadsTable extends Reads with TableInfo<$ReadsTable, ReadEntity> { requiredDuringInsert: true, defaultConstraints: GeneratedColumn.constraintIsAlways( 'REFERENCES channels (cid) ON DELETE CASCADE')); - static const VerificationMeta _unreadMessagesMeta = - const VerificationMeta('unreadMessages'); - @override - late final GeneratedColumn unreadMessages = GeneratedColumn( - 'unread_messages', aliasedName, false, - type: DriftSqlType.int, - requiredDuringInsert: false, - defaultValue: const Constant(0)); - static const VerificationMeta _lastReadMessageIdMeta = - const VerificationMeta('lastReadMessageId'); + static const VerificationMeta _channelRoleMeta = + const VerificationMeta('channelRole'); @override - late final GeneratedColumn lastReadMessageId = - GeneratedColumn('last_read_message_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn channelRole = GeneratedColumn( + 'channel_role', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + static const VerificationMeta _inviteAcceptedAtMeta = + const VerificationMeta('inviteAcceptedAt'); @override - List get $columns => - [lastRead, userId, channelCid, unreadMessages, lastReadMessageId]; + late final GeneratedColumn inviteAcceptedAt = + GeneratedColumn('invite_accepted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _inviteRejectedAtMeta = + const VerificationMeta('inviteRejectedAt'); @override - String get aliasedName => _alias ?? actualTableName; + late final GeneratedColumn inviteRejectedAt = + GeneratedColumn('invite_rejected_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _invitedMeta = + const VerificationMeta('invited'); @override - String get actualTableName => $name; - static const String $name = 'reads'; + late final GeneratedColumn invited = GeneratedColumn( + 'invited', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("invited" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _bannedMeta = const VerificationMeta('banned'); @override - VerificationContext validateIntegrity(Insertable instance, + late final GeneratedColumn banned = GeneratedColumn( + 'banned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("banned" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _shadowBannedMeta = + const VerificationMeta('shadowBanned'); + @override + late final GeneratedColumn shadowBanned = GeneratedColumn( + 'shadow_banned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("shadow_banned" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _pinnedAtMeta = + const VerificationMeta('pinnedAt'); + @override + late final GeneratedColumn pinnedAt = GeneratedColumn( + 'pinned_at', aliasedName, true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const Constant(null)); + static const VerificationMeta _archivedAtMeta = + const VerificationMeta('archivedAt'); + @override + late final GeneratedColumn archivedAt = GeneratedColumn( + 'archived_at', aliasedName, true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const Constant(null)); + static const VerificationMeta _isModeratorMeta = + const VerificationMeta('isModerator'); + @override + late final GeneratedColumn isModerator = GeneratedColumn( + 'is_moderator', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_moderator" IN (0, 1))'), + defaultValue: const Constant(false)); + @override + late final GeneratedColumnWithTypeConverter?, String> + extraData = GeneratedColumn('extra_data', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $MembersTable.$converterextraDatan); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + static const VerificationMeta _updatedAtMeta = + const VerificationMeta('updatedAt'); + @override + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => [ + userId, + channelCid, + channelRole, + inviteAcceptedAt, + inviteRejectedAt, + invited, + banned, + shadowBanned, + pinnedAt, + archivedAt, + isModerator, + extraData, + createdAt, + updatedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'members'; + @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)); @@ -7507,17 +7354,61 @@ class $ReadsTable extends Reads with TableInfo<$ReadsTable, ReadEntity> { } else if (isInserting) { context.missing(_channelCidMeta); } - if (data.containsKey('unread_messages')) { + if (data.containsKey('channel_role')) { context.handle( - _unreadMessagesMeta, - unreadMessages.isAcceptableOrUnknown( - data['unread_messages']!, _unreadMessagesMeta)); + _channelRoleMeta, + channelRole.isAcceptableOrUnknown( + data['channel_role']!, _channelRoleMeta)); } - if (data.containsKey('last_read_message_id')) { + if (data.containsKey('invite_accepted_at')) { context.handle( - _lastReadMessageIdMeta, - lastReadMessageId.isAcceptableOrUnknown( - data['last_read_message_id']!, _lastReadMessageIdMeta)); + _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('pinned_at')) { + context.handle(_pinnedAtMeta, + pinnedAt.isAcceptableOrUnknown(data['pinned_at']!, _pinnedAtMeta)); + } + if (data.containsKey('archived_at')) { + context.handle( + _archivedAtMeta, + archivedAt.isAcceptableOrUnknown( + data['archived_at']!, _archivedAtMeta)); + } + 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)); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); } return context; } @@ -7525,198 +7416,424 @@ class $ReadsTable extends Reads with TableInfo<$ReadsTable, ReadEntity> { @override Set get $primaryKey => {userId, channelCid}; @override - ReadEntity map(Map data, {String? tablePrefix}) { + MemberEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return ReadEntity( - lastRead: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}last_read'])!, + return MemberEntity( userId: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, channelCid: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}channel_cid'])!, - unreadMessages: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}unread_messages'])!, - lastReadMessageId: attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}last_read_message_id']), + channelRole: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}channel_role']), + inviteAcceptedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}invite_accepted_at']), + inviteRejectedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}invite_rejected_at']), + invited: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}invited'])!, + banned: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}banned'])!, + shadowBanned: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}shadow_banned'])!, + pinnedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}pinned_at']), + archivedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}archived_at']), + isModerator: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}is_moderator'])!, + extraData: $MembersTable.$converterextraDatan.fromSql(attachedDatabase + .typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, ); } @override - $ReadsTable createAlias(String alias) { - return $ReadsTable(attachedDatabase, alias); + $MembersTable createAlias(String alias) { + return $MembersTable(attachedDatabase, alias); } -} -class ReadEntity extends DataClass implements Insertable { - /// Date of the read event - final DateTime lastRead; + static TypeConverter, String> $converterextraData = + MapConverter(); + static TypeConverter?, String?> $converterextraDatan = + NullAwareTypeConverter.wrap($converterextraData); +} - /// Id of the User who sent the event +class MemberEntity extends DataClass implements Insertable { + /// The interested user id final String userId; - /// The channel cid of which this read belongs + /// The channel cid of which this user is part of final String channelCid; - /// Number of unread messages - final int unreadMessages; + /// The role of the user in the channel + final String? channelRole; - /// Id of the last read message - final String? lastReadMessageId; - const ReadEntity( - {required this.lastRead, - required this.userId, - required this.channelCid, - required this.unreadMessages, - this.lastReadMessageId}); - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - map['last_read'] = Variable(lastRead); - map['user_id'] = Variable(userId); - map['channel_cid'] = Variable(channelCid); - map['unread_messages'] = Variable(unreadMessages); - if (!nullToAbsent || lastReadMessageId != null) { - map['last_read_message_id'] = Variable(lastReadMessageId); - } - return map; - } + /// The date on which the user accepted the invite to the channel + final DateTime? inviteAcceptedAt; - factory ReadEntity.fromJson(Map json, - {ValueSerializer? serializer}) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return ReadEntity( - lastRead: serializer.fromJson(json['lastRead']), - userId: serializer.fromJson(json['userId']), - channelCid: serializer.fromJson(json['channelCid']), - unreadMessages: serializer.fromJson(json['unreadMessages']), - lastReadMessageId: - serializer.fromJson(json['lastReadMessageId']), - ); - } - @override + /// The date on which the user rejected the invite to the channel + final DateTime? inviteRejectedAt; + + /// True if the user has been invited to the channel + final bool invited; + + /// True if the member is banned from the channel + final bool banned; + + /// True if the member is shadow banned from the channel + final bool shadowBanned; + + /// The date at which the channel was pinned by the member + final DateTime? pinnedAt; + + /// The date at which the channel was archived by the member + final DateTime? archivedAt; + + /// True if the user is a moderator of the channel + final bool isModerator; + + /// Map of custom member extraData + final Map? extraData; + + /// The date of creation + final DateTime createdAt; + + /// The last date of update + final DateTime updatedAt; + const MemberEntity( + {required this.userId, + required this.channelCid, + this.channelRole, + this.inviteAcceptedAt, + this.inviteRejectedAt, + required this.invited, + required this.banned, + required this.shadowBanned, + this.pinnedAt, + this.archivedAt, + required this.isModerator, + this.extraData, + required this.createdAt, + required this.updatedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['user_id'] = Variable(userId); + map['channel_cid'] = Variable(channelCid); + if (!nullToAbsent || channelRole != null) { + map['channel_role'] = Variable(channelRole); + } + if (!nullToAbsent || inviteAcceptedAt != null) { + map['invite_accepted_at'] = Variable(inviteAcceptedAt); + } + if (!nullToAbsent || inviteRejectedAt != null) { + map['invite_rejected_at'] = Variable(inviteRejectedAt); + } + map['invited'] = Variable(invited); + map['banned'] = Variable(banned); + map['shadow_banned'] = Variable(shadowBanned); + if (!nullToAbsent || pinnedAt != null) { + map['pinned_at'] = Variable(pinnedAt); + } + if (!nullToAbsent || archivedAt != null) { + map['archived_at'] = Variable(archivedAt); + } + map['is_moderator'] = Variable(isModerator); + if (!nullToAbsent || extraData != null) { + map['extra_data'] = + Variable($MembersTable.$converterextraDatan.toSql(extraData)); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + return map; + } + + factory MemberEntity.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemberEntity( + userId: serializer.fromJson(json['userId']), + channelCid: serializer.fromJson(json['channelCid']), + channelRole: serializer.fromJson(json['channelRole']), + 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']), + pinnedAt: serializer.fromJson(json['pinnedAt']), + archivedAt: serializer.fromJson(json['archivedAt']), + isModerator: serializer.fromJson(json['isModerator']), + extraData: serializer.fromJson?>(json['extraData']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ); + } + @override Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'lastRead': serializer.toJson(lastRead), 'userId': serializer.toJson(userId), 'channelCid': serializer.toJson(channelCid), - 'unreadMessages': serializer.toJson(unreadMessages), - 'lastReadMessageId': serializer.toJson(lastReadMessageId), + 'channelRole': serializer.toJson(channelRole), + 'inviteAcceptedAt': serializer.toJson(inviteAcceptedAt), + 'inviteRejectedAt': serializer.toJson(inviteRejectedAt), + 'invited': serializer.toJson(invited), + 'banned': serializer.toJson(banned), + 'shadowBanned': serializer.toJson(shadowBanned), + 'pinnedAt': serializer.toJson(pinnedAt), + 'archivedAt': serializer.toJson(archivedAt), + 'isModerator': serializer.toJson(isModerator), + 'extraData': serializer.toJson?>(extraData), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), }; } - ReadEntity copyWith( - {DateTime? lastRead, - String? userId, + MemberEntity copyWith( + {String? userId, String? channelCid, - int? unreadMessages, - Value lastReadMessageId = const Value.absent()}) => - ReadEntity( - lastRead: lastRead ?? this.lastRead, + Value channelRole = const Value.absent(), + Value inviteAcceptedAt = const Value.absent(), + Value inviteRejectedAt = const Value.absent(), + bool? invited, + bool? banned, + bool? shadowBanned, + Value pinnedAt = const Value.absent(), + Value archivedAt = const Value.absent(), + bool? isModerator, + Value?> extraData = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt}) => + MemberEntity( userId: userId ?? this.userId, channelCid: channelCid ?? this.channelCid, - unreadMessages: unreadMessages ?? this.unreadMessages, - lastReadMessageId: lastReadMessageId.present - ? lastReadMessageId.value - : this.lastReadMessageId, + channelRole: channelRole.present ? channelRole.value : this.channelRole, + inviteAcceptedAt: inviteAcceptedAt.present + ? inviteAcceptedAt.value + : this.inviteAcceptedAt, + inviteRejectedAt: inviteRejectedAt.present + ? inviteRejectedAt.value + : this.inviteRejectedAt, + invited: invited ?? this.invited, + banned: banned ?? this.banned, + shadowBanned: shadowBanned ?? this.shadowBanned, + pinnedAt: pinnedAt.present ? pinnedAt.value : this.pinnedAt, + archivedAt: archivedAt.present ? archivedAt.value : this.archivedAt, + isModerator: isModerator ?? this.isModerator, + extraData: extraData.present ? extraData.value : this.extraData, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, ); - ReadEntity copyWithCompanion(ReadsCompanion data) { - return ReadEntity( - lastRead: data.lastRead.present ? data.lastRead.value : this.lastRead, + MemberEntity copyWithCompanion(MembersCompanion data) { + return MemberEntity( userId: data.userId.present ? data.userId.value : this.userId, channelCid: data.channelCid.present ? data.channelCid.value : this.channelCid, - unreadMessages: data.unreadMessages.present - ? data.unreadMessages.value - : this.unreadMessages, - lastReadMessageId: data.lastReadMessageId.present - ? data.lastReadMessageId.value - : this.lastReadMessageId, + channelRole: + data.channelRole.present ? data.channelRole.value : this.channelRole, + inviteAcceptedAt: data.inviteAcceptedAt.present + ? data.inviteAcceptedAt.value + : this.inviteAcceptedAt, + inviteRejectedAt: data.inviteRejectedAt.present + ? data.inviteRejectedAt.value + : this.inviteRejectedAt, + invited: data.invited.present ? data.invited.value : this.invited, + banned: data.banned.present ? data.banned.value : this.banned, + shadowBanned: data.shadowBanned.present + ? data.shadowBanned.value + : this.shadowBanned, + pinnedAt: data.pinnedAt.present ? data.pinnedAt.value : this.pinnedAt, + archivedAt: + data.archivedAt.present ? data.archivedAt.value : this.archivedAt, + isModerator: + data.isModerator.present ? data.isModerator.value : this.isModerator, + extraData: data.extraData.present ? data.extraData.value : this.extraData, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, ); } @override String toString() { - return (StringBuffer('ReadEntity(') - ..write('lastRead: $lastRead, ') + return (StringBuffer('MemberEntity(') ..write('userId: $userId, ') ..write('channelCid: $channelCid, ') - ..write('unreadMessages: $unreadMessages, ') - ..write('lastReadMessageId: $lastReadMessageId') + ..write('channelRole: $channelRole, ') + ..write('inviteAcceptedAt: $inviteAcceptedAt, ') + ..write('inviteRejectedAt: $inviteRejectedAt, ') + ..write('invited: $invited, ') + ..write('banned: $banned, ') + ..write('shadowBanned: $shadowBanned, ') + ..write('pinnedAt: $pinnedAt, ') + ..write('archivedAt: $archivedAt, ') + ..write('isModerator: $isModerator, ') + ..write('extraData: $extraData, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') ..write(')')) .toString(); } @override int get hashCode => Object.hash( - lastRead, userId, channelCid, unreadMessages, lastReadMessageId); + userId, + channelCid, + channelRole, + inviteAcceptedAt, + inviteRejectedAt, + invited, + banned, + shadowBanned, + pinnedAt, + archivedAt, + isModerator, + extraData, + createdAt, + updatedAt); @override bool operator ==(Object other) => identical(this, other) || - (other is ReadEntity && - other.lastRead == this.lastRead && + (other is MemberEntity && other.userId == this.userId && other.channelCid == this.channelCid && - other.unreadMessages == this.unreadMessages && - other.lastReadMessageId == this.lastReadMessageId); + other.channelRole == this.channelRole && + other.inviteAcceptedAt == this.inviteAcceptedAt && + other.inviteRejectedAt == this.inviteRejectedAt && + other.invited == this.invited && + other.banned == this.banned && + other.shadowBanned == this.shadowBanned && + other.pinnedAt == this.pinnedAt && + other.archivedAt == this.archivedAt && + other.isModerator == this.isModerator && + other.extraData == this.extraData && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt); } -class ReadsCompanion extends UpdateCompanion { - final Value lastRead; +class MembersCompanion extends UpdateCompanion { final Value userId; final Value channelCid; - final Value unreadMessages; - final Value lastReadMessageId; + final Value channelRole; + final Value inviteAcceptedAt; + final Value inviteRejectedAt; + final Value invited; + final Value banned; + final Value shadowBanned; + final Value pinnedAt; + final Value archivedAt; + final Value isModerator; + final Value?> extraData; + final Value createdAt; + final Value updatedAt; final Value rowid; - const ReadsCompanion({ - this.lastRead = const Value.absent(), + const MembersCompanion({ this.userId = const Value.absent(), this.channelCid = const Value.absent(), - this.unreadMessages = const Value.absent(), - this.lastReadMessageId = const Value.absent(), + this.channelRole = 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.pinnedAt = const Value.absent(), + this.archivedAt = const Value.absent(), + this.isModerator = const Value.absent(), + this.extraData = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.rowid = const Value.absent(), }); - ReadsCompanion.insert({ - required DateTime lastRead, + MembersCompanion.insert({ required String userId, required String channelCid, - this.unreadMessages = const Value.absent(), - this.lastReadMessageId = const Value.absent(), + this.channelRole = 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.pinnedAt = const Value.absent(), + this.archivedAt = const Value.absent(), + this.isModerator = const Value.absent(), + this.extraData = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.rowid = const Value.absent(), - }) : lastRead = Value(lastRead), - userId = Value(userId), + }) : userId = Value(userId), channelCid = Value(channelCid); - static Insertable custom({ - Expression? lastRead, + static Insertable custom({ Expression? userId, Expression? channelCid, - Expression? unreadMessages, - Expression? lastReadMessageId, + Expression? channelRole, + Expression? inviteAcceptedAt, + Expression? inviteRejectedAt, + Expression? invited, + Expression? banned, + Expression? shadowBanned, + Expression? pinnedAt, + Expression? archivedAt, + Expression? isModerator, + Expression? extraData, + Expression? createdAt, + Expression? updatedAt, Expression? rowid, }) { 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, - if (lastReadMessageId != null) 'last_read_message_id': lastReadMessageId, + if (channelRole != null) 'channel_role': channelRole, + 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 (pinnedAt != null) 'pinned_at': pinnedAt, + if (archivedAt != null) 'archived_at': archivedAt, + if (isModerator != null) 'is_moderator': isModerator, + if (extraData != null) 'extra_data': extraData, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, if (rowid != null) 'rowid': rowid, }); } - ReadsCompanion copyWith( - {Value? lastRead, - Value? userId, + MembersCompanion copyWith( + {Value? userId, Value? channelCid, - Value? unreadMessages, - Value? lastReadMessageId, + Value? channelRole, + Value? inviteAcceptedAt, + Value? inviteRejectedAt, + Value? invited, + Value? banned, + Value? shadowBanned, + Value? pinnedAt, + Value? archivedAt, + Value? isModerator, + Value?>? extraData, + Value? createdAt, + Value? updatedAt, Value? rowid}) { - return ReadsCompanion( - lastRead: lastRead ?? this.lastRead, + return MembersCompanion( userId: userId ?? this.userId, channelCid: channelCid ?? this.channelCid, - unreadMessages: unreadMessages ?? this.unreadMessages, - lastReadMessageId: lastReadMessageId ?? this.lastReadMessageId, + channelRole: channelRole ?? this.channelRole, + inviteAcceptedAt: inviteAcceptedAt ?? this.inviteAcceptedAt, + inviteRejectedAt: inviteRejectedAt ?? this.inviteRejectedAt, + invited: invited ?? this.invited, + banned: banned ?? this.banned, + shadowBanned: shadowBanned ?? this.shadowBanned, + pinnedAt: pinnedAt ?? this.pinnedAt, + archivedAt: archivedAt ?? this.archivedAt, + isModerator: isModerator ?? this.isModerator, + extraData: extraData ?? this.extraData, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, rowid: rowid ?? this.rowid, ); } @@ -7724,20 +7841,48 @@ class ReadsCompanion extends UpdateCompanion { @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); + if (channelRole.present) { + map['channel_role'] = Variable(channelRole.value); } - if (lastReadMessageId.present) { - map['last_read_message_id'] = Variable(lastReadMessageId.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 (pinnedAt.present) { + map['pinned_at'] = Variable(pinnedAt.value); + } + if (archivedAt.present) { + map['archived_at'] = Variable(archivedAt.value); + } + if (isModerator.present) { + map['is_moderator'] = Variable(isModerator.value); + } + if (extraData.present) { + map['extra_data'] = Variable( + $MembersTable.$converterextraDatan.toSql(extraData.value)); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); } if (rowid.present) { map['rowid'] = Variable(rowid.value); @@ -7747,53 +7892,90 @@ class ReadsCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('ReadsCompanion(') - ..write('lastRead: $lastRead, ') + return (StringBuffer('MembersCompanion(') ..write('userId: $userId, ') ..write('channelCid: $channelCid, ') - ..write('unreadMessages: $unreadMessages, ') - ..write('lastReadMessageId: $lastReadMessageId, ') + ..write('channelRole: $channelRole, ') + ..write('inviteAcceptedAt: $inviteAcceptedAt, ') + ..write('inviteRejectedAt: $inviteRejectedAt, ') + ..write('invited: $invited, ') + ..write('banned: $banned, ') + ..write('shadowBanned: $shadowBanned, ') + ..write('pinnedAt: $pinnedAt, ') + ..write('archivedAt: $archivedAt, ') + ..write('isModerator: $isModerator, ') + ..write('extraData: $extraData, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } -class $ChannelQueriesTable extends ChannelQueries - with TableInfo<$ChannelQueriesTable, ChannelQueryEntity> { +class $ReadsTable extends Reads with TableInfo<$ReadsTable, ReadEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $ChannelQueriesTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _queryHashMeta = - const VerificationMeta('queryHash'); + $ReadsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _lastReadMeta = + const VerificationMeta('lastRead'); @override - late final GeneratedColumn queryHash = GeneratedColumn( - 'query_hash', aliasedName, false, + late final GeneratedColumn lastRead = GeneratedColumn( + 'last_read', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); + @override + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true); static const VerificationMeta _channelCidMeta = const VerificationMeta('channelCid'); @override late final GeneratedColumn channelCid = GeneratedColumn( 'channel_cid', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES channels (cid) ON DELETE CASCADE')); + static const VerificationMeta _unreadMessagesMeta = + const VerificationMeta('unreadMessages'); @override - List get $columns => [queryHash, channelCid]; + late final GeneratedColumn unreadMessages = GeneratedColumn( + 'unread_messages', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(0)); + static const VerificationMeta _lastReadMessageIdMeta = + const VerificationMeta('lastReadMessageId'); + @override + late final GeneratedColumn lastReadMessageId = + GeneratedColumn('last_read_message_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => + [lastRead, userId, channelCid, unreadMessages, lastReadMessageId]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'channel_queries'; + static const String $name = 'reads'; @override - VerificationContext validateIntegrity(Insertable instance, + 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)); + if (data.containsKey('last_read')) { + context.handle(_lastReadMeta, + lastRead.isAcceptableOrUnknown(data['last_read']!, _lastReadMeta)); } else if (isInserting) { - context.missing(_queryHashMeta); + 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( @@ -7803,127 +7985,216 @@ class $ChannelQueriesTable extends ChannelQueries } else if (isInserting) { context.missing(_channelCidMeta); } + if (data.containsKey('unread_messages')) { + context.handle( + _unreadMessagesMeta, + unreadMessages.isAcceptableOrUnknown( + data['unread_messages']!, _unreadMessagesMeta)); + } + if (data.containsKey('last_read_message_id')) { + context.handle( + _lastReadMessageIdMeta, + lastReadMessageId.isAcceptableOrUnknown( + data['last_read_message_id']!, _lastReadMessageIdMeta)); + } return context; } @override - Set get $primaryKey => {queryHash, channelCid}; + Set get $primaryKey => {userId, channelCid}; @override - ChannelQueryEntity map(Map data, {String? tablePrefix}) { + ReadEntity map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return ChannelQueryEntity( - queryHash: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}query_hash'])!, + return ReadEntity( + lastRead: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}last_read'])!, + userId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, channelCid: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}channel_cid'])!, + unreadMessages: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}unread_messages'])!, + lastReadMessageId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}last_read_message_id']), ); } @override - $ChannelQueriesTable createAlias(String alias) { - return $ChannelQueriesTable(attachedDatabase, alias); + $ReadsTable createAlias(String alias) { + return $ReadsTable(attachedDatabase, alias); } } -class ChannelQueryEntity extends DataClass - implements Insertable { - /// The unique hash of this query - final String queryHash; +class ReadEntity extends DataClass implements Insertable { + /// Date of the read event + final DateTime lastRead; - /// The channel cid of this query + /// Id of the User who sent the event + final String userId; + + /// The channel cid of which this read belongs final String channelCid; - const ChannelQueryEntity({required this.queryHash, required this.channelCid}); + + /// Number of unread messages + final int unreadMessages; + + /// Id of the last read message + final String? lastReadMessageId; + const ReadEntity( + {required this.lastRead, + required this.userId, + required this.channelCid, + required this.unreadMessages, + this.lastReadMessageId}); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['query_hash'] = Variable(queryHash); + map['last_read'] = Variable(lastRead); + map['user_id'] = Variable(userId); map['channel_cid'] = Variable(channelCid); + map['unread_messages'] = Variable(unreadMessages); + if (!nullToAbsent || lastReadMessageId != null) { + map['last_read_message_id'] = Variable(lastReadMessageId); + } return map; } - factory ChannelQueryEntity.fromJson(Map json, + factory ReadEntity.fromJson(Map json, {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; - return ChannelQueryEntity( - queryHash: serializer.fromJson(json['queryHash']), + return ReadEntity( + lastRead: serializer.fromJson(json['lastRead']), + userId: serializer.fromJson(json['userId']), channelCid: serializer.fromJson(json['channelCid']), + unreadMessages: serializer.fromJson(json['unreadMessages']), + lastReadMessageId: + serializer.fromJson(json['lastReadMessageId']), ); } @override Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'queryHash': serializer.toJson(queryHash), + 'lastRead': serializer.toJson(lastRead), + 'userId': serializer.toJson(userId), 'channelCid': serializer.toJson(channelCid), + 'unreadMessages': serializer.toJson(unreadMessages), + 'lastReadMessageId': serializer.toJson(lastReadMessageId), }; } - ChannelQueryEntity copyWith({String? queryHash, String? channelCid}) => - ChannelQueryEntity( - queryHash: queryHash ?? this.queryHash, + ReadEntity copyWith( + {DateTime? lastRead, + String? userId, + String? channelCid, + int? unreadMessages, + Value lastReadMessageId = const Value.absent()}) => + ReadEntity( + lastRead: lastRead ?? this.lastRead, + userId: userId ?? this.userId, channelCid: channelCid ?? this.channelCid, + unreadMessages: unreadMessages ?? this.unreadMessages, + lastReadMessageId: lastReadMessageId.present + ? lastReadMessageId.value + : this.lastReadMessageId, ); - ChannelQueryEntity copyWithCompanion(ChannelQueriesCompanion data) { - return ChannelQueryEntity( - queryHash: data.queryHash.present ? data.queryHash.value : this.queryHash, + ReadEntity copyWithCompanion(ReadsCompanion data) { + return ReadEntity( + lastRead: data.lastRead.present ? data.lastRead.value : this.lastRead, + userId: data.userId.present ? data.userId.value : this.userId, channelCid: data.channelCid.present ? data.channelCid.value : this.channelCid, + unreadMessages: data.unreadMessages.present + ? data.unreadMessages.value + : this.unreadMessages, + lastReadMessageId: data.lastReadMessageId.present + ? data.lastReadMessageId.value + : this.lastReadMessageId, ); } @override String toString() { - return (StringBuffer('ChannelQueryEntity(') - ..write('queryHash: $queryHash, ') - ..write('channelCid: $channelCid') + return (StringBuffer('ReadEntity(') + ..write('lastRead: $lastRead, ') + ..write('userId: $userId, ') + ..write('channelCid: $channelCid, ') + ..write('unreadMessages: $unreadMessages, ') + ..write('lastReadMessageId: $lastReadMessageId') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(queryHash, channelCid); + int get hashCode => Object.hash( + lastRead, userId, channelCid, unreadMessages, lastReadMessageId); @override bool operator ==(Object other) => identical(this, other) || - (other is ChannelQueryEntity && - other.queryHash == this.queryHash && - other.channelCid == this.channelCid); + (other is ReadEntity && + other.lastRead == this.lastRead && + other.userId == this.userId && + other.channelCid == this.channelCid && + other.unreadMessages == this.unreadMessages && + other.lastReadMessageId == this.lastReadMessageId); } -class ChannelQueriesCompanion extends UpdateCompanion { - final Value queryHash; +class ReadsCompanion extends UpdateCompanion { + final Value lastRead; + final Value userId; final Value channelCid; + final Value unreadMessages; + final Value lastReadMessageId; final Value rowid; - const ChannelQueriesCompanion({ - this.queryHash = const Value.absent(), + const ReadsCompanion({ + this.lastRead = const Value.absent(), + this.userId = const Value.absent(), this.channelCid = const Value.absent(), + this.unreadMessages = const Value.absent(), + this.lastReadMessageId = const Value.absent(), this.rowid = const Value.absent(), }); - ChannelQueriesCompanion.insert({ - required String queryHash, + ReadsCompanion.insert({ + required DateTime lastRead, + required String userId, required String channelCid, + this.unreadMessages = const Value.absent(), + this.lastReadMessageId = const Value.absent(), this.rowid = const Value.absent(), - }) : queryHash = Value(queryHash), + }) : lastRead = Value(lastRead), + userId = Value(userId), channelCid = Value(channelCid); - static Insertable custom({ - Expression? queryHash, + static Insertable custom({ + Expression? lastRead, + Expression? userId, Expression? channelCid, + Expression? unreadMessages, + Expression? lastReadMessageId, Expression? rowid, }) { return RawValuesInsertable({ - if (queryHash != null) 'query_hash': queryHash, + if (lastRead != null) 'last_read': lastRead, + if (userId != null) 'user_id': userId, if (channelCid != null) 'channel_cid': channelCid, + if (unreadMessages != null) 'unread_messages': unreadMessages, + if (lastReadMessageId != null) 'last_read_message_id': lastReadMessageId, if (rowid != null) 'rowid': rowid, }); } - ChannelQueriesCompanion copyWith( - {Value? queryHash, + ReadsCompanion copyWith( + {Value? lastRead, + Value? userId, Value? channelCid, + Value? unreadMessages, + Value? lastReadMessageId, Value? rowid}) { - return ChannelQueriesCompanion( - queryHash: queryHash ?? this.queryHash, + return ReadsCompanion( + lastRead: lastRead ?? this.lastRead, + userId: userId ?? this.userId, channelCid: channelCid ?? this.channelCid, + unreadMessages: unreadMessages ?? this.unreadMessages, + lastReadMessageId: lastReadMessageId ?? this.lastReadMessageId, rowid: rowid ?? this.rowid, ); } @@ -7931,12 +8202,21 @@ class ChannelQueriesCompanion extends UpdateCompanion { @override Map toColumns(bool nullToAbsent) { final map = {}; - if (queryHash.present) { - map['query_hash'] = Variable(queryHash.value); + 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); + } + if (lastReadMessageId.present) { + map['last_read_message_id'] = Variable(lastReadMessageId.value); + } if (rowid.present) { map['rowid'] = Variable(rowid.value); } @@ -7945,101 +8225,299 @@ class ChannelQueriesCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('ChannelQueriesCompanion(') - ..write('queryHash: $queryHash, ') + return (StringBuffer('ReadsCompanion(') + ..write('lastRead: $lastRead, ') + ..write('userId: $userId, ') ..write('channelCid: $channelCid, ') + ..write('unreadMessages: $unreadMessages, ') + ..write('lastReadMessageId: $lastReadMessageId, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } -class $ConnectionEventsTable extends ConnectionEvents - with TableInfo<$ConnectionEventsTable, ConnectionEventEntity> { +class $ChannelQueriesTable extends ChannelQueries + with TableInfo<$ChannelQueriesTable, ChannelQueryEntity> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $ConnectionEventsTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _idMeta = const VerificationMeta('id'); - @override - late final GeneratedColumn id = GeneratedColumn( - 'id', aliasedName, false, - type: DriftSqlType.int, requiredDuringInsert: false); - static const VerificationMeta _typeMeta = const VerificationMeta('type'); + $ChannelQueriesTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _queryHashMeta = + const VerificationMeta('queryHash'); @override - late final GeneratedColumn type = GeneratedColumn( - 'type', aliasedName, false, + late final GeneratedColumn queryHash = GeneratedColumn( + 'query_hash', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _channelCidMeta = + const VerificationMeta('channelCid'); @override - late final GeneratedColumnWithTypeConverter?, String> - ownUser = GeneratedColumn('own_user', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false) - .withConverter?>( - $ConnectionEventsTable.$converterownUsern); - static const VerificationMeta _totalUnreadCountMeta = - const VerificationMeta('totalUnreadCount'); - @override - late final GeneratedColumn totalUnreadCount = GeneratedColumn( - 'total_unread_count', aliasedName, true, - type: DriftSqlType.int, requiredDuringInsert: false); - static const VerificationMeta _unreadChannelsMeta = - const VerificationMeta('unreadChannels'); - @override - late final GeneratedColumn unreadChannels = GeneratedColumn( - 'unread_channels', aliasedName, true, - type: DriftSqlType.int, requiredDuringInsert: false); - static const VerificationMeta _lastEventAtMeta = - const VerificationMeta('lastEventAt'); - @override - late final GeneratedColumn lastEventAt = GeneratedColumn( - 'last_event_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); - static const VerificationMeta _lastSyncAtMeta = - const VerificationMeta('lastSyncAt'); - @override - late final GeneratedColumn lastSyncAt = GeneratedColumn( - 'last_sync_at', aliasedName, true, - type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn channelCid = GeneratedColumn( + 'channel_cid', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); @override - List get $columns => [ - id, - type, - ownUser, - totalUnreadCount, - unreadChannels, - lastEventAt, - lastSyncAt - ]; + List get $columns => [queryHash, channelCid]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'connection_events'; + static const String $name = 'channel_queries'; @override - VerificationContext validateIntegrity( - Insertable instance, + 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)); - } - if (data.containsKey('type')) { - context.handle( - _typeMeta, type.isAcceptableOrUnknown(data['type']!, _typeMeta)); + if (data.containsKey('query_hash')) { + context.handle(_queryHashMeta, + queryHash.isAcceptableOrUnknown(data['query_hash']!, _queryHashMeta)); } else if (isInserting) { - context.missing(_typeMeta); + context.missing(_queryHashMeta); } - if (data.containsKey('total_unread_count')) { + if (data.containsKey('channel_cid')) { context.handle( - _totalUnreadCountMeta, - totalUnreadCount.isAcceptableOrUnknown( - data['total_unread_count']!, _totalUnreadCountMeta)); + _channelCidMeta, + channelCid.isAcceptableOrUnknown( + data['channel_cid']!, _channelCidMeta)); + } else if (isInserting) { + context.missing(_channelCidMeta); } - if (data.containsKey('unread_channels')) { - context.handle( - _unreadChannelsMeta, - unreadChannels.isAcceptableOrUnknown( + return context; + } + + @override + Set get $primaryKey => {queryHash, channelCid}; + @override + ChannelQueryEntity map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return ChannelQueryEntity( + queryHash: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}query_hash'])!, + channelCid: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}channel_cid'])!, + ); + } + + @override + $ChannelQueriesTable createAlias(String alias) { + return $ChannelQueriesTable(attachedDatabase, alias); + } +} + +class ChannelQueryEntity extends DataClass + implements Insertable { + /// The unique hash of this query + final String queryHash; + + /// The channel cid of this query + final String channelCid; + const ChannelQueryEntity({required this.queryHash, required this.channelCid}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['query_hash'] = Variable(queryHash); + map['channel_cid'] = Variable(channelCid); + return map; + } + + factory ChannelQueryEntity.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return ChannelQueryEntity( + queryHash: serializer.fromJson(json['queryHash']), + channelCid: serializer.fromJson(json['channelCid']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.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, + ); + ChannelQueryEntity copyWithCompanion(ChannelQueriesCompanion data) { + return ChannelQueryEntity( + queryHash: data.queryHash.present ? data.queryHash.value : this.queryHash, + channelCid: + data.channelCid.present ? data.channelCid.value : this.channelCid, + ); + } + + @override + String toString() { + return (StringBuffer('ChannelQueryEntity(') + ..write('queryHash: $queryHash, ') + ..write('channelCid: $channelCid') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(queryHash, channelCid); + @override + bool operator ==(Object 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; + final Value rowid; + const ChannelQueriesCompanion({ + this.queryHash = const Value.absent(), + this.channelCid = const Value.absent(), + this.rowid = const Value.absent(), + }); + ChannelQueriesCompanion.insert({ + required String queryHash, + required String channelCid, + this.rowid = const Value.absent(), + }) : queryHash = Value(queryHash), + channelCid = Value(channelCid); + static Insertable custom({ + Expression? queryHash, + Expression? channelCid, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (queryHash != null) 'query_hash': queryHash, + if (channelCid != null) 'channel_cid': channelCid, + if (rowid != null) 'rowid': rowid, + }); + } + + ChannelQueriesCompanion copyWith( + {Value? queryHash, + Value? channelCid, + Value? rowid}) { + return ChannelQueriesCompanion( + queryHash: queryHash ?? this.queryHash, + channelCid: channelCid ?? this.channelCid, + rowid: rowid ?? this.rowid, + ); + } + + @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); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ChannelQueriesCompanion(') + ..write('queryHash: $queryHash, ') + ..write('channelCid: $channelCid, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $ConnectionEventsTable extends ConnectionEvents + with TableInfo<$ConnectionEventsTable, ConnectionEventEntity> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $ConnectionEventsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: false); + static const VerificationMeta _typeMeta = const VerificationMeta('type'); + @override + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + late final GeneratedColumnWithTypeConverter?, String> + ownUser = GeneratedColumn('own_user', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $ConnectionEventsTable.$converterownUsern); + static const VerificationMeta _totalUnreadCountMeta = + const VerificationMeta('totalUnreadCount'); + @override + late final GeneratedColumn totalUnreadCount = GeneratedColumn( + 'total_unread_count', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + static const VerificationMeta _unreadChannelsMeta = + const VerificationMeta('unreadChannels'); + @override + late final GeneratedColumn unreadChannels = GeneratedColumn( + 'unread_channels', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + static const VerificationMeta _lastEventAtMeta = + const VerificationMeta('lastEventAt'); + @override + late final GeneratedColumn lastEventAt = GeneratedColumn( + 'last_event_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + static const VerificationMeta _lastSyncAtMeta = + const VerificationMeta('lastSyncAt'); + @override + late final GeneratedColumn lastSyncAt = GeneratedColumn( + 'last_sync_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + type, + ownUser, + totalUnreadCount, + unreadChannels, + lastEventAt, + lastSyncAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = '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)); + } + if (data.containsKey('type')) { + context.handle( + _typeMeta, type.isAcceptableOrUnknown(data['type']!, _typeMeta)); + } else if (isInserting) { + context.missing(_typeMeta); + } + 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')) { @@ -8355,6 +8833,7 @@ abstract class _$DriftChatDatabase extends GeneratedDatabase { late final $ChannelsTable channels = $ChannelsTable(this); late final $MessagesTable messages = $MessagesTable(this); late final $DraftMessagesTable draftMessages = $DraftMessagesTable(this); + late final $LocationsTable locations = $LocationsTable(this); late final $PinnedMessagesTable pinnedMessages = $PinnedMessagesTable(this); late final $PollsTable polls = $PollsTable(this); late final $PollVotesTable pollVotes = $PollVotesTable(this); @@ -8372,6 +8851,7 @@ abstract class _$DriftChatDatabase extends GeneratedDatabase { late final MessageDao messageDao = MessageDao(this as DriftChatDatabase); late final DraftMessageDao draftMessageDao = DraftMessageDao(this as DriftChatDatabase); + late final LocationDao locationDao = LocationDao(this as DriftChatDatabase); late final PinnedMessageDao pinnedMessageDao = PinnedMessageDao(this as DriftChatDatabase); late final PinnedMessageReactionDao pinnedMessageReactionDao = @@ -8393,6 +8873,7 @@ abstract class _$DriftChatDatabase extends GeneratedDatabase { channels, messages, draftMessages, + locations, pinnedMessages, polls, pollVotes, @@ -8428,6 +8909,20 @@ abstract class _$DriftChatDatabase extends GeneratedDatabase { TableUpdate('draft_messages', kind: UpdateKind.delete), ], ), + WritePropagation( + on: TableUpdateQuery.onTableName('channels', + limitUpdateKind: UpdateKind.delete), + result: [ + TableUpdate('locations', kind: UpdateKind.delete), + ], + ), + WritePropagation( + on: TableUpdateQuery.onTableName('messages', + limitUpdateKind: UpdateKind.delete), + result: [ + TableUpdate('locations', kind: UpdateKind.delete), + ], + ), WritePropagation( on: TableUpdateQuery.onTableName('polls', limitUpdateKind: UpdateKind.delete), @@ -8467,154 +8962,941 @@ abstract class _$DriftChatDatabase extends GeneratedDatabase { ); } -typedef $$ChannelsTableCreateCompanionBuilder = ChannelsCompanion Function({ +typedef $$ChannelsTableCreateCompanionBuilder = ChannelsCompanion Function({ + required String id, + required String type, + required String cid, + Value?> ownCapabilities, + required Map config, + Value frozen, + Value lastMessageAt, + Value createdAt, + Value updatedAt, + Value deletedAt, + Value memberCount, + Value createdById, + Value?> extraData, + Value rowid, +}); +typedef $$ChannelsTableUpdateCompanionBuilder = ChannelsCompanion Function({ + Value id, + Value type, + Value cid, + Value?> ownCapabilities, + Value> config, + Value frozen, + Value lastMessageAt, + Value createdAt, + Value updatedAt, + Value deletedAt, + Value memberCount, + Value createdById, + Value?> extraData, + Value rowid, +}); + +final class $$ChannelsTableReferences + extends BaseReferences<_$DriftChatDatabase, $ChannelsTable, ChannelEntity> { + $$ChannelsTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static MultiTypedResultKey<$MessagesTable, List> + _messagesRefsTable(_$DriftChatDatabase db) => + MultiTypedResultKey.fromTable(db.messages, + aliasName: $_aliasNameGenerator( + db.channels.cid, db.messages.channelCid)); + + $$MessagesTableProcessedTableManager get messagesRefs { + final manager = $$MessagesTableTableManager($_db, $_db.messages).filter( + (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + + final cache = $_typedResult.readTableOrNull(_messagesRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } + + static MultiTypedResultKey<$DraftMessagesTable, List> + _draftMessagesRefsTable(_$DriftChatDatabase db) => + MultiTypedResultKey.fromTable(db.draftMessages, + aliasName: $_aliasNameGenerator( + db.channels.cid, db.draftMessages.channelCid)); + + $$DraftMessagesTableProcessedTableManager get draftMessagesRefs { + final manager = $$DraftMessagesTableTableManager($_db, $_db.draftMessages) + .filter( + (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + + final cache = $_typedResult.readTableOrNull(_draftMessagesRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } + + static MultiTypedResultKey<$LocationsTable, List> + _locationsRefsTable(_$DriftChatDatabase db) => + MultiTypedResultKey.fromTable(db.locations, + aliasName: $_aliasNameGenerator( + db.channels.cid, db.locations.channelCid)); + + $$LocationsTableProcessedTableManager get locationsRefs { + final manager = $$LocationsTableTableManager($_db, $_db.locations).filter( + (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + + final cache = $_typedResult.readTableOrNull(_locationsRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } + + static MultiTypedResultKey<$MembersTable, List> + _membersRefsTable(_$DriftChatDatabase db) => + MultiTypedResultKey.fromTable(db.members, + aliasName: + $_aliasNameGenerator(db.channels.cid, db.members.channelCid)); + + $$MembersTableProcessedTableManager get membersRefs { + final manager = $$MembersTableTableManager($_db, $_db.members).filter( + (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + + final cache = $_typedResult.readTableOrNull(_membersRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } + + static MultiTypedResultKey<$ReadsTable, List> _readsRefsTable( + _$DriftChatDatabase db) => + MultiTypedResultKey.fromTable(db.reads, + aliasName: + $_aliasNameGenerator(db.channels.cid, db.reads.channelCid)); + + $$ReadsTableProcessedTableManager get readsRefs { + final manager = $$ReadsTableTableManager($_db, $_db.reads).filter( + (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + + final cache = $_typedResult.readTableOrNull(_readsRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } +} + +class $$ChannelsTableFilterComposer + extends Composer<_$DriftChatDatabase, $ChannelsTable> { + $$ChannelsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get type => $composableBuilder( + column: $table.type, builder: (column) => ColumnFilters(column)); + + ColumnFilters get cid => $composableBuilder( + column: $table.cid, builder: (column) => ColumnFilters(column)); + + ColumnWithTypeConverterFilters?, List, String> + get ownCapabilities => $composableBuilder( + column: $table.ownCapabilities, + builder: (column) => ColumnWithTypeConverterFilters(column)); + + ColumnWithTypeConverterFilters, Map, + String> + get config => $composableBuilder( + column: $table.config, + builder: (column) => ColumnWithTypeConverterFilters(column)); + + ColumnFilters get frozen => $composableBuilder( + column: $table.frozen, builder: (column) => ColumnFilters(column)); + + ColumnFilters get lastMessageAt => $composableBuilder( + column: $table.lastMessageAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get deletedAt => $composableBuilder( + column: $table.deletedAt, builder: (column) => ColumnFilters(column)); + + ColumnFilters get memberCount => $composableBuilder( + column: $table.memberCount, builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdById => $composableBuilder( + column: $table.createdById, builder: (column) => ColumnFilters(column)); + + ColumnWithTypeConverterFilters?, Map, + String> + get extraData => $composableBuilder( + column: $table.extraData, + builder: (column) => ColumnWithTypeConverterFilters(column)); + + Expression messagesRefs( + Expression Function($$MessagesTableFilterComposer f) f) { + final $$MessagesTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MessagesTableFilterComposer( + $db: $db, + $table: $db.messages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression draftMessagesRefs( + Expression Function($$DraftMessagesTableFilterComposer f) f) { + final $$DraftMessagesTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.draftMessages, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$DraftMessagesTableFilterComposer( + $db: $db, + $table: $db.draftMessages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression locationsRefs( + Expression Function($$LocationsTableFilterComposer f) f) { + final $$LocationsTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.locations, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$LocationsTableFilterComposer( + $db: $db, + $table: $db.locations, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression membersRefs( + Expression Function($$MembersTableFilterComposer f) f) { + final $$MembersTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.members, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MembersTableFilterComposer( + $db: $db, + $table: $db.members, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression readsRefs( + Expression Function($$ReadsTableFilterComposer f) f) { + final $$ReadsTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.reads, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$ReadsTableFilterComposer( + $db: $db, + $table: $db.reads, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } +} + +class $$ChannelsTableOrderingComposer + extends Composer<_$DriftChatDatabase, $ChannelsTable> { + $$ChannelsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get type => $composableBuilder( + column: $table.type, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get cid => $composableBuilder( + column: $table.cid, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get ownCapabilities => $composableBuilder( + column: $table.ownCapabilities, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get config => $composableBuilder( + column: $table.config, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get frozen => $composableBuilder( + column: $table.frozen, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get lastMessageAt => $composableBuilder( + column: $table.lastMessageAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get deletedAt => $composableBuilder( + column: $table.deletedAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get memberCount => $composableBuilder( + column: $table.memberCount, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdById => $composableBuilder( + column: $table.createdById, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get extraData => $composableBuilder( + column: $table.extraData, builder: (column) => ColumnOrderings(column)); +} + +class $$ChannelsTableAnnotationComposer + extends Composer<_$DriftChatDatabase, $ChannelsTable> { + $$ChannelsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get type => + $composableBuilder(column: $table.type, builder: (column) => column); + + GeneratedColumn get cid => + $composableBuilder(column: $table.cid, builder: (column) => column); + + GeneratedColumnWithTypeConverter?, String> get ownCapabilities => + $composableBuilder( + column: $table.ownCapabilities, builder: (column) => column); + + GeneratedColumnWithTypeConverter, String> get config => + $composableBuilder(column: $table.config, builder: (column) => column); + + GeneratedColumn get frozen => + $composableBuilder(column: $table.frozen, builder: (column) => column); + + GeneratedColumn get lastMessageAt => $composableBuilder( + column: $table.lastMessageAt, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + GeneratedColumn get updatedAt => + $composableBuilder(column: $table.updatedAt, builder: (column) => column); + + GeneratedColumn get deletedAt => + $composableBuilder(column: $table.deletedAt, builder: (column) => column); + + GeneratedColumn get memberCount => $composableBuilder( + column: $table.memberCount, builder: (column) => column); + + GeneratedColumn get createdById => $composableBuilder( + column: $table.createdById, builder: (column) => column); + + GeneratedColumnWithTypeConverter?, String> + get extraData => $composableBuilder( + column: $table.extraData, builder: (column) => column); + + Expression messagesRefs( + Expression Function($$MessagesTableAnnotationComposer a) f) { + final $$MessagesTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MessagesTableAnnotationComposer( + $db: $db, + $table: $db.messages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression draftMessagesRefs( + Expression Function($$DraftMessagesTableAnnotationComposer a) f) { + final $$DraftMessagesTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.draftMessages, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$DraftMessagesTableAnnotationComposer( + $db: $db, + $table: $db.draftMessages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression locationsRefs( + Expression Function($$LocationsTableAnnotationComposer a) f) { + final $$LocationsTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.locations, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$LocationsTableAnnotationComposer( + $db: $db, + $table: $db.locations, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression membersRefs( + Expression Function($$MembersTableAnnotationComposer a) f) { + final $$MembersTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.members, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MembersTableAnnotationComposer( + $db: $db, + $table: $db.members, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } + + Expression readsRefs( + Expression Function($$ReadsTableAnnotationComposer a) f) { + final $$ReadsTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.cid, + referencedTable: $db.reads, + getReferencedColumn: (t) => t.channelCid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$ReadsTableAnnotationComposer( + $db: $db, + $table: $db.reads, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } +} + +class $$ChannelsTableTableManager extends RootTableManager< + _$DriftChatDatabase, + $ChannelsTable, + ChannelEntity, + $$ChannelsTableFilterComposer, + $$ChannelsTableOrderingComposer, + $$ChannelsTableAnnotationComposer, + $$ChannelsTableCreateCompanionBuilder, + $$ChannelsTableUpdateCompanionBuilder, + (ChannelEntity, $$ChannelsTableReferences), + ChannelEntity, + PrefetchHooks Function( + {bool messagesRefs, + bool draftMessagesRefs, + bool locationsRefs, + bool membersRefs, + bool readsRefs})> { + $$ChannelsTableTableManager(_$DriftChatDatabase db, $ChannelsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$ChannelsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$ChannelsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$ChannelsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value type = const Value.absent(), + Value cid = const Value.absent(), + Value?> ownCapabilities = const Value.absent(), + Value> config = const Value.absent(), + Value frozen = const Value.absent(), + 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(), + Value rowid = const Value.absent(), + }) => + ChannelsCompanion( + id: id, + type: type, + cid: cid, + ownCapabilities: ownCapabilities, + config: config, + frozen: frozen, + lastMessageAt: lastMessageAt, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + memberCount: memberCount, + createdById: createdById, + extraData: extraData, + rowid: rowid, + ), + createCompanionCallback: ({ + required String id, + required String type, + required String cid, + Value?> ownCapabilities = const Value.absent(), + required Map config, + Value frozen = const Value.absent(), + 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(), + Value rowid = const Value.absent(), + }) => + ChannelsCompanion.insert( + id: id, + type: type, + cid: cid, + ownCapabilities: ownCapabilities, + config: config, + frozen: frozen, + lastMessageAt: lastMessageAt, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + memberCount: memberCount, + createdById: createdById, + extraData: extraData, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => + (e.readTable(table), $$ChannelsTableReferences(db, table, e))) + .toList(), + prefetchHooksCallback: ( + {messagesRefs = false, + draftMessagesRefs = false, + locationsRefs = false, + membersRefs = false, + readsRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [ + if (messagesRefs) db.messages, + if (draftMessagesRefs) db.draftMessages, + if (locationsRefs) db.locations, + if (membersRefs) db.members, + if (readsRefs) db.reads + ], + addJoins: null, + getPrefetchedDataCallback: (items) async { + return [ + if (messagesRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: + $$ChannelsTableReferences._messagesRefsTable(db), + managerFromTypedResult: (p0) => + $$ChannelsTableReferences(db, table, p0) + .messagesRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.channelCid == item.cid), + typedResults: items), + if (draftMessagesRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: $$ChannelsTableReferences + ._draftMessagesRefsTable(db), + managerFromTypedResult: (p0) => + $$ChannelsTableReferences(db, table, p0) + .draftMessagesRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.channelCid == item.cid), + typedResults: items), + if (locationsRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: + $$ChannelsTableReferences._locationsRefsTable(db), + managerFromTypedResult: (p0) => + $$ChannelsTableReferences(db, table, p0) + .locationsRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.channelCid == item.cid), + typedResults: items), + if (membersRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: + $$ChannelsTableReferences._membersRefsTable(db), + managerFromTypedResult: (p0) => + $$ChannelsTableReferences(db, table, p0) + .membersRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.channelCid == item.cid), + typedResults: items), + if (readsRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: + $$ChannelsTableReferences._readsRefsTable(db), + managerFromTypedResult: (p0) => + $$ChannelsTableReferences(db, table, p0).readsRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.channelCid == item.cid), + typedResults: items) + ]; + }, + ); + }, + )); +} + +typedef $$ChannelsTableProcessedTableManager = ProcessedTableManager< + _$DriftChatDatabase, + $ChannelsTable, + ChannelEntity, + $$ChannelsTableFilterComposer, + $$ChannelsTableOrderingComposer, + $$ChannelsTableAnnotationComposer, + $$ChannelsTableCreateCompanionBuilder, + $$ChannelsTableUpdateCompanionBuilder, + (ChannelEntity, $$ChannelsTableReferences), + ChannelEntity, + PrefetchHooks Function( + {bool messagesRefs, + bool draftMessagesRefs, + bool locationsRefs, + bool membersRefs, + bool readsRefs})>; +typedef $$MessagesTableCreateCompanionBuilder = MessagesCompanion Function({ required String id, - required String type, - required String cid, - Value?> ownCapabilities, - required Map config, - Value frozen, - Value lastMessageAt, - Value createdAt, - Value updatedAt, - Value deletedAt, - Value memberCount, - Value createdById, + Value messageText, + required List attachments, + required String state, + Value type, + required List mentionedUsers, + Value?> reactionGroups, + Value parentId, + Value quotedMessageId, + Value pollId, + Value replyCount, + Value showInChannel, + Value shadowed, + Value command, + Value localCreatedAt, + Value remoteCreatedAt, + Value localUpdatedAt, + Value remoteUpdatedAt, + Value localDeletedAt, + Value remoteDeletedAt, + Value messageTextUpdatedAt, + Value userId, + Value pinned, + Value pinnedAt, + Value pinExpires, + Value pinnedByUserId, + required String channelCid, + Value?> i18n, + Value?> restrictedVisibility, + Value draftMessageId, Value?> extraData, Value rowid, }); -typedef $$ChannelsTableUpdateCompanionBuilder = ChannelsCompanion Function({ +typedef $$MessagesTableUpdateCompanionBuilder = MessagesCompanion Function({ Value id, + Value messageText, + Value> attachments, + Value state, Value type, - Value cid, - Value?> ownCapabilities, - Value> config, - Value frozen, - Value lastMessageAt, - Value createdAt, - Value updatedAt, - Value deletedAt, - Value memberCount, - Value createdById, + Value> mentionedUsers, + Value?> reactionGroups, + Value parentId, + Value quotedMessageId, + Value pollId, + Value replyCount, + Value showInChannel, + Value shadowed, + Value command, + Value localCreatedAt, + Value remoteCreatedAt, + Value localUpdatedAt, + Value remoteUpdatedAt, + Value localDeletedAt, + Value remoteDeletedAt, + Value messageTextUpdatedAt, + Value userId, + Value pinned, + Value pinnedAt, + Value pinExpires, + Value pinnedByUserId, + Value channelCid, + Value?> i18n, + Value?> restrictedVisibility, + Value draftMessageId, Value?> extraData, Value rowid, }); -final class $$ChannelsTableReferences - extends BaseReferences<_$DriftChatDatabase, $ChannelsTable, ChannelEntity> { - $$ChannelsTableReferences(super.$_db, super.$_table, super.$_typedResult); +final class $$MessagesTableReferences + extends BaseReferences<_$DriftChatDatabase, $MessagesTable, MessageEntity> { + $$MessagesTableReferences(super.$_db, super.$_table, super.$_typedResult); - static MultiTypedResultKey<$MessagesTable, List> - _messagesRefsTable(_$DriftChatDatabase db) => - MultiTypedResultKey.fromTable(db.messages, - aliasName: $_aliasNameGenerator( - db.channels.cid, db.messages.channelCid)); + static $ChannelsTable _channelCidTable(_$DriftChatDatabase db) => + db.channels.createAlias( + $_aliasNameGenerator(db.messages.channelCid, db.channels.cid)); - $$MessagesTableProcessedTableManager get messagesRefs { - final manager = $$MessagesTableTableManager($_db, $_db.messages).filter( - (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + $$ChannelsTableProcessedTableManager get channelCid { + final $_column = $_itemColumn('channel_cid')!; - final cache = $_typedResult.readTableOrNull(_messagesRefsTable($_db)); + final manager = $$ChannelsTableTableManager($_db, $_db.channels) + .filter((f) => f.cid.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_channelCidTable($_db)); + if (item == null) return manager; return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: cache)); + manager.$state.copyWith(prefetchedData: [item])); } static MultiTypedResultKey<$DraftMessagesTable, List> _draftMessagesRefsTable(_$DriftChatDatabase db) => MultiTypedResultKey.fromTable(db.draftMessages, aliasName: $_aliasNameGenerator( - db.channels.cid, db.draftMessages.channelCid)); + db.messages.id, db.draftMessages.parentId)); $$DraftMessagesTableProcessedTableManager get draftMessagesRefs { final manager = $$DraftMessagesTableTableManager($_db, $_db.draftMessages) - .filter( - (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + .filter((f) => f.parentId.id.sqlEquals($_itemColumn('id')!)); final cache = $_typedResult.readTableOrNull(_draftMessagesRefsTable($_db)); return ProcessedTableManager( manager.$state.copyWith(prefetchedData: cache)); } - static MultiTypedResultKey<$MembersTable, List> - _membersRefsTable(_$DriftChatDatabase db) => - MultiTypedResultKey.fromTable(db.members, + static MultiTypedResultKey<$LocationsTable, List> + _locationsRefsTable(_$DriftChatDatabase db) => + MultiTypedResultKey.fromTable(db.locations, aliasName: - $_aliasNameGenerator(db.channels.cid, db.members.channelCid)); + $_aliasNameGenerator(db.messages.id, db.locations.messageId)); - $$MembersTableProcessedTableManager get membersRefs { - final manager = $$MembersTableTableManager($_db, $_db.members).filter( - (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + $$LocationsTableProcessedTableManager get locationsRefs { + final manager = $$LocationsTableTableManager($_db, $_db.locations) + .filter((f) => f.messageId.id.sqlEquals($_itemColumn('id')!)); - final cache = $_typedResult.readTableOrNull(_membersRefsTable($_db)); + final cache = $_typedResult.readTableOrNull(_locationsRefsTable($_db)); return ProcessedTableManager( manager.$state.copyWith(prefetchedData: cache)); } - static MultiTypedResultKey<$ReadsTable, List> _readsRefsTable( - _$DriftChatDatabase db) => - MultiTypedResultKey.fromTable(db.reads, - aliasName: - $_aliasNameGenerator(db.channels.cid, db.reads.channelCid)); + static MultiTypedResultKey<$ReactionsTable, List> + _reactionsRefsTable(_$DriftChatDatabase db) => + MultiTypedResultKey.fromTable(db.reactions, + aliasName: + $_aliasNameGenerator(db.messages.id, db.reactions.messageId)); - $$ReadsTableProcessedTableManager get readsRefs { - final manager = $$ReadsTableTableManager($_db, $_db.reads).filter( - (f) => f.channelCid.cid.sqlEquals($_itemColumn('cid')!)); + $$ReactionsTableProcessedTableManager get reactionsRefs { + final manager = $$ReactionsTableTableManager($_db, $_db.reactions) + .filter((f) => f.messageId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull(_reactionsRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } +} + +class $$MessagesTableFilterComposer + extends Composer<_$DriftChatDatabase, $MessagesTable> { + $$MessagesTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get messageText => $composableBuilder( + column: $table.messageText, builder: (column) => ColumnFilters(column)); + + ColumnWithTypeConverterFilters, List, String> + get attachments => $composableBuilder( + column: $table.attachments, + builder: (column) => ColumnWithTypeConverterFilters(column)); + + ColumnFilters get state => $composableBuilder( + column: $table.state, builder: (column) => ColumnFilters(column)); + + ColumnFilters get type => $composableBuilder( + column: $table.type, builder: (column) => ColumnFilters(column)); + + ColumnWithTypeConverterFilters, List, String> + get mentionedUsers => $composableBuilder( + column: $table.mentionedUsers, + builder: (column) => ColumnWithTypeConverterFilters(column)); + + ColumnWithTypeConverterFilters?, + Map, String> + get reactionGroups => $composableBuilder( + column: $table.reactionGroups, + builder: (column) => ColumnWithTypeConverterFilters(column)); + + ColumnFilters get parentId => $composableBuilder( + column: $table.parentId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get quotedMessageId => $composableBuilder( + column: $table.quotedMessageId, + builder: (column) => ColumnFilters(column)); + + ColumnFilters get pollId => $composableBuilder( + column: $table.pollId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get replyCount => $composableBuilder( + column: $table.replyCount, builder: (column) => ColumnFilters(column)); + + ColumnFilters get showInChannel => $composableBuilder( + column: $table.showInChannel, builder: (column) => ColumnFilters(column)); + + ColumnFilters get shadowed => $composableBuilder( + column: $table.shadowed, builder: (column) => ColumnFilters(column)); + + ColumnFilters get command => $composableBuilder( + column: $table.command, builder: (column) => ColumnFilters(column)); + + ColumnFilters get localCreatedAt => $composableBuilder( + column: $table.localCreatedAt, + builder: (column) => ColumnFilters(column)); + + ColumnFilters get remoteCreatedAt => $composableBuilder( + column: $table.remoteCreatedAt, + builder: (column) => ColumnFilters(column)); - final cache = $_typedResult.readTableOrNull(_readsRefsTable($_db)); - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: cache)); - } -} + ColumnFilters get localUpdatedAt => $composableBuilder( + column: $table.localUpdatedAt, + builder: (column) => ColumnFilters(column)); -class $$ChannelsTableFilterComposer - extends Composer<_$DriftChatDatabase, $ChannelsTable> { - $$ChannelsTableFilterComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - ColumnFilters get id => $composableBuilder( - column: $table.id, builder: (column) => ColumnFilters(column)); + ColumnFilters get remoteUpdatedAt => $composableBuilder( + column: $table.remoteUpdatedAt, + builder: (column) => ColumnFilters(column)); - ColumnFilters get type => $composableBuilder( - column: $table.type, builder: (column) => ColumnFilters(column)); + ColumnFilters get localDeletedAt => $composableBuilder( + column: $table.localDeletedAt, + builder: (column) => ColumnFilters(column)); - ColumnFilters get cid => $composableBuilder( - column: $table.cid, builder: (column) => ColumnFilters(column)); + ColumnFilters get remoteDeletedAt => $composableBuilder( + column: $table.remoteDeletedAt, + builder: (column) => ColumnFilters(column)); - ColumnWithTypeConverterFilters?, List, String> - get ownCapabilities => $composableBuilder( - column: $table.ownCapabilities, - builder: (column) => ColumnWithTypeConverterFilters(column)); + ColumnFilters get messageTextUpdatedAt => $composableBuilder( + column: $table.messageTextUpdatedAt, + builder: (column) => ColumnFilters(column)); - ColumnWithTypeConverterFilters, Map, - String> - get config => $composableBuilder( - column: $table.config, - builder: (column) => ColumnWithTypeConverterFilters(column)); + ColumnFilters get userId => $composableBuilder( + column: $table.userId, builder: (column) => ColumnFilters(column)); - ColumnFilters get frozen => $composableBuilder( - column: $table.frozen, builder: (column) => ColumnFilters(column)); + ColumnFilters get pinned => $composableBuilder( + column: $table.pinned, builder: (column) => ColumnFilters(column)); - ColumnFilters get lastMessageAt => $composableBuilder( - column: $table.lastMessageAt, builder: (column) => ColumnFilters(column)); + ColumnFilters get pinnedAt => $composableBuilder( + column: $table.pinnedAt, builder: (column) => ColumnFilters(column)); - ColumnFilters get createdAt => $composableBuilder( - column: $table.createdAt, builder: (column) => ColumnFilters(column)); + ColumnFilters get pinExpires => $composableBuilder( + column: $table.pinExpires, builder: (column) => ColumnFilters(column)); - ColumnFilters get updatedAt => $composableBuilder( - column: $table.updatedAt, builder: (column) => ColumnFilters(column)); + ColumnFilters get pinnedByUserId => $composableBuilder( + column: $table.pinnedByUserId, + builder: (column) => ColumnFilters(column)); - ColumnFilters get deletedAt => $composableBuilder( - column: $table.deletedAt, builder: (column) => ColumnFilters(column)); + ColumnWithTypeConverterFilters?, Map, + String> + get i18n => $composableBuilder( + column: $table.i18n, + builder: (column) => ColumnWithTypeConverterFilters(column)); - ColumnFilters get memberCount => $composableBuilder( - column: $table.memberCount, builder: (column) => ColumnFilters(column)); + ColumnWithTypeConverterFilters?, List, String> + get restrictedVisibility => $composableBuilder( + column: $table.restrictedVisibility, + builder: (column) => ColumnWithTypeConverterFilters(column)); - ColumnFilters get createdById => $composableBuilder( - column: $table.createdById, builder: (column) => ColumnFilters(column)); + ColumnFilters get draftMessageId => $composableBuilder( + column: $table.draftMessageId, + builder: (column) => ColumnFilters(column)); ColumnWithTypeConverterFilters?, Map, String> @@ -8622,34 +9904,33 @@ class $$ChannelsTableFilterComposer column: $table.extraData, builder: (column) => ColumnWithTypeConverterFilters(column)); - Expression messagesRefs( - Expression Function($$MessagesTableFilterComposer f) f) { - final $$MessagesTableFilterComposer composer = $composerBuilder( + $$ChannelsTableFilterComposer get channelCid { + final $$ChannelsTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, - referencedTable: $db.messages, - getReferencedColumn: (t) => t.channelCid, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$MessagesTableFilterComposer( + $$ChannelsTableFilterComposer( $db: $db, - $table: $db.messages, + $table: $db.channels, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer, )); - return f(composer); + return composer; } Expression draftMessagesRefs( Expression Function($$DraftMessagesTableFilterComposer f) f) { final $$DraftMessagesTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, + getCurrentColumn: (t) => t.id, referencedTable: $db.draftMessages, - getReferencedColumn: (t) => t.channelCid, + getReferencedColumn: (t) => t.parentId, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => @@ -8664,19 +9945,19 @@ class $$ChannelsTableFilterComposer return f(composer); } - Expression membersRefs( - Expression Function($$MembersTableFilterComposer f) f) { - final $$MembersTableFilterComposer composer = $composerBuilder( + Expression locationsRefs( + Expression Function($$LocationsTableFilterComposer f) f) { + final $$LocationsTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, - referencedTable: $db.members, - getReferencedColumn: (t) => t.channelCid, + getCurrentColumn: (t) => t.id, + referencedTable: $db.locations, + getReferencedColumn: (t) => t.messageId, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$MembersTableFilterComposer( + $$LocationsTableFilterComposer( $db: $db, - $table: $db.members, + $table: $db.locations, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -8685,19 +9966,19 @@ class $$ChannelsTableFilterComposer return f(composer); } - Expression readsRefs( - Expression Function($$ReadsTableFilterComposer f) f) { - final $$ReadsTableFilterComposer composer = $composerBuilder( + Expression reactionsRefs( + Expression Function($$ReactionsTableFilterComposer f) f) { + final $$ReactionsTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, - referencedTable: $db.reads, - getReferencedColumn: (t) => t.channelCid, + getCurrentColumn: (t) => t.id, + referencedTable: $db.reactions, + getReferencedColumn: (t) => t.messageId, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ReadsTableFilterComposer( + $$ReactionsTableFilterComposer( $db: $db, - $table: $db.reads, + $table: $db.reactions, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -8707,9 +9988,9 @@ class $$ChannelsTableFilterComposer } } -class $$ChannelsTableOrderingComposer - extends Composer<_$DriftChatDatabase, $ChannelsTable> { - $$ChannelsTableOrderingComposer({ +class $$MessagesTableOrderingComposer + extends Composer<_$DriftChatDatabase, $MessagesTable> { + $$MessagesTableOrderingComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -8719,48 +10000,131 @@ class $$ChannelsTableOrderingComposer ColumnOrderings get id => $composableBuilder( column: $table.id, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get messageText => $composableBuilder( + column: $table.messageText, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get attachments => $composableBuilder( + column: $table.attachments, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get state => $composableBuilder( + column: $table.state, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get type => $composableBuilder( column: $table.type, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get cid => $composableBuilder( - column: $table.cid, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get mentionedUsers => $composableBuilder( + column: $table.mentionedUsers, + builder: (column) => ColumnOrderings(column)); - ColumnOrderings get ownCapabilities => $composableBuilder( - column: $table.ownCapabilities, + ColumnOrderings get reactionGroups => $composableBuilder( + column: $table.reactionGroups, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get config => $composableBuilder( - column: $table.config, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get parentId => $composableBuilder( + column: $table.parentId, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get frozen => $composableBuilder( - column: $table.frozen, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get quotedMessageId => $composableBuilder( + column: $table.quotedMessageId, + builder: (column) => ColumnOrderings(column)); - ColumnOrderings get lastMessageAt => $composableBuilder( - column: $table.lastMessageAt, + ColumnOrderings get pollId => $composableBuilder( + column: $table.pollId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get replyCount => $composableBuilder( + column: $table.replyCount, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get showInChannel => $composableBuilder( + column: $table.showInChannel, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get createdAt => $composableBuilder( - column: $table.createdAt, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get shadowed => $composableBuilder( + column: $table.shadowed, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get updatedAt => $composableBuilder( - column: $table.updatedAt, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get command => $composableBuilder( + column: $table.command, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get deletedAt => $composableBuilder( - column: $table.deletedAt, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get localCreatedAt => $composableBuilder( + column: $table.localCreatedAt, + builder: (column) => ColumnOrderings(column)); - ColumnOrderings get memberCount => $composableBuilder( - column: $table.memberCount, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get remoteCreatedAt => $composableBuilder( + column: $table.remoteCreatedAt, + builder: (column) => ColumnOrderings(column)); - ColumnOrderings get createdById => $composableBuilder( - column: $table.createdById, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get localUpdatedAt => $composableBuilder( + column: $table.localUpdatedAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get remoteUpdatedAt => $composableBuilder( + column: $table.remoteUpdatedAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get localDeletedAt => $composableBuilder( + column: $table.localDeletedAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get remoteDeletedAt => $composableBuilder( + column: $table.remoteDeletedAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get messageTextUpdatedAt => $composableBuilder( + column: $table.messageTextUpdatedAt, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get userId => $composableBuilder( + column: $table.userId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get pinned => $composableBuilder( + column: $table.pinned, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get pinnedAt => $composableBuilder( + column: $table.pinnedAt, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get pinExpires => $composableBuilder( + column: $table.pinExpires, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get pinnedByUserId => $composableBuilder( + column: $table.pinnedByUserId, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get i18n => $composableBuilder( + column: $table.i18n, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get restrictedVisibility => $composableBuilder( + column: $table.restrictedVisibility, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get draftMessageId => $composableBuilder( + column: $table.draftMessageId, + builder: (column) => ColumnOrderings(column)); ColumnOrderings get extraData => $composableBuilder( column: $table.extraData, builder: (column) => ColumnOrderings(column)); + + $$ChannelsTableOrderingComposer get channelCid { + final $$ChannelsTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$ChannelsTableOrderingComposer( + $db: $db, + $table: $db.channels, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } } -class $$ChannelsTableAnnotationComposer - extends Composer<_$DriftChatDatabase, $ChannelsTable> { - $$ChannelsTableAnnotationComposer({ +class $$MessagesTableAnnotationComposer + extends Composer<_$DriftChatDatabase, $MessagesTable> { + $$MessagesTableAnnotationComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -8770,72 +10134,125 @@ class $$ChannelsTableAnnotationComposer GeneratedColumn get id => $composableBuilder(column: $table.id, builder: (column) => column); + GeneratedColumn get messageText => $composableBuilder( + column: $table.messageText, builder: (column) => column); + + GeneratedColumnWithTypeConverter, String> get attachments => + $composableBuilder( + column: $table.attachments, builder: (column) => column); + + GeneratedColumn get state => + $composableBuilder(column: $table.state, builder: (column) => column); + GeneratedColumn get type => $composableBuilder(column: $table.type, builder: (column) => column); - GeneratedColumn get cid => - $composableBuilder(column: $table.cid, builder: (column) => column); - - GeneratedColumnWithTypeConverter?, String> get ownCapabilities => + GeneratedColumnWithTypeConverter, String> get mentionedUsers => $composableBuilder( - column: $table.ownCapabilities, builder: (column) => column); + column: $table.mentionedUsers, builder: (column) => column); - GeneratedColumnWithTypeConverter, String> get config => - $composableBuilder(column: $table.config, builder: (column) => column); + GeneratedColumnWithTypeConverter?, String> + get reactionGroups => $composableBuilder( + column: $table.reactionGroups, builder: (column) => column); - GeneratedColumn get frozen => - $composableBuilder(column: $table.frozen, builder: (column) => column); + GeneratedColumn get parentId => + $composableBuilder(column: $table.parentId, builder: (column) => column); - GeneratedColumn get lastMessageAt => $composableBuilder( - column: $table.lastMessageAt, builder: (column) => column); + GeneratedColumn get quotedMessageId => $composableBuilder( + column: $table.quotedMessageId, builder: (column) => column); - GeneratedColumn get createdAt => - $composableBuilder(column: $table.createdAt, builder: (column) => column); + GeneratedColumn get pollId => + $composableBuilder(column: $table.pollId, builder: (column) => column); - GeneratedColumn get updatedAt => - $composableBuilder(column: $table.updatedAt, builder: (column) => column); + GeneratedColumn get replyCount => $composableBuilder( + column: $table.replyCount, builder: (column) => column); - GeneratedColumn get deletedAt => - $composableBuilder(column: $table.deletedAt, builder: (column) => column); + GeneratedColumn get showInChannel => $composableBuilder( + column: $table.showInChannel, builder: (column) => column); - GeneratedColumn get memberCount => $composableBuilder( - column: $table.memberCount, builder: (column) => column); + GeneratedColumn get shadowed => + $composableBuilder(column: $table.shadowed, builder: (column) => column); - GeneratedColumn get createdById => $composableBuilder( - column: $table.createdById, builder: (column) => column); + GeneratedColumn get command => + $composableBuilder(column: $table.command, builder: (column) => column); + + GeneratedColumn get localCreatedAt => $composableBuilder( + column: $table.localCreatedAt, builder: (column) => column); + + GeneratedColumn get remoteCreatedAt => $composableBuilder( + column: $table.remoteCreatedAt, builder: (column) => column); + + GeneratedColumn get localUpdatedAt => $composableBuilder( + column: $table.localUpdatedAt, builder: (column) => column); + + GeneratedColumn get remoteUpdatedAt => $composableBuilder( + column: $table.remoteUpdatedAt, builder: (column) => column); + + GeneratedColumn get localDeletedAt => $composableBuilder( + column: $table.localDeletedAt, builder: (column) => column); + + GeneratedColumn get remoteDeletedAt => $composableBuilder( + column: $table.remoteDeletedAt, builder: (column) => column); + + GeneratedColumn get messageTextUpdatedAt => $composableBuilder( + column: $table.messageTextUpdatedAt, builder: (column) => column); + + GeneratedColumn get userId => + $composableBuilder(column: $table.userId, builder: (column) => column); + + GeneratedColumn get pinned => + $composableBuilder(column: $table.pinned, builder: (column) => column); + + GeneratedColumn get pinnedAt => + $composableBuilder(column: $table.pinnedAt, builder: (column) => column); + + GeneratedColumn get pinExpires => $composableBuilder( + column: $table.pinExpires, builder: (column) => column); + + GeneratedColumn get pinnedByUserId => $composableBuilder( + column: $table.pinnedByUserId, builder: (column) => column); + + GeneratedColumnWithTypeConverter?, String> get i18n => + $composableBuilder(column: $table.i18n, builder: (column) => column); + + GeneratedColumnWithTypeConverter?, String> + get restrictedVisibility => $composableBuilder( + column: $table.restrictedVisibility, builder: (column) => column); + + GeneratedColumn get draftMessageId => $composableBuilder( + column: $table.draftMessageId, builder: (column) => column); GeneratedColumnWithTypeConverter?, String> get extraData => $composableBuilder( column: $table.extraData, builder: (column) => column); - Expression messagesRefs( - Expression Function($$MessagesTableAnnotationComposer a) f) { - final $$MessagesTableAnnotationComposer composer = $composerBuilder( + $$ChannelsTableAnnotationComposer get channelCid { + final $$ChannelsTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, - referencedTable: $db.messages, - getReferencedColumn: (t) => t.channelCid, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$MessagesTableAnnotationComposer( + $$ChannelsTableAnnotationComposer( $db: $db, - $table: $db.messages, + $table: $db.channels, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer, )); - return f(composer); + return composer; } Expression draftMessagesRefs( Expression Function($$DraftMessagesTableAnnotationComposer a) f) { final $$DraftMessagesTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, + getCurrentColumn: (t) => t.id, referencedTable: $db.draftMessages, - getReferencedColumn: (t) => t.channelCid, + getReferencedColumn: (t) => t.parentId, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => @@ -8850,19 +10267,19 @@ class $$ChannelsTableAnnotationComposer return f(composer); } - Expression membersRefs( - Expression Function($$MembersTableAnnotationComposer a) f) { - final $$MembersTableAnnotationComposer composer = $composerBuilder( + Expression locationsRefs( + Expression Function($$LocationsTableAnnotationComposer a) f) { + final $$LocationsTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, - referencedTable: $db.members, - getReferencedColumn: (t) => t.channelCid, + getCurrentColumn: (t) => t.id, + referencedTable: $db.locations, + getReferencedColumn: (t) => t.messageId, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$MembersTableAnnotationComposer( + $$LocationsTableAnnotationComposer( $db: $db, - $table: $db.members, + $table: $db.locations, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -8871,19 +10288,19 @@ class $$ChannelsTableAnnotationComposer return f(composer); } - Expression readsRefs( - Expression Function($$ReadsTableAnnotationComposer a) f) { - final $$ReadsTableAnnotationComposer composer = $composerBuilder( + Expression reactionsRefs( + Expression Function($$ReactionsTableAnnotationComposer a) f) { + final $$ReactionsTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.cid, - referencedTable: $db.reads, - getReferencedColumn: (t) => t.channelCid, + getCurrentColumn: (t) => t.id, + referencedTable: $db.reactions, + getReferencedColumn: (t) => t.messageId, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ReadsTableAnnotationComposer( + $$ReactionsTableAnnotationComposer( $db: $db, - $table: $db.reads, + $table: $db.reactions, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -8893,166 +10310,252 @@ class $$ChannelsTableAnnotationComposer } } -class $$ChannelsTableTableManager extends RootTableManager< +class $$MessagesTableTableManager extends RootTableManager< _$DriftChatDatabase, - $ChannelsTable, - ChannelEntity, - $$ChannelsTableFilterComposer, - $$ChannelsTableOrderingComposer, - $$ChannelsTableAnnotationComposer, - $$ChannelsTableCreateCompanionBuilder, - $$ChannelsTableUpdateCompanionBuilder, - (ChannelEntity, $$ChannelsTableReferences), - ChannelEntity, + $MessagesTable, + MessageEntity, + $$MessagesTableFilterComposer, + $$MessagesTableOrderingComposer, + $$MessagesTableAnnotationComposer, + $$MessagesTableCreateCompanionBuilder, + $$MessagesTableUpdateCompanionBuilder, + (MessageEntity, $$MessagesTableReferences), + MessageEntity, PrefetchHooks Function( - {bool messagesRefs, + {bool channelCid, bool draftMessagesRefs, - bool membersRefs, - bool readsRefs})> { - $$ChannelsTableTableManager(_$DriftChatDatabase db, $ChannelsTable table) + bool locationsRefs, + bool reactionsRefs})> { + $$MessagesTableTableManager(_$DriftChatDatabase db, $MessagesTable table) : super(TableManagerState( db: db, table: table, createFilteringComposer: () => - $$ChannelsTableFilterComposer($db: db, $table: table), + $$MessagesTableFilterComposer($db: db, $table: table), createOrderingComposer: () => - $$ChannelsTableOrderingComposer($db: db, $table: table), + $$MessagesTableOrderingComposer($db: db, $table: table), createComputedFieldComposer: () => - $$ChannelsTableAnnotationComposer($db: db, $table: table), + $$MessagesTableAnnotationComposer($db: db, $table: table), updateCompanionCallback: ({ Value id = const Value.absent(), + Value messageText = const Value.absent(), + Value> attachments = const Value.absent(), + Value state = const Value.absent(), Value type = const Value.absent(), - Value cid = const Value.absent(), - Value?> ownCapabilities = const Value.absent(), - Value> config = const Value.absent(), - Value frozen = const Value.absent(), - 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> mentionedUsers = const Value.absent(), + Value?> reactionGroups = + const Value.absent(), + Value parentId = const Value.absent(), + Value quotedMessageId = const Value.absent(), + Value pollId = const Value.absent(), + Value replyCount = const Value.absent(), + Value showInChannel = const Value.absent(), + Value shadowed = const Value.absent(), + Value command = const Value.absent(), + Value localCreatedAt = const Value.absent(), + Value remoteCreatedAt = const Value.absent(), + Value localUpdatedAt = const Value.absent(), + Value remoteUpdatedAt = const Value.absent(), + Value localDeletedAt = const Value.absent(), + Value remoteDeletedAt = const Value.absent(), + Value messageTextUpdatedAt = const Value.absent(), + Value userId = const Value.absent(), + Value pinned = const Value.absent(), + Value pinnedAt = const Value.absent(), + Value pinExpires = const Value.absent(), + Value pinnedByUserId = const Value.absent(), + Value channelCid = const Value.absent(), + Value?> i18n = const Value.absent(), + Value?> restrictedVisibility = const Value.absent(), + Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => - ChannelsCompanion( + MessagesCompanion( id: id, + messageText: messageText, + attachments: attachments, + state: state, type: type, - cid: cid, - ownCapabilities: ownCapabilities, - config: config, - frozen: frozen, - lastMessageAt: lastMessageAt, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - memberCount: memberCount, - createdById: createdById, + mentionedUsers: mentionedUsers, + reactionGroups: reactionGroups, + parentId: parentId, + quotedMessageId: quotedMessageId, + pollId: pollId, + replyCount: replyCount, + showInChannel: showInChannel, + shadowed: shadowed, + command: command, + localCreatedAt: localCreatedAt, + remoteCreatedAt: remoteCreatedAt, + localUpdatedAt: localUpdatedAt, + remoteUpdatedAt: remoteUpdatedAt, + localDeletedAt: localDeletedAt, + remoteDeletedAt: remoteDeletedAt, + messageTextUpdatedAt: messageTextUpdatedAt, + userId: userId, + pinned: pinned, + pinnedAt: pinnedAt, + pinExpires: pinExpires, + pinnedByUserId: pinnedByUserId, + channelCid: channelCid, + i18n: i18n, + restrictedVisibility: restrictedVisibility, + draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), createCompanionCallback: ({ required String id, - required String type, - required String cid, - Value?> ownCapabilities = const Value.absent(), - required Map config, - Value frozen = const Value.absent(), - 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 messageText = const Value.absent(), + required List attachments, + required String state, + Value type = const Value.absent(), + required List mentionedUsers, + Value?> reactionGroups = + const Value.absent(), + Value parentId = const Value.absent(), + Value quotedMessageId = const Value.absent(), + Value pollId = const Value.absent(), + Value replyCount = const Value.absent(), + Value showInChannel = const Value.absent(), + Value shadowed = const Value.absent(), + Value command = const Value.absent(), + Value localCreatedAt = const Value.absent(), + Value remoteCreatedAt = const Value.absent(), + Value localUpdatedAt = const Value.absent(), + Value remoteUpdatedAt = const Value.absent(), + Value localDeletedAt = const Value.absent(), + Value remoteDeletedAt = const Value.absent(), + Value messageTextUpdatedAt = const Value.absent(), + Value userId = const Value.absent(), + Value pinned = const Value.absent(), + Value pinnedAt = const Value.absent(), + Value pinExpires = const Value.absent(), + Value pinnedByUserId = const Value.absent(), + required String channelCid, + Value?> i18n = const Value.absent(), + Value?> restrictedVisibility = const Value.absent(), + Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => - ChannelsCompanion.insert( + MessagesCompanion.insert( id: id, + messageText: messageText, + attachments: attachments, + state: state, type: type, - cid: cid, - ownCapabilities: ownCapabilities, - config: config, - frozen: frozen, - lastMessageAt: lastMessageAt, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - memberCount: memberCount, - createdById: createdById, + mentionedUsers: mentionedUsers, + reactionGroups: reactionGroups, + parentId: parentId, + quotedMessageId: quotedMessageId, + pollId: pollId, + replyCount: replyCount, + showInChannel: showInChannel, + shadowed: shadowed, + command: command, + localCreatedAt: localCreatedAt, + remoteCreatedAt: remoteCreatedAt, + localUpdatedAt: localUpdatedAt, + remoteUpdatedAt: remoteUpdatedAt, + localDeletedAt: localDeletedAt, + remoteDeletedAt: remoteDeletedAt, + messageTextUpdatedAt: messageTextUpdatedAt, + userId: userId, + pinned: pinned, + pinnedAt: pinnedAt, + pinExpires: pinExpires, + pinnedByUserId: pinnedByUserId, + channelCid: channelCid, + i18n: i18n, + restrictedVisibility: restrictedVisibility, + draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), withReferenceMapper: (p0) => p0 .map((e) => - (e.readTable(table), $$ChannelsTableReferences(db, table, e))) + (e.readTable(table), $$MessagesTableReferences(db, table, e))) .toList(), prefetchHooksCallback: ( - {messagesRefs = false, + {channelCid = false, draftMessagesRefs = false, - membersRefs = false, - readsRefs = false}) { + locationsRefs = false, + reactionsRefs = false}) { return PrefetchHooks( db: db, explicitlyWatchedTables: [ - if (messagesRefs) db.messages, if (draftMessagesRefs) db.draftMessages, - if (membersRefs) db.members, - if (readsRefs) db.reads + if (locationsRefs) db.locations, + if (reactionsRefs) db.reactions ], - addJoins: null, + addJoins: < + T extends TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic>>(state) { + if (channelCid) { + state = state.withJoin( + currentTable: table, + currentColumn: table.channelCid, + referencedTable: + $$MessagesTableReferences._channelCidTable(db), + referencedColumn: + $$MessagesTableReferences._channelCidTable(db).cid, + ) as T; + } + + return state; + }, getPrefetchedDataCallback: (items) async { return [ - if (messagesRefs) - await $_getPrefetchedData( - currentTable: table, - referencedTable: - $$ChannelsTableReferences._messagesRefsTable(db), - managerFromTypedResult: (p0) => - $$ChannelsTableReferences(db, table, p0) - .messagesRefs, - referencedItemsForCurrentItem: - (item, referencedItems) => referencedItems - .where((e) => e.channelCid == item.cid), - typedResults: items), if (draftMessagesRefs) - await $_getPrefetchedData( currentTable: table, - referencedTable: $$ChannelsTableReferences + referencedTable: $$MessagesTableReferences ._draftMessagesRefsTable(db), managerFromTypedResult: (p0) => - $$ChannelsTableReferences(db, table, p0) + $$MessagesTableReferences(db, table, p0) .draftMessagesRefs, - referencedItemsForCurrentItem: - (item, referencedItems) => referencedItems - .where((e) => e.channelCid == item.cid), + referencedItemsForCurrentItem: (item, + referencedItems) => + referencedItems.where((e) => e.parentId == item.id), typedResults: items), - if (membersRefs) - await $_getPrefetchedData( + if (locationsRefs) + await $_getPrefetchedData( currentTable: table, referencedTable: - $$ChannelsTableReferences._membersRefsTable(db), + $$MessagesTableReferences._locationsRefsTable(db), managerFromTypedResult: (p0) => - $$ChannelsTableReferences(db, table, p0) - .membersRefs, + $$MessagesTableReferences(db, table, p0) + .locationsRefs, referencedItemsForCurrentItem: (item, referencedItems) => referencedItems - .where((e) => e.channelCid == item.cid), + .where((e) => e.messageId == item.id), typedResults: items), - if (readsRefs) - await $_getPrefetchedData( + if (reactionsRefs) + await $_getPrefetchedData( currentTable: table, referencedTable: - $$ChannelsTableReferences._readsRefsTable(db), + $$MessagesTableReferences._reactionsRefsTable(db), managerFromTypedResult: (p0) => - $$ChannelsTableReferences(db, table, p0).readsRefs, + $$MessagesTableReferences(db, table, p0) + .reactionsRefs, referencedItemsForCurrentItem: (item, referencedItems) => referencedItems - .where((e) => e.channelCid == item.cid), + .where((e) => e.messageId == item.id), typedResults: items) ]; }, @@ -9061,98 +10564,82 @@ class $$ChannelsTableTableManager extends RootTableManager< )); } -typedef $$ChannelsTableProcessedTableManager = ProcessedTableManager< +typedef $$MessagesTableProcessedTableManager = ProcessedTableManager< _$DriftChatDatabase, - $ChannelsTable, - ChannelEntity, - $$ChannelsTableFilterComposer, - $$ChannelsTableOrderingComposer, - $$ChannelsTableAnnotationComposer, - $$ChannelsTableCreateCompanionBuilder, - $$ChannelsTableUpdateCompanionBuilder, - (ChannelEntity, $$ChannelsTableReferences), - ChannelEntity, + $MessagesTable, + MessageEntity, + $$MessagesTableFilterComposer, + $$MessagesTableOrderingComposer, + $$MessagesTableAnnotationComposer, + $$MessagesTableCreateCompanionBuilder, + $$MessagesTableUpdateCompanionBuilder, + (MessageEntity, $$MessagesTableReferences), + MessageEntity, PrefetchHooks Function( - {bool messagesRefs, + {bool channelCid, bool draftMessagesRefs, - bool membersRefs, - bool readsRefs})>; -typedef $$MessagesTableCreateCompanionBuilder = MessagesCompanion Function({ + bool locationsRefs, + bool reactionsRefs})>; +typedef $$DraftMessagesTableCreateCompanionBuilder = DraftMessagesCompanion + Function({ required String id, Value messageText, required List attachments, - required String state, Value type, required List mentionedUsers, - Value?> reactionGroups, Value parentId, Value quotedMessageId, Value pollId, - Value replyCount, Value showInChannel, - Value shadowed, Value command, - Value localCreatedAt, - Value remoteCreatedAt, - Value localUpdatedAt, - Value remoteUpdatedAt, - Value localDeletedAt, - Value remoteDeletedAt, - Value messageTextUpdatedAt, - Value userId, - Value pinned, - Value pinnedAt, - Value pinExpires, - Value pinnedByUserId, + Value silent, + Value createdAt, required String channelCid, - Value?> i18n, - Value?> restrictedVisibility, - Value draftMessageId, Value?> extraData, Value rowid, }); -typedef $$MessagesTableUpdateCompanionBuilder = MessagesCompanion Function({ +typedef $$DraftMessagesTableUpdateCompanionBuilder = DraftMessagesCompanion + Function({ Value id, Value messageText, Value> attachments, - Value state, Value type, Value> mentionedUsers, - Value?> reactionGroups, Value parentId, Value quotedMessageId, Value pollId, - Value replyCount, Value showInChannel, - Value shadowed, Value command, - Value localCreatedAt, - Value remoteCreatedAt, - Value localUpdatedAt, - Value remoteUpdatedAt, - Value localDeletedAt, - Value remoteDeletedAt, - Value messageTextUpdatedAt, - Value userId, - Value pinned, - Value pinnedAt, - Value pinExpires, - Value pinnedByUserId, + Value silent, + Value createdAt, Value channelCid, - Value?> i18n, - Value?> restrictedVisibility, - Value draftMessageId, Value?> extraData, Value rowid, }); -final class $$MessagesTableReferences - extends BaseReferences<_$DriftChatDatabase, $MessagesTable, MessageEntity> { - $$MessagesTableReferences(super.$_db, super.$_table, super.$_typedResult); +final class $$DraftMessagesTableReferences extends BaseReferences< + _$DriftChatDatabase, $DraftMessagesTable, DraftMessageEntity> { + $$DraftMessagesTableReferences( + super.$_db, super.$_table, super.$_typedResult); + + static $MessagesTable _parentIdTable(_$DriftChatDatabase db) => + db.messages.createAlias( + $_aliasNameGenerator(db.draftMessages.parentId, db.messages.id)); + + $$MessagesTableProcessedTableManager? get parentId { + final $_column = $_itemColumn('parent_id'); + if ($_column == null) return null; + final manager = $$MessagesTableTableManager($_db, $_db.messages) + .filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_parentIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } static $ChannelsTable _channelCidTable(_$DriftChatDatabase db) => db.channels.createAlias( - $_aliasNameGenerator(db.messages.channelCid, db.channels.cid)); + $_aliasNameGenerator(db.draftMessages.channelCid, db.channels.cid)); $$ChannelsTableProcessedTableManager get channelCid { final $_column = $_itemColumn('channel_cid')!; @@ -9164,41 +10651,11 @@ final class $$MessagesTableReferences return ProcessedTableManager( manager.$state.copyWith(prefetchedData: [item])); } - - static MultiTypedResultKey<$DraftMessagesTable, List> - _draftMessagesRefsTable(_$DriftChatDatabase db) => - MultiTypedResultKey.fromTable(db.draftMessages, - aliasName: $_aliasNameGenerator( - db.messages.id, db.draftMessages.parentId)); - - $$DraftMessagesTableProcessedTableManager get draftMessagesRefs { - final manager = $$DraftMessagesTableTableManager($_db, $_db.draftMessages) - .filter((f) => f.parentId.id.sqlEquals($_itemColumn('id')!)); - - final cache = $_typedResult.readTableOrNull(_draftMessagesRefsTable($_db)); - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: cache)); - } - - static MultiTypedResultKey<$ReactionsTable, List> - _reactionsRefsTable(_$DriftChatDatabase db) => - MultiTypedResultKey.fromTable(db.reactions, - aliasName: - $_aliasNameGenerator(db.messages.id, db.reactions.messageId)); - - $$ReactionsTableProcessedTableManager get reactionsRefs { - final manager = $$ReactionsTableTableManager($_db, $_db.reactions) - .filter((f) => f.messageId.id.sqlEquals($_itemColumn('id')!)); - - final cache = $_typedResult.readTableOrNull(_reactionsRefsTable($_db)); - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: cache)); - } } -class $$MessagesTableFilterComposer - extends Composer<_$DriftChatDatabase, $MessagesTable> { - $$MessagesTableFilterComposer({ +class $$DraftMessagesTableFilterComposer + extends Composer<_$DriftChatDatabase, $DraftMessagesTable> { + $$DraftMessagesTableFilterComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -9216,9 +10673,6 @@ class $$MessagesTableFilterComposer column: $table.attachments, builder: (column) => ColumnWithTypeConverterFilters(column)); - ColumnFilters get state => $composableBuilder( - column: $table.state, builder: (column) => ColumnFilters(column)); - ColumnFilters get type => $composableBuilder( column: $table.type, builder: (column) => ColumnFilters(column)); @@ -9227,15 +10681,6 @@ class $$MessagesTableFilterComposer column: $table.mentionedUsers, builder: (column) => ColumnWithTypeConverterFilters(column)); - ColumnWithTypeConverterFilters?, - Map, String> - get reactionGroups => $composableBuilder( - column: $table.reactionGroups, - builder: (column) => ColumnWithTypeConverterFilters(column)); - - ColumnFilters get parentId => $composableBuilder( - column: $table.parentId, builder: (column) => ColumnFilters(column)); - ColumnFilters get quotedMessageId => $composableBuilder( column: $table.quotedMessageId, builder: (column) => ColumnFilters(column)); @@ -9243,76 +10688,17 @@ class $$MessagesTableFilterComposer ColumnFilters get pollId => $composableBuilder( column: $table.pollId, builder: (column) => ColumnFilters(column)); - ColumnFilters get replyCount => $composableBuilder( - column: $table.replyCount, builder: (column) => ColumnFilters(column)); - ColumnFilters get showInChannel => $composableBuilder( column: $table.showInChannel, builder: (column) => ColumnFilters(column)); - ColumnFilters get shadowed => $composableBuilder( - column: $table.shadowed, builder: (column) => ColumnFilters(column)); - ColumnFilters get command => $composableBuilder( column: $table.command, builder: (column) => ColumnFilters(column)); - ColumnFilters get localCreatedAt => $composableBuilder( - column: $table.localCreatedAt, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get remoteCreatedAt => $composableBuilder( - column: $table.remoteCreatedAt, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get localUpdatedAt => $composableBuilder( - column: $table.localUpdatedAt, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get remoteUpdatedAt => $composableBuilder( - column: $table.remoteUpdatedAt, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get localDeletedAt => $composableBuilder( - column: $table.localDeletedAt, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get remoteDeletedAt => $composableBuilder( - column: $table.remoteDeletedAt, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get messageTextUpdatedAt => $composableBuilder( - column: $table.messageTextUpdatedAt, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get userId => $composableBuilder( - column: $table.userId, builder: (column) => ColumnFilters(column)); - - ColumnFilters get pinned => $composableBuilder( - column: $table.pinned, builder: (column) => ColumnFilters(column)); - - ColumnFilters get pinnedAt => $composableBuilder( - column: $table.pinnedAt, builder: (column) => ColumnFilters(column)); - - ColumnFilters get pinExpires => $composableBuilder( - column: $table.pinExpires, builder: (column) => ColumnFilters(column)); - - ColumnFilters get pinnedByUserId => $composableBuilder( - column: $table.pinnedByUserId, - builder: (column) => ColumnFilters(column)); - - ColumnWithTypeConverterFilters?, Map, - String> - get i18n => $composableBuilder( - column: $table.i18n, - builder: (column) => ColumnWithTypeConverterFilters(column)); - - ColumnWithTypeConverterFilters?, List, String> - get restrictedVisibility => $composableBuilder( - column: $table.restrictedVisibility, - builder: (column) => ColumnWithTypeConverterFilters(column)); + ColumnFilters get silent => $composableBuilder( + column: $table.silent, builder: (column) => ColumnFilters(column)); - ColumnFilters get draftMessageId => $composableBuilder( - column: $table.draftMessageId, - builder: (column) => ColumnFilters(column)); + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); ColumnWithTypeConverterFilters?, Map, String> @@ -9320,18 +10706,18 @@ class $$MessagesTableFilterComposer column: $table.extraData, builder: (column) => ColumnWithTypeConverterFilters(column)); - $$ChannelsTableFilterComposer get channelCid { - final $$ChannelsTableFilterComposer composer = $composerBuilder( + $$MessagesTableFilterComposer get parentId { + final $$MessagesTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.channelCid, - referencedTable: $db.channels, - getReferencedColumn: (t) => t.cid, + getCurrentColumn: (t) => t.parentId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.id, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ChannelsTableFilterComposer( + $$MessagesTableFilterComposer( $db: $db, - $table: $db.channels, + $table: $db.messages, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -9340,52 +10726,30 @@ class $$MessagesTableFilterComposer return composer; } - Expression draftMessagesRefs( - Expression Function($$DraftMessagesTableFilterComposer f) f) { - final $$DraftMessagesTableFilterComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.draftMessages, - getReferencedColumn: (t) => t.parentId, - builder: (joinBuilder, - {$addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer}) => - $$DraftMessagesTableFilterComposer( - $db: $db, - $table: $db.draftMessages, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - )); - return f(composer); - } - - Expression reactionsRefs( - Expression Function($$ReactionsTableFilterComposer f) f) { - final $$ReactionsTableFilterComposer composer = $composerBuilder( + $$ChannelsTableFilterComposer get channelCid { + final $$ChannelsTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.reactions, - getReferencedColumn: (t) => t.messageId, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ReactionsTableFilterComposer( + $$ChannelsTableFilterComposer( $db: $db, - $table: $db.reactions, + $table: $db.channels, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer, )); - return f(composer); + return composer; } } -class $$MessagesTableOrderingComposer - extends Composer<_$DriftChatDatabase, $MessagesTable> { - $$MessagesTableOrderingComposer({ +class $$DraftMessagesTableOrderingComposer + extends Composer<_$DriftChatDatabase, $DraftMessagesTable> { + $$DraftMessagesTableOrderingComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -9399,103 +10763,58 @@ class $$MessagesTableOrderingComposer column: $table.messageText, builder: (column) => ColumnOrderings(column)); ColumnOrderings get attachments => $composableBuilder( - column: $table.attachments, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get state => $composableBuilder( - column: $table.state, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get type => $composableBuilder( - column: $table.type, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get mentionedUsers => $composableBuilder( - column: $table.mentionedUsers, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get reactionGroups => $composableBuilder( - column: $table.reactionGroups, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get parentId => $composableBuilder( - column: $table.parentId, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get quotedMessageId => $composableBuilder( - column: $table.quotedMessageId, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get pollId => $composableBuilder( - column: $table.pollId, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get replyCount => $composableBuilder( - column: $table.replyCount, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get showInChannel => $composableBuilder( - column: $table.showInChannel, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get shadowed => $composableBuilder( - column: $table.shadowed, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get command => $composableBuilder( - column: $table.command, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get localCreatedAt => $composableBuilder( - column: $table.localCreatedAt, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get remoteCreatedAt => $composableBuilder( - column: $table.remoteCreatedAt, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get localUpdatedAt => $composableBuilder( - column: $table.localUpdatedAt, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get remoteUpdatedAt => $composableBuilder( - column: $table.remoteUpdatedAt, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get localDeletedAt => $composableBuilder( - column: $table.localDeletedAt, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get remoteDeletedAt => $composableBuilder( - column: $table.remoteDeletedAt, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get messageTextUpdatedAt => $composableBuilder( - column: $table.messageTextUpdatedAt, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get userId => $composableBuilder( - column: $table.userId, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get pinned => $composableBuilder( - column: $table.pinned, builder: (column) => ColumnOrderings(column)); + column: $table.attachments, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get pinnedAt => $composableBuilder( - column: $table.pinnedAt, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get type => $composableBuilder( + column: $table.type, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get pinExpires => $composableBuilder( - column: $table.pinExpires, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get mentionedUsers => $composableBuilder( + column: $table.mentionedUsers, + builder: (column) => ColumnOrderings(column)); - ColumnOrderings get pinnedByUserId => $composableBuilder( - column: $table.pinnedByUserId, + ColumnOrderings get quotedMessageId => $composableBuilder( + column: $table.quotedMessageId, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get i18n => $composableBuilder( - column: $table.i18n, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get pollId => $composableBuilder( + column: $table.pollId, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get restrictedVisibility => $composableBuilder( - column: $table.restrictedVisibility, + ColumnOrderings get showInChannel => $composableBuilder( + column: $table.showInChannel, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get draftMessageId => $composableBuilder( - column: $table.draftMessageId, - builder: (column) => ColumnOrderings(column)); + ColumnOrderings get command => $composableBuilder( + column: $table.command, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get silent => $composableBuilder( + column: $table.silent, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); ColumnOrderings get extraData => $composableBuilder( column: $table.extraData, builder: (column) => ColumnOrderings(column)); + $$MessagesTableOrderingComposer get parentId { + final $$MessagesTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.parentId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MessagesTableOrderingComposer( + $db: $db, + $table: $db.messages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } + $$ChannelsTableOrderingComposer get channelCid { final $$ChannelsTableOrderingComposer composer = $composerBuilder( composer: this, @@ -9517,9 +10836,9 @@ class $$MessagesTableOrderingComposer } } -class $$MessagesTableAnnotationComposer - extends Composer<_$DriftChatDatabase, $MessagesTable> { - $$MessagesTableAnnotationComposer({ +class $$DraftMessagesTableAnnotationComposer + extends Composer<_$DriftChatDatabase, $DraftMessagesTable> { + $$DraftMessagesTableAnnotationComposer({ required super.$db, required super.$table, super.joinBuilder, @@ -9536,9 +10855,6 @@ class $$MessagesTableAnnotationComposer $composableBuilder( column: $table.attachments, builder: (column) => column); - GeneratedColumn get state => - $composableBuilder(column: $table.state, builder: (column) => column); - GeneratedColumn get type => $composableBuilder(column: $table.type, builder: (column) => column); @@ -9546,93 +10862,40 @@ class $$MessagesTableAnnotationComposer $composableBuilder( column: $table.mentionedUsers, builder: (column) => column); - GeneratedColumnWithTypeConverter?, String> - get reactionGroups => $composableBuilder( - column: $table.reactionGroups, builder: (column) => column); - - GeneratedColumn get parentId => - $composableBuilder(column: $table.parentId, builder: (column) => column); - GeneratedColumn get quotedMessageId => $composableBuilder( column: $table.quotedMessageId, builder: (column) => column); GeneratedColumn get pollId => $composableBuilder(column: $table.pollId, builder: (column) => column); - GeneratedColumn get replyCount => $composableBuilder( - column: $table.replyCount, builder: (column) => column); - GeneratedColumn get showInChannel => $composableBuilder( column: $table.showInChannel, builder: (column) => column); - GeneratedColumn get shadowed => - $composableBuilder(column: $table.shadowed, builder: (column) => column); - GeneratedColumn get command => $composableBuilder(column: $table.command, builder: (column) => column); - GeneratedColumn get localCreatedAt => $composableBuilder( - column: $table.localCreatedAt, builder: (column) => column); - - GeneratedColumn get remoteCreatedAt => $composableBuilder( - column: $table.remoteCreatedAt, builder: (column) => column); - - GeneratedColumn get localUpdatedAt => $composableBuilder( - column: $table.localUpdatedAt, builder: (column) => column); - - GeneratedColumn get remoteUpdatedAt => $composableBuilder( - column: $table.remoteUpdatedAt, builder: (column) => column); - - GeneratedColumn get localDeletedAt => $composableBuilder( - column: $table.localDeletedAt, builder: (column) => column); - - GeneratedColumn get remoteDeletedAt => $composableBuilder( - column: $table.remoteDeletedAt, builder: (column) => column); - - GeneratedColumn get messageTextUpdatedAt => $composableBuilder( - column: $table.messageTextUpdatedAt, builder: (column) => column); - - GeneratedColumn get userId => - $composableBuilder(column: $table.userId, builder: (column) => column); - - GeneratedColumn get pinned => - $composableBuilder(column: $table.pinned, builder: (column) => column); - - GeneratedColumn get pinnedAt => - $composableBuilder(column: $table.pinnedAt, builder: (column) => column); - - GeneratedColumn get pinExpires => $composableBuilder( - column: $table.pinExpires, builder: (column) => column); - - GeneratedColumn get pinnedByUserId => $composableBuilder( - column: $table.pinnedByUserId, builder: (column) => column); - - GeneratedColumnWithTypeConverter?, String> get i18n => - $composableBuilder(column: $table.i18n, builder: (column) => column); - - GeneratedColumnWithTypeConverter?, String> - get restrictedVisibility => $composableBuilder( - column: $table.restrictedVisibility, builder: (column) => column); + GeneratedColumn get silent => + $composableBuilder(column: $table.silent, builder: (column) => column); - GeneratedColumn get draftMessageId => $composableBuilder( - column: $table.draftMessageId, builder: (column) => column); + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); GeneratedColumnWithTypeConverter?, String> get extraData => $composableBuilder( column: $table.extraData, builder: (column) => column); - $$ChannelsTableAnnotationComposer get channelCid { - final $$ChannelsTableAnnotationComposer composer = $composerBuilder( + $$MessagesTableAnnotationComposer get parentId { + final $$MessagesTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.channelCid, - referencedTable: $db.channels, - getReferencedColumn: (t) => t.cid, + getCurrentColumn: (t) => t.parentId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.id, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ChannelsTableAnnotationComposer( + $$MessagesTableAnnotationComposer( $db: $db, - $table: $db.channels, + $table: $db.messages, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -9641,138 +10904,81 @@ class $$MessagesTableAnnotationComposer return composer; } - Expression draftMessagesRefs( - Expression Function($$DraftMessagesTableAnnotationComposer a) f) { - final $$DraftMessagesTableAnnotationComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.draftMessages, - getReferencedColumn: (t) => t.parentId, - builder: (joinBuilder, - {$addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer}) => - $$DraftMessagesTableAnnotationComposer( - $db: $db, - $table: $db.draftMessages, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - )); - return f(composer); - } - - Expression reactionsRefs( - Expression Function($$ReactionsTableAnnotationComposer a) f) { - final $$ReactionsTableAnnotationComposer composer = $composerBuilder( + $$ChannelsTableAnnotationComposer get channelCid { + final $$ChannelsTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.reactions, - getReferencedColumn: (t) => t.messageId, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ReactionsTableAnnotationComposer( + $$ChannelsTableAnnotationComposer( $db: $db, - $table: $db.reactions, + $table: $db.channels, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer, )); - return f(composer); + return composer; } } -class $$MessagesTableTableManager extends RootTableManager< +class $$DraftMessagesTableTableManager extends RootTableManager< _$DriftChatDatabase, - $MessagesTable, - MessageEntity, - $$MessagesTableFilterComposer, - $$MessagesTableOrderingComposer, - $$MessagesTableAnnotationComposer, - $$MessagesTableCreateCompanionBuilder, - $$MessagesTableUpdateCompanionBuilder, - (MessageEntity, $$MessagesTableReferences), - MessageEntity, - PrefetchHooks Function( - {bool channelCid, bool draftMessagesRefs, bool reactionsRefs})> { - $$MessagesTableTableManager(_$DriftChatDatabase db, $MessagesTable table) + $DraftMessagesTable, + DraftMessageEntity, + $$DraftMessagesTableFilterComposer, + $$DraftMessagesTableOrderingComposer, + $$DraftMessagesTableAnnotationComposer, + $$DraftMessagesTableCreateCompanionBuilder, + $$DraftMessagesTableUpdateCompanionBuilder, + (DraftMessageEntity, $$DraftMessagesTableReferences), + DraftMessageEntity, + PrefetchHooks Function({bool parentId, bool channelCid})> { + $$DraftMessagesTableTableManager( + _$DriftChatDatabase db, $DraftMessagesTable table) : super(TableManagerState( db: db, table: table, createFilteringComposer: () => - $$MessagesTableFilterComposer($db: db, $table: table), + $$DraftMessagesTableFilterComposer($db: db, $table: table), createOrderingComposer: () => - $$MessagesTableOrderingComposer($db: db, $table: table), + $$DraftMessagesTableOrderingComposer($db: db, $table: table), createComputedFieldComposer: () => - $$MessagesTableAnnotationComposer($db: db, $table: table), + $$DraftMessagesTableAnnotationComposer($db: db, $table: table), updateCompanionCallback: ({ Value id = const Value.absent(), Value messageText = const Value.absent(), Value> attachments = const Value.absent(), - Value state = const Value.absent(), Value type = const Value.absent(), Value> mentionedUsers = const Value.absent(), - Value?> reactionGroups = - const Value.absent(), Value parentId = const Value.absent(), Value quotedMessageId = const Value.absent(), Value pollId = const Value.absent(), - Value replyCount = const Value.absent(), Value showInChannel = const Value.absent(), - Value shadowed = const Value.absent(), Value command = const Value.absent(), - Value localCreatedAt = const Value.absent(), - Value remoteCreatedAt = const Value.absent(), - Value localUpdatedAt = const Value.absent(), - Value remoteUpdatedAt = const Value.absent(), - Value localDeletedAt = const Value.absent(), - Value remoteDeletedAt = const Value.absent(), - Value messageTextUpdatedAt = const Value.absent(), - Value userId = const Value.absent(), - Value pinned = const Value.absent(), - Value pinnedAt = const Value.absent(), - Value pinExpires = const Value.absent(), - Value pinnedByUserId = const Value.absent(), + Value silent = const Value.absent(), + Value createdAt = const Value.absent(), Value channelCid = const Value.absent(), - Value?> i18n = const Value.absent(), - Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => - MessagesCompanion( - id: id, - messageText: messageText, - attachments: attachments, - state: state, - type: type, - mentionedUsers: mentionedUsers, - reactionGroups: reactionGroups, - parentId: parentId, - quotedMessageId: quotedMessageId, - pollId: pollId, - replyCount: replyCount, - showInChannel: showInChannel, - shadowed: shadowed, - command: command, - localCreatedAt: localCreatedAt, - remoteCreatedAt: remoteCreatedAt, - localUpdatedAt: localUpdatedAt, - remoteUpdatedAt: remoteUpdatedAt, - localDeletedAt: localDeletedAt, - remoteDeletedAt: remoteDeletedAt, - messageTextUpdatedAt: messageTextUpdatedAt, - userId: userId, - pinned: pinned, - pinnedAt: pinnedAt, - pinExpires: pinExpires, - pinnedByUserId: pinnedByUserId, + DraftMessagesCompanion( + id: id, + messageText: messageText, + attachments: attachments, + type: type, + mentionedUsers: mentionedUsers, + parentId: parentId, + quotedMessageId: quotedMessageId, + pollId: pollId, + showInChannel: showInChannel, + command: command, + silent: silent, + createdAt: createdAt, channelCid: channelCid, - i18n: i18n, - restrictedVisibility: restrictedVisibility, - draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), @@ -9780,85 +10986,46 @@ class $$MessagesTableTableManager extends RootTableManager< required String id, Value messageText = const Value.absent(), required List attachments, - required String state, Value type = const Value.absent(), required List mentionedUsers, - Value?> reactionGroups = - const Value.absent(), Value parentId = const Value.absent(), Value quotedMessageId = const Value.absent(), Value pollId = const Value.absent(), - Value replyCount = const Value.absent(), Value showInChannel = const Value.absent(), - Value shadowed = const Value.absent(), Value command = const Value.absent(), - Value localCreatedAt = const Value.absent(), - Value remoteCreatedAt = const Value.absent(), - Value localUpdatedAt = const Value.absent(), - Value remoteUpdatedAt = const Value.absent(), - Value localDeletedAt = const Value.absent(), - Value remoteDeletedAt = const Value.absent(), - Value messageTextUpdatedAt = const Value.absent(), - Value userId = const Value.absent(), - Value pinned = const Value.absent(), - Value pinnedAt = const Value.absent(), - Value pinExpires = const Value.absent(), - Value pinnedByUserId = const Value.absent(), + Value silent = const Value.absent(), + Value createdAt = const Value.absent(), required String channelCid, - Value?> i18n = const Value.absent(), - Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => - MessagesCompanion.insert( + DraftMessagesCompanion.insert( id: id, messageText: messageText, attachments: attachments, - state: state, type: type, mentionedUsers: mentionedUsers, - reactionGroups: reactionGroups, parentId: parentId, quotedMessageId: quotedMessageId, pollId: pollId, - replyCount: replyCount, showInChannel: showInChannel, - shadowed: shadowed, command: command, - localCreatedAt: localCreatedAt, - remoteCreatedAt: remoteCreatedAt, - localUpdatedAt: localUpdatedAt, - remoteUpdatedAt: remoteUpdatedAt, - localDeletedAt: localDeletedAt, - remoteDeletedAt: remoteDeletedAt, - messageTextUpdatedAt: messageTextUpdatedAt, - userId: userId, - pinned: pinned, - pinnedAt: pinnedAt, - pinExpires: pinExpires, - pinnedByUserId: pinnedByUserId, + silent: silent, + createdAt: createdAt, channelCid: channelCid, - i18n: i18n, - restrictedVisibility: restrictedVisibility, - draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), withReferenceMapper: (p0) => p0 - .map((e) => - (e.readTable(table), $$MessagesTableReferences(db, table, e))) + .map((e) => ( + e.readTable(table), + $$DraftMessagesTableReferences(db, table, e) + )) .toList(), - prefetchHooksCallback: ( - {channelCid = false, - draftMessagesRefs = false, - reactionsRefs = false}) { + prefetchHooksCallback: ({parentId = false, channelCid = false}) { return PrefetchHooks( db: db, - explicitlyWatchedTables: [ - if (draftMessagesRefs) db.draftMessages, - if (reactionsRefs) db.reactions - ], + explicitlyWatchedTables: [], addJoins: < T extends TableManagerState< dynamic, @@ -9872,205 +11039,152 @@ class $$MessagesTableTableManager extends RootTableManager< dynamic, dynamic, dynamic>>(state) { + if (parentId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.parentId, + referencedTable: + $$DraftMessagesTableReferences._parentIdTable(db), + referencedColumn: + $$DraftMessagesTableReferences._parentIdTable(db).id, + ) as T; + } if (channelCid) { state = state.withJoin( currentTable: table, currentColumn: table.channelCid, referencedTable: - $$MessagesTableReferences._channelCidTable(db), + $$DraftMessagesTableReferences._channelCidTable(db), referencedColumn: - $$MessagesTableReferences._channelCidTable(db).cid, + $$DraftMessagesTableReferences._channelCidTable(db).cid, ) as T; } return state; }, getPrefetchedDataCallback: (items) async { - return [ - if (draftMessagesRefs) - await $_getPrefetchedData( - currentTable: table, - referencedTable: $$MessagesTableReferences - ._draftMessagesRefsTable(db), - managerFromTypedResult: (p0) => - $$MessagesTableReferences(db, table, p0) - .draftMessagesRefs, - referencedItemsForCurrentItem: (item, - referencedItems) => - referencedItems.where((e) => e.parentId == item.id), - typedResults: items), - if (reactionsRefs) - await $_getPrefetchedData( - currentTable: table, - referencedTable: - $$MessagesTableReferences._reactionsRefsTable(db), - managerFromTypedResult: (p0) => - $$MessagesTableReferences(db, table, p0) - .reactionsRefs, - referencedItemsForCurrentItem: - (item, referencedItems) => referencedItems - .where((e) => e.messageId == item.id), - typedResults: items) - ]; + return []; }, ); }, )); } -typedef $$MessagesTableProcessedTableManager = ProcessedTableManager< +typedef $$DraftMessagesTableProcessedTableManager = ProcessedTableManager< _$DriftChatDatabase, - $MessagesTable, - MessageEntity, - $$MessagesTableFilterComposer, - $$MessagesTableOrderingComposer, - $$MessagesTableAnnotationComposer, - $$MessagesTableCreateCompanionBuilder, - $$MessagesTableUpdateCompanionBuilder, - (MessageEntity, $$MessagesTableReferences), - MessageEntity, - PrefetchHooks Function( - {bool channelCid, bool draftMessagesRefs, bool reactionsRefs})>; -typedef $$DraftMessagesTableCreateCompanionBuilder = DraftMessagesCompanion - Function({ - required String id, - Value messageText, - required List attachments, - Value type, - required List mentionedUsers, - Value parentId, - Value quotedMessageId, - Value pollId, - Value showInChannel, - Value command, - Value silent, + $DraftMessagesTable, + DraftMessageEntity, + $$DraftMessagesTableFilterComposer, + $$DraftMessagesTableOrderingComposer, + $$DraftMessagesTableAnnotationComposer, + $$DraftMessagesTableCreateCompanionBuilder, + $$DraftMessagesTableUpdateCompanionBuilder, + (DraftMessageEntity, $$DraftMessagesTableReferences), + DraftMessageEntity, + PrefetchHooks Function({bool parentId, bool channelCid})>; +typedef $$LocationsTableCreateCompanionBuilder = LocationsCompanion Function({ + Value channelCid, + Value messageId, + Value userId, + required double latitude, + required double longitude, + required String createdByDeviceId, + Value endAt, Value createdAt, - required String channelCid, - Value?> extraData, + Value updatedAt, Value rowid, }); -typedef $$DraftMessagesTableUpdateCompanionBuilder = DraftMessagesCompanion - Function({ - Value id, - Value messageText, - Value> attachments, - Value type, - Value> mentionedUsers, - Value parentId, - Value quotedMessageId, - Value pollId, - Value showInChannel, - Value command, - Value silent, +typedef $$LocationsTableUpdateCompanionBuilder = LocationsCompanion Function({ + Value channelCid, + Value messageId, + Value userId, + Value latitude, + Value longitude, + Value createdByDeviceId, + Value endAt, Value createdAt, - Value channelCid, - Value?> extraData, + Value updatedAt, Value rowid, }); -final class $$DraftMessagesTableReferences extends BaseReferences< - _$DriftChatDatabase, $DraftMessagesTable, DraftMessageEntity> { - $$DraftMessagesTableReferences( - super.$_db, super.$_table, super.$_typedResult); +final class $$LocationsTableReferences extends BaseReferences< + _$DriftChatDatabase, $LocationsTable, LocationEntity> { + $$LocationsTableReferences(super.$_db, super.$_table, super.$_typedResult); - static $MessagesTable _parentIdTable(_$DriftChatDatabase db) => - db.messages.createAlias( - $_aliasNameGenerator(db.draftMessages.parentId, db.messages.id)); + static $ChannelsTable _channelCidTable(_$DriftChatDatabase db) => + db.channels.createAlias( + $_aliasNameGenerator(db.locations.channelCid, db.channels.cid)); - $$MessagesTableProcessedTableManager? get parentId { - final $_column = $_itemColumn('parent_id'); + $$ChannelsTableProcessedTableManager? get channelCid { + final $_column = $_itemColumn('channel_cid'); if ($_column == null) return null; - final manager = $$MessagesTableTableManager($_db, $_db.messages) - .filter((f) => f.id.sqlEquals($_column)); - final item = $_typedResult.readTableOrNull(_parentIdTable($_db)); + final manager = $$ChannelsTableTableManager($_db, $_db.channels) + .filter((f) => f.cid.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_channelCidTable($_db)); if (item == null) return manager; return ProcessedTableManager( manager.$state.copyWith(prefetchedData: [item])); } - static $ChannelsTable _channelCidTable(_$DriftChatDatabase db) => - db.channels.createAlias( - $_aliasNameGenerator(db.draftMessages.channelCid, db.channels.cid)); - - $$ChannelsTableProcessedTableManager get channelCid { - final $_column = $_itemColumn('channel_cid')!; + static $MessagesTable _messageIdTable(_$DriftChatDatabase db) => + db.messages.createAlias( + $_aliasNameGenerator(db.locations.messageId, db.messages.id)); - final manager = $$ChannelsTableTableManager($_db, $_db.channels) - .filter((f) => f.cid.sqlEquals($_column)); - final item = $_typedResult.readTableOrNull(_channelCidTable($_db)); + $$MessagesTableProcessedTableManager? get messageId { + final $_column = $_itemColumn('message_id'); + if ($_column == null) return null; + final manager = $$MessagesTableTableManager($_db, $_db.messages) + .filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_messageIdTable($_db)); if (item == null) return manager; return ProcessedTableManager( manager.$state.copyWith(prefetchedData: [item])); } } -class $$DraftMessagesTableFilterComposer - extends Composer<_$DriftChatDatabase, $DraftMessagesTable> { - $$DraftMessagesTableFilterComposer({ +class $$LocationsTableFilterComposer + extends Composer<_$DriftChatDatabase, $LocationsTable> { + $$LocationsTableFilterComposer({ required super.$db, required super.$table, super.joinBuilder, super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); - ColumnFilters get id => $composableBuilder( - column: $table.id, builder: (column) => ColumnFilters(column)); - - ColumnFilters get messageText => $composableBuilder( - column: $table.messageText, builder: (column) => ColumnFilters(column)); - - ColumnWithTypeConverterFilters, List, String> - get attachments => $composableBuilder( - column: $table.attachments, - builder: (column) => ColumnWithTypeConverterFilters(column)); + ColumnFilters get userId => $composableBuilder( + column: $table.userId, builder: (column) => ColumnFilters(column)); - ColumnFilters get type => $composableBuilder( - column: $table.type, builder: (column) => ColumnFilters(column)); + ColumnFilters get latitude => $composableBuilder( + column: $table.latitude, builder: (column) => ColumnFilters(column)); - ColumnWithTypeConverterFilters, List, String> - get mentionedUsers => $composableBuilder( - column: $table.mentionedUsers, - builder: (column) => ColumnWithTypeConverterFilters(column)); + ColumnFilters get longitude => $composableBuilder( + column: $table.longitude, builder: (column) => ColumnFilters(column)); - ColumnFilters get quotedMessageId => $composableBuilder( - column: $table.quotedMessageId, + ColumnFilters get createdByDeviceId => $composableBuilder( + column: $table.createdByDeviceId, builder: (column) => ColumnFilters(column)); - ColumnFilters get pollId => $composableBuilder( - column: $table.pollId, builder: (column) => ColumnFilters(column)); - - ColumnFilters get showInChannel => $composableBuilder( - column: $table.showInChannel, builder: (column) => ColumnFilters(column)); - - ColumnFilters get command => $composableBuilder( - column: $table.command, builder: (column) => ColumnFilters(column)); - - ColumnFilters get silent => $composableBuilder( - column: $table.silent, builder: (column) => ColumnFilters(column)); + ColumnFilters get endAt => $composableBuilder( + column: $table.endAt, builder: (column) => ColumnFilters(column)); ColumnFilters get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnFilters(column)); - ColumnWithTypeConverterFilters?, Map, - String> - get extraData => $composableBuilder( - column: $table.extraData, - builder: (column) => ColumnWithTypeConverterFilters(column)); + ColumnFilters get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnFilters(column)); - $$MessagesTableFilterComposer get parentId { - final $$MessagesTableFilterComposer composer = $composerBuilder( + $$ChannelsTableFilterComposer get channelCid { + final $$ChannelsTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.parentId, - referencedTable: $db.messages, - getReferencedColumn: (t) => t.id, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$MessagesTableFilterComposer( + $$ChannelsTableFilterComposer( $db: $db, - $table: $db.messages, + $table: $db.channels, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -10079,18 +11193,18 @@ class $$DraftMessagesTableFilterComposer return composer; } - $$ChannelsTableFilterComposer get channelCid { - final $$ChannelsTableFilterComposer composer = $composerBuilder( + $$MessagesTableFilterComposer get messageId { + final $$MessagesTableFilterComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.channelCid, - referencedTable: $db.channels, - getReferencedColumn: (t) => t.cid, + getCurrentColumn: (t) => t.messageId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.id, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ChannelsTableFilterComposer( + $$MessagesTableFilterComposer( $db: $db, - $table: $db.channels, + $table: $db.messages, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -10100,66 +11214,49 @@ class $$DraftMessagesTableFilterComposer } } -class $$DraftMessagesTableOrderingComposer - extends Composer<_$DriftChatDatabase, $DraftMessagesTable> { - $$DraftMessagesTableOrderingComposer({ +class $$LocationsTableOrderingComposer + extends Composer<_$DriftChatDatabase, $LocationsTable> { + $$LocationsTableOrderingComposer({ required super.$db, required super.$table, super.joinBuilder, super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); - ColumnOrderings get id => $composableBuilder( - column: $table.id, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get messageText => $composableBuilder( - column: $table.messageText, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get attachments => $composableBuilder( - column: $table.attachments, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get type => $composableBuilder( - column: $table.type, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get mentionedUsers => $composableBuilder( - column: $table.mentionedUsers, - builder: (column) => ColumnOrderings(column)); + ColumnOrderings get userId => $composableBuilder( + column: $table.userId, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get quotedMessageId => $composableBuilder( - column: $table.quotedMessageId, - builder: (column) => ColumnOrderings(column)); + ColumnOrderings get latitude => $composableBuilder( + column: $table.latitude, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get pollId => $composableBuilder( - column: $table.pollId, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get longitude => $composableBuilder( + column: $table.longitude, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get showInChannel => $composableBuilder( - column: $table.showInChannel, + ColumnOrderings get createdByDeviceId => $composableBuilder( + column: $table.createdByDeviceId, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get command => $composableBuilder( - column: $table.command, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get silent => $composableBuilder( - column: $table.silent, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get endAt => $composableBuilder( + column: $table.endAt, builder: (column) => ColumnOrderings(column)); ColumnOrderings get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get extraData => $composableBuilder( - column: $table.extraData, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => ColumnOrderings(column)); - $$MessagesTableOrderingComposer get parentId { - final $$MessagesTableOrderingComposer composer = $composerBuilder( + $$ChannelsTableOrderingComposer get channelCid { + final $$ChannelsTableOrderingComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.parentId, - referencedTable: $db.messages, - getReferencedColumn: (t) => t.id, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$MessagesTableOrderingComposer( + $$ChannelsTableOrderingComposer( $db: $db, - $table: $db.messages, + $table: $db.channels, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -10168,18 +11265,18 @@ class $$DraftMessagesTableOrderingComposer return composer; } - $$ChannelsTableOrderingComposer get channelCid { - final $$ChannelsTableOrderingComposer composer = $composerBuilder( + $$MessagesTableOrderingComposer get messageId { + final $$MessagesTableOrderingComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.channelCid, - referencedTable: $db.channels, - getReferencedColumn: (t) => t.cid, + getCurrentColumn: (t) => t.messageId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.id, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ChannelsTableOrderingComposer( + $$MessagesTableOrderingComposer( $db: $db, - $table: $db.channels, + $table: $db.messages, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -10189,66 +11286,48 @@ class $$DraftMessagesTableOrderingComposer } } -class $$DraftMessagesTableAnnotationComposer - extends Composer<_$DriftChatDatabase, $DraftMessagesTable> { - $$DraftMessagesTableAnnotationComposer({ +class $$LocationsTableAnnotationComposer + extends Composer<_$DriftChatDatabase, $LocationsTable> { + $$LocationsTableAnnotationComposer({ required super.$db, required super.$table, super.joinBuilder, super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); - GeneratedColumn get id => - $composableBuilder(column: $table.id, builder: (column) => column); - - GeneratedColumn get messageText => $composableBuilder( - column: $table.messageText, builder: (column) => column); - - GeneratedColumnWithTypeConverter, String> get attachments => - $composableBuilder( - column: $table.attachments, builder: (column) => column); - - GeneratedColumn get type => - $composableBuilder(column: $table.type, builder: (column) => column); - - GeneratedColumnWithTypeConverter, String> get mentionedUsers => - $composableBuilder( - column: $table.mentionedUsers, builder: (column) => column); - - GeneratedColumn get quotedMessageId => $composableBuilder( - column: $table.quotedMessageId, builder: (column) => column); + GeneratedColumn get userId => + $composableBuilder(column: $table.userId, builder: (column) => column); - GeneratedColumn get pollId => - $composableBuilder(column: $table.pollId, builder: (column) => column); + GeneratedColumn get latitude => + $composableBuilder(column: $table.latitude, builder: (column) => column); - GeneratedColumn get showInChannel => $composableBuilder( - column: $table.showInChannel, builder: (column) => column); + GeneratedColumn get longitude => + $composableBuilder(column: $table.longitude, builder: (column) => column); - GeneratedColumn get command => - $composableBuilder(column: $table.command, builder: (column) => column); + GeneratedColumn get createdByDeviceId => $composableBuilder( + column: $table.createdByDeviceId, builder: (column) => column); - GeneratedColumn get silent => - $composableBuilder(column: $table.silent, builder: (column) => column); + GeneratedColumn get endAt => + $composableBuilder(column: $table.endAt, builder: (column) => column); GeneratedColumn get createdAt => $composableBuilder(column: $table.createdAt, builder: (column) => column); - GeneratedColumnWithTypeConverter?, String> - get extraData => $composableBuilder( - column: $table.extraData, builder: (column) => column); + GeneratedColumn get updatedAt => + $composableBuilder(column: $table.updatedAt, builder: (column) => column); - $$MessagesTableAnnotationComposer get parentId { - final $$MessagesTableAnnotationComposer composer = $composerBuilder( + $$ChannelsTableAnnotationComposer get channelCid { + final $$ChannelsTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.parentId, - referencedTable: $db.messages, - getReferencedColumn: (t) => t.id, + getCurrentColumn: (t) => t.channelCid, + referencedTable: $db.channels, + getReferencedColumn: (t) => t.cid, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$MessagesTableAnnotationComposer( + $$ChannelsTableAnnotationComposer( $db: $db, - $table: $db.messages, + $table: $db.channels, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -10257,18 +11336,18 @@ class $$DraftMessagesTableAnnotationComposer return composer; } - $$ChannelsTableAnnotationComposer get channelCid { - final $$ChannelsTableAnnotationComposer composer = $composerBuilder( + $$MessagesTableAnnotationComposer get messageId { + final $$MessagesTableAnnotationComposer composer = $composerBuilder( composer: this, - getCurrentColumn: (t) => t.channelCid, - referencedTable: $db.channels, - getReferencedColumn: (t) => t.cid, + getCurrentColumn: (t) => t.messageId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.id, builder: (joinBuilder, {$addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer}) => - $$ChannelsTableAnnotationComposer( + $$MessagesTableAnnotationComposer( $db: $db, - $table: $db.channels, + $table: $db.messages, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -10278,104 +11357,83 @@ class $$DraftMessagesTableAnnotationComposer } } -class $$DraftMessagesTableTableManager extends RootTableManager< +class $$LocationsTableTableManager extends RootTableManager< _$DriftChatDatabase, - $DraftMessagesTable, - DraftMessageEntity, - $$DraftMessagesTableFilterComposer, - $$DraftMessagesTableOrderingComposer, - $$DraftMessagesTableAnnotationComposer, - $$DraftMessagesTableCreateCompanionBuilder, - $$DraftMessagesTableUpdateCompanionBuilder, - (DraftMessageEntity, $$DraftMessagesTableReferences), - DraftMessageEntity, - PrefetchHooks Function({bool parentId, bool channelCid})> { - $$DraftMessagesTableTableManager( - _$DriftChatDatabase db, $DraftMessagesTable table) + $LocationsTable, + LocationEntity, + $$LocationsTableFilterComposer, + $$LocationsTableOrderingComposer, + $$LocationsTableAnnotationComposer, + $$LocationsTableCreateCompanionBuilder, + $$LocationsTableUpdateCompanionBuilder, + (LocationEntity, $$LocationsTableReferences), + LocationEntity, + PrefetchHooks Function({bool channelCid, bool messageId})> { + $$LocationsTableTableManager(_$DriftChatDatabase db, $LocationsTable table) : super(TableManagerState( db: db, table: table, createFilteringComposer: () => - $$DraftMessagesTableFilterComposer($db: db, $table: table), + $$LocationsTableFilterComposer($db: db, $table: table), createOrderingComposer: () => - $$DraftMessagesTableOrderingComposer($db: db, $table: table), + $$LocationsTableOrderingComposer($db: db, $table: table), createComputedFieldComposer: () => - $$DraftMessagesTableAnnotationComposer($db: db, $table: table), + $$LocationsTableAnnotationComposer($db: db, $table: table), updateCompanionCallback: ({ - Value id = const Value.absent(), - Value messageText = const Value.absent(), - Value> attachments = const Value.absent(), - Value type = const Value.absent(), - Value> mentionedUsers = const Value.absent(), - Value parentId = const Value.absent(), - Value quotedMessageId = const Value.absent(), - Value pollId = const Value.absent(), - Value showInChannel = const Value.absent(), - Value command = const Value.absent(), - Value silent = const Value.absent(), + Value channelCid = const Value.absent(), + Value messageId = const Value.absent(), + Value userId = const Value.absent(), + Value latitude = const Value.absent(), + Value longitude = const Value.absent(), + Value createdByDeviceId = const Value.absent(), + Value endAt = const Value.absent(), Value createdAt = const Value.absent(), - Value channelCid = const Value.absent(), - Value?> extraData = const Value.absent(), + Value updatedAt = const Value.absent(), Value rowid = const Value.absent(), }) => - DraftMessagesCompanion( - id: id, - messageText: messageText, - attachments: attachments, - type: type, - mentionedUsers: mentionedUsers, - parentId: parentId, - quotedMessageId: quotedMessageId, - pollId: pollId, - showInChannel: showInChannel, - command: command, - silent: silent, - createdAt: createdAt, + LocationsCompanion( channelCid: channelCid, - extraData: extraData, + messageId: messageId, + userId: userId, + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, rowid: rowid, ), createCompanionCallback: ({ - required String id, - Value messageText = const Value.absent(), - required List attachments, - Value type = const Value.absent(), - required List mentionedUsers, - Value parentId = const Value.absent(), - Value quotedMessageId = const Value.absent(), - Value pollId = const Value.absent(), - Value showInChannel = const Value.absent(), - Value command = const Value.absent(), - Value silent = const Value.absent(), + Value channelCid = const Value.absent(), + Value messageId = const Value.absent(), + Value userId = const Value.absent(), + required double latitude, + required double longitude, + required String createdByDeviceId, + Value endAt = const Value.absent(), Value createdAt = const Value.absent(), - required String channelCid, - Value?> extraData = const Value.absent(), + Value updatedAt = const Value.absent(), Value rowid = const Value.absent(), }) => - DraftMessagesCompanion.insert( - id: id, - messageText: messageText, - attachments: attachments, - type: type, - mentionedUsers: mentionedUsers, - parentId: parentId, - quotedMessageId: quotedMessageId, - pollId: pollId, - showInChannel: showInChannel, - command: command, - silent: silent, - createdAt: createdAt, + LocationsCompanion.insert( channelCid: channelCid, - extraData: extraData, + messageId: messageId, + userId: userId, + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, rowid: rowid, ), withReferenceMapper: (p0) => p0 .map((e) => ( e.readTable(table), - $$DraftMessagesTableReferences(db, table, e) + $$LocationsTableReferences(db, table, e) )) .toList(), - prefetchHooksCallback: ({parentId = false, channelCid = false}) { + prefetchHooksCallback: ({channelCid = false, messageId = false}) { return PrefetchHooks( db: db, explicitlyWatchedTables: [], @@ -10392,24 +11450,24 @@ class $$DraftMessagesTableTableManager extends RootTableManager< dynamic, dynamic, dynamic>>(state) { - if (parentId) { + if (channelCid) { state = state.withJoin( currentTable: table, - currentColumn: table.parentId, + currentColumn: table.channelCid, referencedTable: - $$DraftMessagesTableReferences._parentIdTable(db), + $$LocationsTableReferences._channelCidTable(db), referencedColumn: - $$DraftMessagesTableReferences._parentIdTable(db).id, + $$LocationsTableReferences._channelCidTable(db).cid, ) as T; } - if (channelCid) { + if (messageId) { state = state.withJoin( currentTable: table, - currentColumn: table.channelCid, + currentColumn: table.messageId, referencedTable: - $$DraftMessagesTableReferences._channelCidTable(db), + $$LocationsTableReferences._messageIdTable(db), referencedColumn: - $$DraftMessagesTableReferences._channelCidTable(db).cid, + $$LocationsTableReferences._messageIdTable(db).id, ) as T; } @@ -10423,18 +11481,18 @@ class $$DraftMessagesTableTableManager extends RootTableManager< )); } -typedef $$DraftMessagesTableProcessedTableManager = ProcessedTableManager< +typedef $$LocationsTableProcessedTableManager = ProcessedTableManager< _$DriftChatDatabase, - $DraftMessagesTable, - DraftMessageEntity, - $$DraftMessagesTableFilterComposer, - $$DraftMessagesTableOrderingComposer, - $$DraftMessagesTableAnnotationComposer, - $$DraftMessagesTableCreateCompanionBuilder, - $$DraftMessagesTableUpdateCompanionBuilder, - (DraftMessageEntity, $$DraftMessagesTableReferences), - DraftMessageEntity, - PrefetchHooks Function({bool parentId, bool channelCid})>; + $LocationsTable, + LocationEntity, + $$LocationsTableFilterComposer, + $$LocationsTableOrderingComposer, + $$LocationsTableAnnotationComposer, + $$LocationsTableCreateCompanionBuilder, + $$LocationsTableUpdateCompanionBuilder, + (LocationEntity, $$LocationsTableReferences), + LocationEntity, + PrefetchHooks Function({bool channelCid, bool messageId})>; typedef $$PinnedMessagesTableCreateCompanionBuilder = PinnedMessagesCompanion Function({ required String id, @@ -13772,6 +14830,8 @@ class $DriftChatDatabaseManager { $$MessagesTableTableManager(_db, _db.messages); $$DraftMessagesTableTableManager get draftMessages => $$DraftMessagesTableTableManager(_db, _db.draftMessages); + $$LocationsTableTableManager get locations => + $$LocationsTableTableManager(_db, _db.locations); $$PinnedMessagesTableTableManager get pinnedMessages => $$PinnedMessagesTableTableManager(_db, _db.pinnedMessages); $$PollsTableTableManager get polls => diff --git a/packages/stream_chat_persistence/lib/src/entity/entity.dart b/packages/stream_chat_persistence/lib/src/entity/entity.dart index 2ef87c5cb6..58fb6a164d 100644 --- a/packages/stream_chat_persistence/lib/src/entity/entity.dart +++ b/packages/stream_chat_persistence/lib/src/entity/entity.dart @@ -2,6 +2,7 @@ export 'channel_queries.dart'; export 'channels.dart'; export 'connection_events.dart'; export 'draft_messages.dart'; +export 'locations.dart'; export 'members.dart'; export 'messages.dart'; export 'pinned_message_reactions.dart'; diff --git a/packages/stream_chat_persistence/lib/src/entity/locations.dart b/packages/stream_chat_persistence/lib/src/entity/locations.dart new file mode 100644 index 0000000000..04417c3d61 --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/entity/locations.dart @@ -0,0 +1,43 @@ +// coverage:ignore-file +import 'package:drift/drift.dart'; +import 'package:stream_chat_persistence/src/entity/channels.dart'; +import 'package:stream_chat_persistence/src/entity/messages.dart'; + +/// Represents a [Locations] table in [DriftChatDatabase]. +@DataClassName('LocationEntity') +class Locations extends Table { + /// The channel CID where the location is shared + TextColumn get channelCid => text() + .nullable() + .references(Channels, #cid, onDelete: KeyAction.cascade)(); + + /// The ID of the message that contains this shared location + TextColumn get messageId => text() + .nullable() + .references(Messages, #id, onDelete: KeyAction.cascade)(); + + /// The ID of the user who shared the location + TextColumn get userId => text().nullable()(); + + /// The latitude of the shared location + RealColumn get latitude => real()(); + + /// The longitude of the shared location + RealColumn get longitude => real()(); + + /// The ID of the device that created the location + TextColumn get createdByDeviceId => text()(); + + /// The date at which the shared location will end (for live locations) + /// If null, this is a static location + DateTimeColumn get endAt => dateTime().nullable()(); + + /// The date at which the location was created + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); + + /// The date at which the location was last updated + DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); + + @override + Set get primaryKey => {messageId}; +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/location_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/location_mapper.dart new file mode 100644 index 0000000000..bcbc18be1b --- /dev/null +++ b/packages/stream_chat_persistence/lib/src/mapper/location_mapper.dart @@ -0,0 +1,40 @@ +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; + +/// Useful mapping functions for [LocationEntity] +extension LocationEntityX on LocationEntity { + /// Maps a [LocationEntity] into [Location] + Location toLocation({ + ChannelModel? channel, + Message? message, + }) => + Location( + channelCid: channelCid, + channel: channel, + messageId: messageId, + message: message, + userId: userId, + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, + ); +} + +/// Useful mapping functions for [Location] +extension LocationX on Location { + /// Maps a [Location] into [LocationEntity] + LocationEntity toEntity() => LocationEntity( + channelCid: channelCid, + messageId: messageId, + userId: userId, + latitude: latitude, + longitude: longitude, + createdByDeviceId: createdByDeviceId, + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, + ); +} diff --git a/packages/stream_chat_persistence/lib/src/mapper/mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/mapper.dart index 742776f504..45b35dba81 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/mapper.dart @@ -1,6 +1,7 @@ export 'channel_mapper.dart'; export 'draft_message_mapper.dart'; export 'event_mapper.dart'; +export 'location_mapper.dart'; export 'member_mapper.dart'; export 'message_mapper.dart'; export 'pinned_message_mapper.dart'; 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 8e4d9d544b..a2770e2a93 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart @@ -14,6 +14,7 @@ extension MessageEntityX on MessageEntity { Message? quotedMessage, Poll? poll, Draft? draft, + Location? sharedLocation, }) => Message( shadowed: shadowed, @@ -54,6 +55,7 @@ extension MessageEntityX on MessageEntity { i18n: i18n, restrictedVisibility: restrictedVisibility, draft: draft, + sharedLocation: sharedLocation, ); } diff --git a/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart index a87b716ec2..9a0544427c 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart @@ -13,6 +13,8 @@ extension PinnedMessageEntityX on PinnedMessageEntity { List? ownReactions, Message? quotedMessage, Poll? poll, + Draft? draft, + Location? sharedLocation, }) => Message( shadowed: shadowed, @@ -52,6 +54,8 @@ extension PinnedMessageEntityX on PinnedMessageEntity { mentionedUsers.map((e) => User.fromJson(jsonDecode(e))).toList(), i18n: i18n, restrictedVisibility: restrictedVisibility, + draft: draft, + sharedLocation: sharedLocation, ); } @@ -90,5 +94,6 @@ extension PMessageX on Message { pinnedByUserId: pinnedBy?.id, i18n: i18n, restrictedVisibility: restrictedVisibility, + draftMessageId: draft?.message.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 c76991948b..bb4e14ed0a 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 @@ -224,6 +224,20 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { ); } + @override + Future> getLocationsByCid(String cid) async { + assert(_debugIsConnected, ''); + _logger.info('getLocationsByCid'); + return db!.locationDao.getLocationsByCid(cid); + } + + @override + Future getLocationByMessageId(String messageId) async { + assert(_debugIsConnected, ''); + _logger.info('getLocationByMessageId'); + return db!.locationDao.getLocationByMessageId(messageId); + } + @override Future> getReadsByCid(String cid) async { assert(_debugIsConnected, ''); @@ -394,6 +408,13 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { return db!.userDao.updateUsers(users); } + @override + Future updateLocations(List locations) async { + assert(_debugIsConnected, ''); + _logger.info('updateLocations'); + return db!.locationDao.updateLocations(locations); + } + @override Future deletePinnedMessageReactionsByMessageId( List messageIds, @@ -437,6 +458,20 @@ class StreamChatPersistenceClient extends ChatPersistenceClient { ); } + @override + Future deleteLocationsByCid(String cid) { + assert(_debugIsConnected, ''); + _logger.info('deleteLocationsByCid'); + return db!.locationDao.deleteLocationsByCid(cid); + } + + @override + Future deleteLocationsByMessageIds(List messageIds) { + assert(_debugIsConnected, ''); + _logger.info('deleteLocationsByMessageIds'); + return db!.locationDao.deleteLocationsByMessageIds(messageIds); + } + @override Future updateChannelThreads( String cid, diff --git a/packages/stream_chat_persistence/test/mock_chat_database.dart b/packages/stream_chat_persistence/test/mock_chat_database.dart index 6f1f61af0d..cb0f06a541 100644 --- a/packages/stream_chat_persistence/test/mock_chat_database.dart +++ b/packages/stream_chat_persistence/test/mock_chat_database.dart @@ -63,6 +63,10 @@ class MockChatDatabase extends Mock implements DriftChatDatabase { _draftMessageDao ??= MockDraftMessageDao(); DraftMessageDao? _draftMessageDao; + @override + LocationDao get locationDao => _locationDao ??= MockLocationDao(); + LocationDao? _locationDao; + @override Future flush() => Future.value(); @@ -96,3 +100,5 @@ class MockPollDao extends Mock implements PollDao {} class MockPollVoteDao extends Mock implements PollVoteDao {} class MockDraftMessageDao extends Mock implements DraftMessageDao {} + +class MockLocationDao extends Mock implements LocationDao {} diff --git a/packages/stream_chat_persistence/test/src/dao/location_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/location_dao_test.dart new file mode 100644 index 0000000000..62856dae35 --- /dev/null +++ b/packages/stream_chat_persistence/test/src/dao/location_dao_test.dart @@ -0,0 +1,316 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/dao/dao.dart'; +import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; + +import '../../stream_chat_persistence_client_test.dart'; + +void main() { + late LocationDao locationDao; + late DriftChatDatabase database; + + setUp(() { + database = testDatabaseProvider('testUserId'); + locationDao = database.locationDao; + }); + + Future> _prepareLocationData({ + String cid = 'test:Cid', + int count = 3, + }) async { + final channels = [ChannelModel(cid: cid)]; + final users = List.generate(count, (index) => User(id: 'testUserId$index')); + final messages = List.generate( + count, + (index) => Message( + id: 'testMessageId$cid$index', + type: 'testType', + user: users[index], + createdAt: DateTime.now(), + text: 'Test message #$index', + ), + ); + + final locations = List.generate( + count, + (index) => Location( + channelCid: cid, + messageId: messages[index].id, + userId: users[index].id, + latitude: 37.7749 + index * 0.001, // San Francisco area + longitude: -122.4194 + index * 0.001, + createdByDeviceId: 'testDevice$index', + endAt: index % 2 == 0 + ? DateTime.now().add(Duration(hours: 1)) + : null, // Some live, some static + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ), + ); + + await database.userDao.updateUsers(users); + await database.channelDao.updateChannels(channels); + await database.messageDao.updateMessages(cid, messages); + await locationDao.updateLocations(locations); + + return locations; + } + + test('getLocationsByCid', () async { + const cid = 'test:Cid'; + + // Should be empty initially + final locations = await locationDao.getLocationsByCid(cid); + expect(locations, isEmpty); + + // Adding sample locations + final insertedLocations = await _prepareLocationData(cid: cid); + expect(insertedLocations, isNotEmpty); + + // Fetched locations length should match inserted locations length + final fetchedLocations = await locationDao.getLocationsByCid(cid); + expect(fetchedLocations.length, insertedLocations.length); + + // Every location channelCid should match the provided cid + expect(fetchedLocations.every((it) => it.channelCid == cid), true); + }); + + test('updateLocations', () async { + const cid = 'test:Cid'; + + // Preparing test data + final insertedLocations = await _prepareLocationData(cid: cid); + + // Adding a new location + final newUser = User(id: 'newUserId'); + final newMessage = Message( + id: 'newMessageId', + type: 'testType', + user: newUser, + createdAt: DateTime.now(), + text: 'New test message', + ); + final newLocation = Location( + channelCid: cid, + messageId: newMessage.id, + userId: newUser.id, + latitude: 40.7128, // New York + longitude: -74.0060, + createdByDeviceId: 'newDevice', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ); + + await database.userDao.updateUsers([newUser]); + await database.messageDao.updateMessages(cid, [newMessage]); + await locationDao.updateLocations([newLocation]); + + // Fetched locations length should be one more than inserted locations + // Fetched locations should contain the newLocation + final fetchedLocations = await locationDao.getLocationsByCid(cid); + expect(fetchedLocations.length, insertedLocations.length + 1); + expect( + fetchedLocations.any((it) => + it.messageId == newLocation.messageId && + it.latitude == newLocation.latitude && + it.longitude == newLocation.longitude), + isTrue, + ); + }); + + test('getLocationByMessageId', () async { + const cid = 'test:Cid'; + + // Preparing test data + final insertedLocations = await _prepareLocationData(cid: cid); + + // Fetched location should not be null + final locationToFetch = insertedLocations.first; + final fetchedLocation = + await locationDao.getLocationByMessageId(locationToFetch.messageId!); + expect(fetchedLocation, isNotNull); + expect(fetchedLocation!.messageId, locationToFetch.messageId); + expect(fetchedLocation.latitude, locationToFetch.latitude); + expect(fetchedLocation.longitude, locationToFetch.longitude); + }); + + test( + 'getLocationByMessageId should return null for non-existent messageId', + () async { + // Should return null for non-existent messageId + final fetchedLocation = + await locationDao.getLocationByMessageId('nonExistentMessageId'); + expect(fetchedLocation, isNull); + }, + ); + + test('deleteLocationsByCid', () async { + const cid = 'test:Cid'; + + // Preparing test data + final insertedLocations = await _prepareLocationData(cid: cid); + + // Verify locations exist + final locationsBeforeDelete = await locationDao.getLocationsByCid(cid); + expect(locationsBeforeDelete.length, insertedLocations.length); + + // Deleting all locations for the channel + await locationDao.deleteLocationsByCid(cid); + + // Fetched location list should be empty + final fetchedLocations = await locationDao.getLocationsByCid(cid); + expect(fetchedLocations, isEmpty); + }); + + test('deleteLocationsByMessageIds', () async { + const cid = 'test:Cid'; + + // Preparing test data + final insertedLocations = await _prepareLocationData(cid: cid); + + // Deleting the first two locations by their message IDs + final messageIdsToDelete = + insertedLocations.take(2).map((it) => it.messageId!).toList(); + await locationDao.deleteLocationsByMessageIds(messageIdsToDelete); + + // Fetched location list should be one less than inserted locations + final fetchedLocations = await locationDao.getLocationsByCid(cid); + expect(fetchedLocations.length, + insertedLocations.length - messageIdsToDelete.length); + + // Deleted locations should not exist in fetched locations + expect( + fetchedLocations.any((it) => messageIdsToDelete.contains(it.messageId)), + isFalse, + ); + }); + + group('deleteLocationsByMessageIds', () { + test('should delete locations for specific message IDs only', () async { + const cid1 = 'test:Cid1'; + const cid2 = 'test:Cid2'; + + // Preparing test data for two channels + final insertedLocations1 = + await _prepareLocationData(cid: cid1, count: 2); + final insertedLocations2 = + await _prepareLocationData(cid: cid2, count: 2); + + // Verify all locations exist + final locations1 = await locationDao.getLocationsByCid(cid1); + final locations2 = await locationDao.getLocationsByCid(cid2); + expect(locations1.length, insertedLocations1.length); + expect(locations2.length, insertedLocations2.length); + + // Delete only locations from the first channel + final messageIdsToDelete = + insertedLocations1.map((it) => it.messageId!).toList(); + await locationDao.deleteLocationsByMessageIds(messageIdsToDelete); + + // Only locations from cid1 should be deleted + final fetchedLocations1 = await locationDao.getLocationsByCid(cid1); + final fetchedLocations2 = await locationDao.getLocationsByCid(cid2); + expect(fetchedLocations1, isEmpty); + expect(fetchedLocations2.length, insertedLocations2.length); + }); + }); + + group('Location entity references', () { + test( + 'should delete locations when referenced channel is deleted', + () async { + const cid = 'test:channelRefCascade'; + + // Prepare test data + await _prepareLocationData(cid: cid, count: 2); + + // Verify locations exist before channel deletion + final locationsBeforeDelete = await locationDao.getLocationsByCid(cid); + expect(locationsBeforeDelete, isNotEmpty); + expect(locationsBeforeDelete.length, 2); + + // Delete the channel + await database.channelDao.deleteChannelByCids([cid]); + + // Verify locations have been deleted (cascade) + final locationsAfterDelete = await locationDao.getLocationsByCid(cid); + expect(locationsAfterDelete, isEmpty); + }, + ); + + test( + 'should delete locations when referenced message is deleted', + () async { + const cid = 'test:messageRefCascade'; + + // Prepare test data + final insertedLocations = + await _prepareLocationData(cid: cid, count: 3); + final messageToDelete = insertedLocations.first.messageId!; + + // Verify location exists before message deletion + final locationBeforeDelete = + await locationDao.getLocationByMessageId(messageToDelete); + expect(locationBeforeDelete, isNotNull); + expect(locationBeforeDelete!.messageId, messageToDelete); + + // Verify all locations exist + final allLocationsBeforeDelete = + await locationDao.getLocationsByCid(cid); + expect(allLocationsBeforeDelete.length, 3); + + // Delete the message + await database.messageDao.deleteMessageByIds([messageToDelete]); + + // Verify the specific location has been deleted (cascade) + final locationAfterDelete = + await locationDao.getLocationByMessageId(messageToDelete); + expect(locationAfterDelete, isNull); + + // Verify other locations still exist + final allLocationsAfterDelete = + await locationDao.getLocationsByCid(cid); + expect(allLocationsAfterDelete.length, 2); + expect( + allLocationsAfterDelete.any((it) => it.messageId == messageToDelete), + isFalse, + ); + }, + ); + + test( + 'should delete all locations when multiple messages are deleted', + () async { + const cid = 'test:multipleMessageRefCascade'; + + // Prepare test data + final insertedLocations = + await _prepareLocationData(cid: cid, count: 3); + final messageIdsToDelete = + insertedLocations.take(2).map((it) => it.messageId!).toList(); + + // Verify locations exist before message deletion + final allLocationsBeforeDelete = + await locationDao.getLocationsByCid(cid); + expect(allLocationsBeforeDelete.length, 3); + + // Delete multiple messages + await database.messageDao.deleteMessageByIds(messageIdsToDelete); + + // Verify corresponding locations have been deleted (cascade) + final allLocationsAfterDelete = + await locationDao.getLocationsByCid(cid); + expect(allLocationsAfterDelete.length, 1); + expect( + allLocationsAfterDelete + .any((it) => messageIdsToDelete.contains(it.messageId)), + isFalse, + ); + }, + ); + }); + + tearDown(() async { + await database.disconnect(); + }); +} diff --git a/packages/stream_chat_persistence/test/src/mapper/location_mapper_test.dart b/packages/stream_chat_persistence/test/src/mapper/location_mapper_test.dart new file mode 100644 index 0000000000..622a76dcb2 --- /dev/null +++ b/packages/stream_chat_persistence/test/src/mapper/location_mapper_test.dart @@ -0,0 +1,141 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; +import 'package:stream_chat_persistence/src/mapper/location_mapper.dart'; + +void main() { + group('LocationMapper', () { + test('toLocation should map the entity into Location', () { + final createdAt = DateTime.now(); + final updatedAt = DateTime.now(); + final endAt = DateTime.now().add(const Duration(hours: 1)); + + final entity = LocationEntity( + channelCid: 'testCid', + userId: 'testUserId', + messageId: 'testMessageId', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'testDeviceId', + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, + ); + + final location = entity.toLocation(); + + expect(location, isA()); + expect(location.channelCid, entity.channelCid); + expect(location.userId, entity.userId); + expect(location.messageId, entity.messageId); + expect(location.latitude, entity.latitude); + expect(location.longitude, entity.longitude); + expect(location.createdByDeviceId, entity.createdByDeviceId); + expect(location.endAt, entity.endAt); + expect(location.createdAt, entity.createdAt); + expect(location.updatedAt, entity.updatedAt); + }); + + test('toEntity should map the Location into LocationEntity', () { + final createdAt = DateTime.now(); + final updatedAt = DateTime.now(); + final endAt = DateTime.now().add(const Duration(hours: 1)); + + final location = Location( + channelCid: 'testCid', + userId: 'testUserId', + messageId: 'testMessageId', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'testDeviceId', + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, + ); + + final entity = location.toEntity(); + + expect(entity, isA()); + expect(entity.channelCid, location.channelCid); + expect(entity.userId, location.userId); + expect(entity.messageId, location.messageId); + expect(entity.latitude, location.latitude); + expect(entity.longitude, location.longitude); + expect(entity.createdByDeviceId, location.createdByDeviceId); + expect(entity.endAt, location.endAt); + expect(entity.createdAt, location.createdAt); + expect(entity.updatedAt, location.updatedAt); + }); + + test('roundtrip conversion should preserve data', () { + final createdAt = DateTime.now(); + final updatedAt = DateTime.now(); + final endAt = DateTime.now().add(const Duration(hours: 1)); + + final originalLocation = Location( + channelCid: 'testCid', + userId: 'testUserId', + messageId: 'testMessageId', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'testDeviceId', + endAt: endAt, + createdAt: createdAt, + updatedAt: updatedAt, + ); + + final entity = originalLocation.toEntity(); + final convertedLocation = entity.toLocation(); + + expect(convertedLocation.channelCid, originalLocation.channelCid); + expect(convertedLocation.userId, originalLocation.userId); + expect(convertedLocation.messageId, originalLocation.messageId); + expect(convertedLocation.latitude, originalLocation.latitude); + expect(convertedLocation.longitude, originalLocation.longitude); + expect(convertedLocation.createdByDeviceId, + originalLocation.createdByDeviceId); + expect(convertedLocation.endAt, originalLocation.endAt); + expect(convertedLocation.createdAt, originalLocation.createdAt); + expect(convertedLocation.updatedAt, originalLocation.updatedAt); + }); + + test('should handle live location conversion', () { + final endAt = DateTime.now().add(const Duration(hours: 1)); + final location = Location( + channelCid: 'testCid', + userId: 'testUserId', + messageId: 'testMessageId', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'testDeviceId', + endAt: endAt, + ); + + final entity = location.toEntity(); + final convertedLocation = entity.toLocation(); + + expect(convertedLocation.isLive, isTrue); + expect(convertedLocation.isStatic, isFalse); + expect(convertedLocation.endAt, endAt); + }); + + test('should handle static location conversion', () { + final location = Location( + channelCid: 'testCid', + userId: 'testUserId', + messageId: 'testMessageId', + latitude: 40.7128, + longitude: -74.0060, + createdByDeviceId: 'testDeviceId', + // No endAt = static location + ); + + final entity = location.toEntity(); + final convertedLocation = entity.toLocation(); + + expect(convertedLocation.isLive, isFalse); + expect(convertedLocation.isStatic, isTrue); + expect(convertedLocation.endAt, isNull); + }); + }); +} diff --git a/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart b/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart index 0a8cfc6783..7f1f17c758 100644 --- a/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart +++ b/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart @@ -689,6 +689,96 @@ void main() { .deleteDraftMessageByCid(cid, parentId: parentId)).called(1); }); + test('getLocationsByCid', () async { + const cid = 'testCid'; + final locations = List.generate( + 3, + (index) => Location( + channelCid: cid, + messageId: 'testMessageId$index', + userId: 'testUserId$index', + latitude: 37.7749 + index * 0.001, + longitude: -122.4194 + index * 0.001, + createdByDeviceId: 'testDevice$index', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ), + ); + + when(() => mockDatabase.locationDao.getLocationsByCid(cid)) + .thenAnswer((_) async => locations); + + final fetchedLocations = await client.getLocationsByCid(cid); + expect(fetchedLocations.length, locations.length); + verify(() => mockDatabase.locationDao.getLocationsByCid(cid)).called(1); + }); + + test('getLocationByMessageId', () async { + const messageId = 'testMessageId'; + final location = Location( + channelCid: 'testCid', + messageId: messageId, + userId: 'testUserId', + latitude: 37.7749, + longitude: -122.4194, + createdByDeviceId: 'testDevice', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ); + + when(() => mockDatabase.locationDao.getLocationByMessageId(messageId)) + .thenAnswer((_) async => location); + + final fetchedLocation = await client.getLocationByMessageId(messageId); + expect(fetchedLocation, isNotNull); + expect(fetchedLocation!.messageId, messageId); + verify(() => mockDatabase.locationDao.getLocationByMessageId(messageId)) + .called(1); + }); + + test('updateLocations', () async { + final locations = List.generate( + 3, + (index) => Location( + channelCid: 'testCid$index', + messageId: 'testMessageId$index', + userId: 'testUserId$index', + latitude: 37.7749 + index * 0.001, + longitude: -122.4194 + index * 0.001, + createdByDeviceId: 'testDevice$index', + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ), + ); + + when(() => mockDatabase.locationDao.updateLocations(locations)) + .thenAnswer((_) async {}); + + await client.updateLocations(locations); + verify(() => mockDatabase.locationDao.updateLocations(locations)) + .called(1); + }); + + test('deleteLocationsByCid', () async { + const cid = 'testCid'; + when(() => mockDatabase.locationDao.deleteLocationsByCid(cid)) + .thenAnswer((_) async {}); + + await client.deleteLocationsByCid(cid); + verify(() => mockDatabase.locationDao.deleteLocationsByCid(cid)) + .called(1); + }); + + test('deleteLocationsByMessageIds', () async { + final messageIds = ['testMessageId1', 'testMessageId2']; + when(() => mockDatabase.locationDao.deleteLocationsByMessageIds(messageIds)) + .thenAnswer((_) async {}); + + await client.deleteLocationsByMessageIds(messageIds); + verify(() => mockDatabase.locationDao.deleteLocationsByMessageIds(messageIds)) + .called(1); + }); + tearDown(() async { await client.disconnect(flush: true); }); From e1a6469cda5432a6309173ed2e2cb8ef6d559376 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Mon, 21 Jul 2025 16:36:13 +0200 Subject: [PATCH 21/26] refactor: remove draftMessageId from message entities This commit removes the `draftMessageId` field from `MessageEntity` and `PinnedMessageEntity` in the persistence layer. This field was unused and caused unnecessary database schema complexity. The `draftMessageId` field was previously intended to store the ID of a draft message if the current message was a parent message. However, this functionality was never implemented or used, making the field redundant. Removing this field simplifies the database schema and reduces the amount of data stored, potentially improving performance and maintainability. --- .../lib/src/db/drift_chat_database.g.dart | 122 ------------------ .../lib/src/entity/messages.dart | 3 - .../lib/src/mapper/message_mapper.dart | 1 - .../lib/src/mapper/pinned_message_mapper.dart | 1 - 4 files changed, 127 deletions(-) diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart index 9dff3dc78a..8d06917c05 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart @@ -846,12 +846,6 @@ class $MessagesTable extends Messages type: DriftSqlType.string, requiredDuringInsert: false) .withConverter?>( $MessagesTable.$converterrestrictedVisibilityn); - static const VerificationMeta _draftMessageIdMeta = - const VerificationMeta('draftMessageId'); - @override - late final GeneratedColumn draftMessageId = GeneratedColumn( - 'draft_message_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); @override late final GeneratedColumnWithTypeConverter?, String> extraData = GeneratedColumn('extra_data', aliasedName, true, @@ -889,7 +883,6 @@ class $MessagesTable extends Messages channelCid, i18n, restrictedVisibility, - draftMessageId, extraData ]; @override @@ -1031,12 +1024,6 @@ class $MessagesTable extends Messages } else if (isInserting) { context.missing(_channelCidMeta); } - if (data.containsKey('draft_message_id')) { - context.handle( - _draftMessageIdMeta, - draftMessageId.isAcceptableOrUnknown( - data['draft_message_id']!, _draftMessageIdMeta)); - } return context; } @@ -1109,8 +1096,6 @@ class $MessagesTable extends Messages restrictedVisibility: $MessagesTable.$converterrestrictedVisibilityn .fromSql(attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}restricted_visibility'])), - draftMessageId: attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}draft_message_id']), extraData: $MessagesTable.$converterextraDatan.fromSql(attachedDatabase .typeMapping .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), @@ -1232,9 +1217,6 @@ class MessageEntity extends DataClass implements Insertable { /// The list of user ids that should be able to see the message. final List? restrictedVisibility; - /// Id of the draft message if this message is a parent message. - final String? draftMessageId; - /// Message custom extraData final Map? extraData; const MessageEntity( @@ -1267,7 +1249,6 @@ class MessageEntity extends DataClass implements Insertable { required this.channelCid, this.i18n, this.restrictedVisibility, - this.draftMessageId, this.extraData}); @override Map toColumns(bool nullToAbsent) { @@ -1352,9 +1333,6 @@ class MessageEntity extends DataClass implements Insertable { .$converterrestrictedVisibilityn .toSql(restrictedVisibility)); } - if (!nullToAbsent || draftMessageId != null) { - map['draft_message_id'] = Variable(draftMessageId); - } if (!nullToAbsent || extraData != null) { map['extra_data'] = Variable( $MessagesTable.$converterextraDatan.toSql(extraData)); @@ -1398,7 +1376,6 @@ class MessageEntity extends DataClass implements Insertable { i18n: serializer.fromJson?>(json['i18n']), restrictedVisibility: serializer.fromJson?>(json['restrictedVisibility']), - draftMessageId: serializer.fromJson(json['draftMessageId']), extraData: serializer.fromJson?>(json['extraData']), ); } @@ -1438,7 +1415,6 @@ class MessageEntity extends DataClass implements Insertable { 'i18n': serializer.toJson?>(i18n), 'restrictedVisibility': serializer.toJson?>(restrictedVisibility), - 'draftMessageId': serializer.toJson(draftMessageId), 'extraData': serializer.toJson?>(extraData), }; } @@ -1474,7 +1450,6 @@ class MessageEntity extends DataClass implements Insertable { String? channelCid, Value?> i18n = const Value.absent(), Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent()}) => MessageEntity( id: id ?? this.id, @@ -1524,8 +1499,6 @@ class MessageEntity extends DataClass implements Insertable { restrictedVisibility: restrictedVisibility.present ? restrictedVisibility.value : this.restrictedVisibility, - draftMessageId: - draftMessageId.present ? draftMessageId.value : this.draftMessageId, extraData: extraData.present ? extraData.value : this.extraData, ); MessageEntity copyWithCompanion(MessagesCompanion data) { @@ -1590,9 +1563,6 @@ class MessageEntity extends DataClass implements Insertable { restrictedVisibility: data.restrictedVisibility.present ? data.restrictedVisibility.value : this.restrictedVisibility, - draftMessageId: data.draftMessageId.present - ? data.draftMessageId.value - : this.draftMessageId, extraData: data.extraData.present ? data.extraData.value : this.extraData, ); } @@ -1629,7 +1599,6 @@ class MessageEntity extends DataClass implements Insertable { ..write('channelCid: $channelCid, ') ..write('i18n: $i18n, ') ..write('restrictedVisibility: $restrictedVisibility, ') - ..write('draftMessageId: $draftMessageId, ') ..write('extraData: $extraData') ..write(')')) .toString(); @@ -1666,7 +1635,6 @@ class MessageEntity extends DataClass implements Insertable { channelCid, i18n, restrictedVisibility, - draftMessageId, extraData ]); @override @@ -1702,7 +1670,6 @@ class MessageEntity extends DataClass implements Insertable { other.channelCid == this.channelCid && other.i18n == this.i18n && other.restrictedVisibility == this.restrictedVisibility && - other.draftMessageId == this.draftMessageId && other.extraData == this.extraData); } @@ -1736,7 +1703,6 @@ class MessagesCompanion extends UpdateCompanion { final Value channelCid; final Value?> i18n; final Value?> restrictedVisibility; - final Value draftMessageId; final Value?> extraData; final Value rowid; const MessagesCompanion({ @@ -1769,7 +1735,6 @@ class MessagesCompanion extends UpdateCompanion { this.channelCid = const Value.absent(), this.i18n = const Value.absent(), this.restrictedVisibility = const Value.absent(), - this.draftMessageId = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); @@ -1803,7 +1768,6 @@ class MessagesCompanion extends UpdateCompanion { required String channelCid, this.i18n = const Value.absent(), this.restrictedVisibility = const Value.absent(), - this.draftMessageId = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }) : id = Value(id), @@ -1841,7 +1805,6 @@ class MessagesCompanion extends UpdateCompanion { Expression? channelCid, Expression? i18n, Expression? restrictedVisibility, - Expression? draftMessageId, Expression? extraData, Expression? rowid, }) { @@ -1877,7 +1840,6 @@ class MessagesCompanion extends UpdateCompanion { if (i18n != null) 'i18n': i18n, if (restrictedVisibility != null) 'restricted_visibility': restrictedVisibility, - if (draftMessageId != null) 'draft_message_id': draftMessageId, if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, }); @@ -1913,7 +1875,6 @@ class MessagesCompanion extends UpdateCompanion { Value? channelCid, Value?>? i18n, Value?>? restrictedVisibility, - Value? draftMessageId, Value?>? extraData, Value? rowid}) { return MessagesCompanion( @@ -1946,7 +1907,6 @@ class MessagesCompanion extends UpdateCompanion { channelCid: channelCid ?? this.channelCid, i18n: i18n ?? this.i18n, restrictedVisibility: restrictedVisibility ?? this.restrictedVisibility, - draftMessageId: draftMessageId ?? this.draftMessageId, extraData: extraData ?? this.extraData, rowid: rowid ?? this.rowid, ); @@ -2049,9 +2009,6 @@ class MessagesCompanion extends UpdateCompanion { .$converterrestrictedVisibilityn .toSql(restrictedVisibility.value)); } - if (draftMessageId.present) { - map['draft_message_id'] = Variable(draftMessageId.value); - } if (extraData.present) { map['extra_data'] = Variable( $MessagesTable.$converterextraDatan.toSql(extraData.value)); @@ -2094,7 +2051,6 @@ class MessagesCompanion extends UpdateCompanion { ..write('channelCid: $channelCid, ') ..write('i18n: $i18n, ') ..write('restrictedVisibility: $restrictedVisibility, ') - ..write('draftMessageId: $draftMessageId, ') ..write('extraData: $extraData, ') ..write('rowid: $rowid') ..write(')')) @@ -3476,12 +3432,6 @@ class $PinnedMessagesTable extends PinnedMessages type: DriftSqlType.string, requiredDuringInsert: false) .withConverter?>( $PinnedMessagesTable.$converterrestrictedVisibilityn); - static const VerificationMeta _draftMessageIdMeta = - const VerificationMeta('draftMessageId'); - @override - late final GeneratedColumn draftMessageId = GeneratedColumn( - 'draft_message_id', aliasedName, true, - type: DriftSqlType.string, requiredDuringInsert: false); @override late final GeneratedColumnWithTypeConverter?, String> extraData = GeneratedColumn('extra_data', aliasedName, true, @@ -3519,7 +3469,6 @@ class $PinnedMessagesTable extends PinnedMessages channelCid, i18n, restrictedVisibility, - draftMessageId, extraData ]; @override @@ -3662,12 +3611,6 @@ class $PinnedMessagesTable extends PinnedMessages } else if (isInserting) { context.missing(_channelCidMeta); } - if (data.containsKey('draft_message_id')) { - context.handle( - _draftMessageIdMeta, - draftMessageId.isAcceptableOrUnknown( - data['draft_message_id']!, _draftMessageIdMeta)); - } return context; } @@ -3741,8 +3684,6 @@ class $PinnedMessagesTable extends PinnedMessages restrictedVisibility: $PinnedMessagesTable.$converterrestrictedVisibilityn .fromSql(attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}restricted_visibility'])), - draftMessageId: attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}draft_message_id']), extraData: $PinnedMessagesTable.$converterextraDatan.fromSql( attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}extra_data'])), @@ -3865,9 +3806,6 @@ class PinnedMessageEntity extends DataClass /// The list of user ids that should be able to see the message. final List? restrictedVisibility; - /// Id of the draft message if this message is a parent message. - final String? draftMessageId; - /// Message custom extraData final Map? extraData; const PinnedMessageEntity( @@ -3900,7 +3838,6 @@ class PinnedMessageEntity extends DataClass required this.channelCid, this.i18n, this.restrictedVisibility, - this.draftMessageId, this.extraData}); @override Map toColumns(bool nullToAbsent) { @@ -3986,9 +3923,6 @@ class PinnedMessageEntity extends DataClass .$converterrestrictedVisibilityn .toSql(restrictedVisibility)); } - if (!nullToAbsent || draftMessageId != null) { - map['draft_message_id'] = Variable(draftMessageId); - } if (!nullToAbsent || extraData != null) { map['extra_data'] = Variable( $PinnedMessagesTable.$converterextraDatan.toSql(extraData)); @@ -4032,7 +3966,6 @@ class PinnedMessageEntity extends DataClass i18n: serializer.fromJson?>(json['i18n']), restrictedVisibility: serializer.fromJson?>(json['restrictedVisibility']), - draftMessageId: serializer.fromJson(json['draftMessageId']), extraData: serializer.fromJson?>(json['extraData']), ); } @@ -4072,7 +4005,6 @@ class PinnedMessageEntity extends DataClass 'i18n': serializer.toJson?>(i18n), 'restrictedVisibility': serializer.toJson?>(restrictedVisibility), - 'draftMessageId': serializer.toJson(draftMessageId), 'extraData': serializer.toJson?>(extraData), }; } @@ -4108,7 +4040,6 @@ class PinnedMessageEntity extends DataClass String? channelCid, Value?> i18n = const Value.absent(), Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent()}) => PinnedMessageEntity( id: id ?? this.id, @@ -4158,8 +4089,6 @@ class PinnedMessageEntity extends DataClass restrictedVisibility: restrictedVisibility.present ? restrictedVisibility.value : this.restrictedVisibility, - draftMessageId: - draftMessageId.present ? draftMessageId.value : this.draftMessageId, extraData: extraData.present ? extraData.value : this.extraData, ); PinnedMessageEntity copyWithCompanion(PinnedMessagesCompanion data) { @@ -4224,9 +4153,6 @@ class PinnedMessageEntity extends DataClass restrictedVisibility: data.restrictedVisibility.present ? data.restrictedVisibility.value : this.restrictedVisibility, - draftMessageId: data.draftMessageId.present - ? data.draftMessageId.value - : this.draftMessageId, extraData: data.extraData.present ? data.extraData.value : this.extraData, ); } @@ -4263,7 +4189,6 @@ class PinnedMessageEntity extends DataClass ..write('channelCid: $channelCid, ') ..write('i18n: $i18n, ') ..write('restrictedVisibility: $restrictedVisibility, ') - ..write('draftMessageId: $draftMessageId, ') ..write('extraData: $extraData') ..write(')')) .toString(); @@ -4300,7 +4225,6 @@ class PinnedMessageEntity extends DataClass channelCid, i18n, restrictedVisibility, - draftMessageId, extraData ]); @override @@ -4336,7 +4260,6 @@ class PinnedMessageEntity extends DataClass other.channelCid == this.channelCid && other.i18n == this.i18n && other.restrictedVisibility == this.restrictedVisibility && - other.draftMessageId == this.draftMessageId && other.extraData == this.extraData); } @@ -4370,7 +4293,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { final Value channelCid; final Value?> i18n; final Value?> restrictedVisibility; - final Value draftMessageId; final Value?> extraData; final Value rowid; const PinnedMessagesCompanion({ @@ -4403,7 +4325,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { this.channelCid = const Value.absent(), this.i18n = const Value.absent(), this.restrictedVisibility = const Value.absent(), - this.draftMessageId = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); @@ -4437,7 +4358,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { required String channelCid, this.i18n = const Value.absent(), this.restrictedVisibility = const Value.absent(), - this.draftMessageId = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }) : id = Value(id), @@ -4475,7 +4395,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { Expression? channelCid, Expression? i18n, Expression? restrictedVisibility, - Expression? draftMessageId, Expression? extraData, Expression? rowid, }) { @@ -4511,7 +4430,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { if (i18n != null) 'i18n': i18n, if (restrictedVisibility != null) 'restricted_visibility': restrictedVisibility, - if (draftMessageId != null) 'draft_message_id': draftMessageId, if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, }); @@ -4547,7 +4465,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { Value? channelCid, Value?>? i18n, Value?>? restrictedVisibility, - Value? draftMessageId, Value?>? extraData, Value? rowid}) { return PinnedMessagesCompanion( @@ -4580,7 +4497,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { channelCid: channelCid ?? this.channelCid, i18n: i18n ?? this.i18n, restrictedVisibility: restrictedVisibility ?? this.restrictedVisibility, - draftMessageId: draftMessageId ?? this.draftMessageId, extraData: extraData ?? this.extraData, rowid: rowid ?? this.rowid, ); @@ -4685,9 +4601,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { .$converterrestrictedVisibilityn .toSql(restrictedVisibility.value)); } - if (draftMessageId.present) { - map['draft_message_id'] = Variable(draftMessageId.value); - } if (extraData.present) { map['extra_data'] = Variable( $PinnedMessagesTable.$converterextraDatan.toSql(extraData.value)); @@ -4730,7 +4643,6 @@ class PinnedMessagesCompanion extends UpdateCompanion { ..write('channelCid: $channelCid, ') ..write('i18n: $i18n, ') ..write('restrictedVisibility: $restrictedVisibility, ') - ..write('draftMessageId: $draftMessageId, ') ..write('extraData: $extraData, ') ..write('rowid: $rowid') ..write(')')) @@ -9676,7 +9588,6 @@ typedef $$MessagesTableCreateCompanionBuilder = MessagesCompanion Function({ required String channelCid, Value?> i18n, Value?> restrictedVisibility, - Value draftMessageId, Value?> extraData, Value rowid, }); @@ -9710,7 +9621,6 @@ typedef $$MessagesTableUpdateCompanionBuilder = MessagesCompanion Function({ Value channelCid, Value?> i18n, Value?> restrictedVisibility, - Value draftMessageId, Value?> extraData, Value rowid, }); @@ -9894,10 +9804,6 @@ class $$MessagesTableFilterComposer column: $table.restrictedVisibility, builder: (column) => ColumnWithTypeConverterFilters(column)); - ColumnFilters get draftMessageId => $composableBuilder( - column: $table.draftMessageId, - builder: (column) => ColumnFilters(column)); - ColumnWithTypeConverterFilters?, Map, String> get extraData => $composableBuilder( @@ -10094,10 +10000,6 @@ class $$MessagesTableOrderingComposer column: $table.restrictedVisibility, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get draftMessageId => $composableBuilder( - column: $table.draftMessageId, - builder: (column) => ColumnOrderings(column)); - ColumnOrderings get extraData => $composableBuilder( column: $table.extraData, builder: (column) => ColumnOrderings(column)); @@ -10219,9 +10121,6 @@ class $$MessagesTableAnnotationComposer get restrictedVisibility => $composableBuilder( column: $table.restrictedVisibility, builder: (column) => column); - GeneratedColumn get draftMessageId => $composableBuilder( - column: $table.draftMessageId, builder: (column) => column); - GeneratedColumnWithTypeConverter?, String> get extraData => $composableBuilder( column: $table.extraData, builder: (column) => column); @@ -10367,7 +10266,6 @@ class $$MessagesTableTableManager extends RootTableManager< Value channelCid = const Value.absent(), Value?> i18n = const Value.absent(), Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => @@ -10401,7 +10299,6 @@ class $$MessagesTableTableManager extends RootTableManager< channelCid: channelCid, i18n: i18n, restrictedVisibility: restrictedVisibility, - draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), @@ -10436,7 +10333,6 @@ class $$MessagesTableTableManager extends RootTableManager< required String channelCid, Value?> i18n = const Value.absent(), Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => @@ -10470,7 +10366,6 @@ class $$MessagesTableTableManager extends RootTableManager< channelCid: channelCid, i18n: i18n, restrictedVisibility: restrictedVisibility, - draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), @@ -11524,7 +11419,6 @@ typedef $$PinnedMessagesTableCreateCompanionBuilder = PinnedMessagesCompanion required String channelCid, Value?> i18n, Value?> restrictedVisibility, - Value draftMessageId, Value?> extraData, Value rowid, }); @@ -11559,7 +11453,6 @@ typedef $$PinnedMessagesTableUpdateCompanionBuilder = PinnedMessagesCompanion Value channelCid, Value?> i18n, Value?> restrictedVisibility, - Value draftMessageId, Value?> extraData, Value rowid, }); @@ -11706,10 +11599,6 @@ class $$PinnedMessagesTableFilterComposer column: $table.restrictedVisibility, builder: (column) => ColumnWithTypeConverterFilters(column)); - ColumnFilters get draftMessageId => $composableBuilder( - column: $table.draftMessageId, - builder: (column) => ColumnFilters(column)); - ColumnWithTypeConverterFilters?, Map, String> get extraData => $composableBuilder( @@ -11849,10 +11738,6 @@ class $$PinnedMessagesTableOrderingComposer column: $table.restrictedVisibility, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get draftMessageId => $composableBuilder( - column: $table.draftMessageId, - builder: (column) => ColumnOrderings(column)); - ColumnOrderings get extraData => $composableBuilder( column: $table.extraData, builder: (column) => ColumnOrderings(column)); } @@ -11957,9 +11842,6 @@ class $$PinnedMessagesTableAnnotationComposer get restrictedVisibility => $composableBuilder( column: $table.restrictedVisibility, builder: (column) => column); - GeneratedColumn get draftMessageId => $composableBuilder( - column: $table.draftMessageId, builder: (column) => column); - GeneratedColumnWithTypeConverter?, String> get extraData => $composableBuilder( column: $table.extraData, builder: (column) => column); @@ -12042,7 +11924,6 @@ class $$PinnedMessagesTableTableManager extends RootTableManager< Value channelCid = const Value.absent(), Value?> i18n = const Value.absent(), Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => @@ -12076,7 +11957,6 @@ class $$PinnedMessagesTableTableManager extends RootTableManager< channelCid: channelCid, i18n: i18n, restrictedVisibility: restrictedVisibility, - draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), @@ -12111,7 +11991,6 @@ class $$PinnedMessagesTableTableManager extends RootTableManager< required String channelCid, Value?> i18n = const Value.absent(), Value?> restrictedVisibility = const Value.absent(), - Value draftMessageId = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), }) => @@ -12145,7 +12024,6 @@ class $$PinnedMessagesTableTableManager extends RootTableManager< channelCid: channelCid, i18n: i18n, restrictedVisibility: restrictedVisibility, - draftMessageId: draftMessageId, extraData: extraData, rowid: rowid, ), diff --git a/packages/stream_chat_persistence/lib/src/entity/messages.dart b/packages/stream_chat_persistence/lib/src/entity/messages.dart index 766bbe5995..caf11a1a11 100644 --- a/packages/stream_chat_persistence/lib/src/entity/messages.dart +++ b/packages/stream_chat_persistence/lib/src/entity/messages.dart @@ -129,9 +129,6 @@ class Messages extends Table { TextColumn get restrictedVisibility => text().nullable().map(ListConverter())(); - /// Id of the draft message if this message is a parent message. - TextColumn get draftMessageId => text().nullable()(); - /// Message custom extraData TextColumn get extraData => text().nullable().map(MapConverter())(); 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 a2770e2a93..4640c0f325 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/message_mapper.dart @@ -93,6 +93,5 @@ extension MessageX on Message { pinnedByUserId: pinnedBy?.id, i18n: i18n, restrictedVisibility: restrictedVisibility, - draftMessageId: draft?.message.id, ); } diff --git a/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart index 9a0544427c..fbd168c717 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/pinned_message_mapper.dart @@ -94,6 +94,5 @@ extension PMessageX on Message { pinnedByUserId: pinnedBy?.id, i18n: i18n, restrictedVisibility: restrictedVisibility, - draftMessageId: draft?.message.id, ); } From ebb5b437712624412ef530a4d8b864c838acedf5 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 23 Jul 2025 16:06:09 +0200 Subject: [PATCH 22/26] refactor: make `createdByDeviceId` nullable The `createdByDeviceId` field in the `Locations` table has been made nullable to accommodate cases where this information might not be available. This change is reflected in the generated Drift code. --- .../lib/src/db/drift_chat_database.g.dart | 44 ++++++++++--------- .../lib/src/entity/locations.dart | 2 +- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart index 8d06917c05..6d380c1c7a 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart @@ -2809,8 +2809,8 @@ class $LocationsTable extends Locations const VerificationMeta('createdByDeviceId'); @override late final GeneratedColumn createdByDeviceId = - GeneratedColumn('created_by_device_id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + GeneratedColumn('created_by_device_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _endAtMeta = const VerificationMeta('endAt'); @override late final GeneratedColumn endAt = GeneratedColumn( @@ -2885,8 +2885,6 @@ class $LocationsTable extends Locations _createdByDeviceIdMeta, createdByDeviceId.isAcceptableOrUnknown( data['created_by_device_id']!, _createdByDeviceIdMeta)); - } else if (isInserting) { - context.missing(_createdByDeviceIdMeta); } if (data.containsKey('end_at')) { context.handle( @@ -2920,7 +2918,7 @@ class $LocationsTable extends Locations longitude: attachedDatabase.typeMapping .read(DriftSqlType.double, data['${effectivePrefix}longitude'])!, createdByDeviceId: attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}created_by_device_id'])!, + DriftSqlType.string, data['${effectivePrefix}created_by_device_id']), endAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}end_at']), createdAt: attachedDatabase.typeMapping @@ -2953,7 +2951,7 @@ class LocationEntity extends DataClass implements Insertable { final double longitude; /// The ID of the device that created the location - final String createdByDeviceId; + final String? createdByDeviceId; /// The date at which the shared location will end (for live locations) /// If null, this is a static location @@ -2970,7 +2968,7 @@ class LocationEntity extends DataClass implements Insertable { this.userId, required this.latitude, required this.longitude, - required this.createdByDeviceId, + this.createdByDeviceId, this.endAt, required this.createdAt, required this.updatedAt}); @@ -2988,7 +2986,9 @@ class LocationEntity extends DataClass implements Insertable { } map['latitude'] = Variable(latitude); map['longitude'] = Variable(longitude); - map['created_by_device_id'] = Variable(createdByDeviceId); + if (!nullToAbsent || createdByDeviceId != null) { + map['created_by_device_id'] = Variable(createdByDeviceId); + } if (!nullToAbsent || endAt != null) { map['end_at'] = Variable(endAt); } @@ -3006,7 +3006,8 @@ class LocationEntity extends DataClass implements Insertable { userId: serializer.fromJson(json['userId']), latitude: serializer.fromJson(json['latitude']), longitude: serializer.fromJson(json['longitude']), - createdByDeviceId: serializer.fromJson(json['createdByDeviceId']), + createdByDeviceId: + serializer.fromJson(json['createdByDeviceId']), endAt: serializer.fromJson(json['endAt']), createdAt: serializer.fromJson(json['createdAt']), updatedAt: serializer.fromJson(json['updatedAt']), @@ -3021,7 +3022,7 @@ class LocationEntity extends DataClass implements Insertable { 'userId': serializer.toJson(userId), 'latitude': serializer.toJson(latitude), 'longitude': serializer.toJson(longitude), - 'createdByDeviceId': serializer.toJson(createdByDeviceId), + 'createdByDeviceId': serializer.toJson(createdByDeviceId), 'endAt': serializer.toJson(endAt), 'createdAt': serializer.toJson(createdAt), 'updatedAt': serializer.toJson(updatedAt), @@ -3034,7 +3035,7 @@ class LocationEntity extends DataClass implements Insertable { Value userId = const Value.absent(), double? latitude, double? longitude, - String? createdByDeviceId, + Value createdByDeviceId = const Value.absent(), Value endAt = const Value.absent(), DateTime? createdAt, DateTime? updatedAt}) => @@ -3044,7 +3045,9 @@ class LocationEntity extends DataClass implements Insertable { userId: userId.present ? userId.value : this.userId, latitude: latitude ?? this.latitude, longitude: longitude ?? this.longitude, - createdByDeviceId: createdByDeviceId ?? this.createdByDeviceId, + createdByDeviceId: createdByDeviceId.present + ? createdByDeviceId.value + : this.createdByDeviceId, endAt: endAt.present ? endAt.value : this.endAt, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, @@ -3106,7 +3109,7 @@ class LocationsCompanion extends UpdateCompanion { final Value userId; final Value latitude; final Value longitude; - final Value createdByDeviceId; + final Value createdByDeviceId; final Value endAt; final Value createdAt; final Value updatedAt; @@ -3129,14 +3132,13 @@ class LocationsCompanion extends UpdateCompanion { this.userId = const Value.absent(), required double latitude, required double longitude, - required String createdByDeviceId, + this.createdByDeviceId = const Value.absent(), this.endAt = const Value.absent(), this.createdAt = const Value.absent(), this.updatedAt = const Value.absent(), this.rowid = const Value.absent(), }) : latitude = Value(latitude), - longitude = Value(longitude), - createdByDeviceId = Value(createdByDeviceId); + longitude = Value(longitude); static Insertable custom({ Expression? channelCid, Expression? messageId, @@ -3169,7 +3171,7 @@ class LocationsCompanion extends UpdateCompanion { Value? userId, Value? latitude, Value? longitude, - Value? createdByDeviceId, + Value? createdByDeviceId, Value? endAt, Value? createdAt, Value? updatedAt, @@ -10983,7 +10985,7 @@ typedef $$LocationsTableCreateCompanionBuilder = LocationsCompanion Function({ Value userId, required double latitude, required double longitude, - required String createdByDeviceId, + Value createdByDeviceId, Value endAt, Value createdAt, Value updatedAt, @@ -10995,7 +10997,7 @@ typedef $$LocationsTableUpdateCompanionBuilder = LocationsCompanion Function({ Value userId, Value latitude, Value longitude, - Value createdByDeviceId, + Value createdByDeviceId, Value endAt, Value createdAt, Value updatedAt, @@ -11280,7 +11282,7 @@ class $$LocationsTableTableManager extends RootTableManager< Value userId = const Value.absent(), Value latitude = const Value.absent(), Value longitude = const Value.absent(), - Value createdByDeviceId = const Value.absent(), + Value createdByDeviceId = const Value.absent(), Value endAt = const Value.absent(), Value createdAt = const Value.absent(), Value updatedAt = const Value.absent(), @@ -11304,7 +11306,7 @@ class $$LocationsTableTableManager extends RootTableManager< Value userId = const Value.absent(), required double latitude, required double longitude, - required String createdByDeviceId, + Value createdByDeviceId = const Value.absent(), Value endAt = const Value.absent(), Value createdAt = const Value.absent(), Value updatedAt = const Value.absent(), diff --git a/packages/stream_chat_persistence/lib/src/entity/locations.dart b/packages/stream_chat_persistence/lib/src/entity/locations.dart index 04417c3d61..b12f448b8b 100644 --- a/packages/stream_chat_persistence/lib/src/entity/locations.dart +++ b/packages/stream_chat_persistence/lib/src/entity/locations.dart @@ -26,7 +26,7 @@ class Locations extends Table { RealColumn get longitude => real()(); /// The ID of the device that created the location - TextColumn get createdByDeviceId => text()(); + TextColumn get createdByDeviceId => text().nullable()(); /// The date at which the shared location will end (for live locations) /// If null, this is a static location From 69f4a3eeebacf583676a4f0a5c71a64edb5c051e Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 23 Jul 2025 16:07:00 +0200 Subject: [PATCH 23/26] chore: bump schema version to 23 --- .../stream_chat_persistence/lib/src/db/drift_chat_database.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart index e01545bf4b..8b740c80c6 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart @@ -57,7 +57,7 @@ class DriftChatDatabase extends _$DriftChatDatabase { // you should bump this number whenever you change or add a table definition. @override - int get schemaVersion => 22; + int get schemaVersion => 23; @override MigrationStrategy get migration => MigrationStrategy( From 3ce0681bbbb330ab30a101f804f76f01f87cfd28 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 23 Jul 2025 16:28:53 +0200 Subject: [PATCH 24/26] chore: fix lint --- .../test/src/dao/location_dao_test.dart | 8 +++++--- .../test/stream_chat_persistence_client_test.dart | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/stream_chat_persistence/test/src/dao/location_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/location_dao_test.dart index 62856dae35..2311ac8d2d 100644 --- a/packages/stream_chat_persistence/test/src/dao/location_dao_test.dart +++ b/packages/stream_chat_persistence/test/src/dao/location_dao_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_redundant_argument_values + import 'package:flutter_test/flutter_test.dart'; import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_persistence/src/dao/dao.dart'; @@ -15,7 +17,7 @@ void main() { }); Future> _prepareLocationData({ - String cid = 'test:Cid', + required String cid, int count = 3, }) async { final channels = [ChannelModel(cid: cid)]; @@ -40,8 +42,8 @@ void main() { latitude: 37.7749 + index * 0.001, // San Francisco area longitude: -122.4194 + index * 0.001, createdByDeviceId: 'testDevice$index', - endAt: index % 2 == 0 - ? DateTime.now().add(Duration(hours: 1)) + endAt: index.isEven + ? DateTime.now().add(const Duration(hours: 1)) : null, // Some live, some static createdAt: DateTime.now(), updatedAt: DateTime.now(), diff --git a/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart b/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart index 07d9c19c99..566e6f0313 100644 --- a/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart +++ b/packages/stream_chat_persistence/test/stream_chat_persistence_client_test.dart @@ -781,12 +781,14 @@ void main() { test('deleteLocationsByMessageIds', () async { final messageIds = ['testMessageId1', 'testMessageId2']; - when(() => mockDatabase.locationDao.deleteLocationsByMessageIds(messageIds)) - .thenAnswer((_) async {}); + when( + () => mockDatabase.locationDao.deleteLocationsByMessageIds(messageIds), + ).thenAnswer((_) async {}); await client.deleteLocationsByMessageIds(messageIds); - verify(() => mockDatabase.locationDao.deleteLocationsByMessageIds(messageIds)) - .called(1); + verify( + () => mockDatabase.locationDao.deleteLocationsByMessageIds(messageIds), + ).called(1); }); tearDown(() async { From 1075d8c0cc0d8b6db8050a80e708c20d46f90798 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 23 Jul 2025 16:31:42 +0200 Subject: [PATCH 25/26] fix: use correct DAO for pinned message reactions Pinned messages were incorrectly using the main `ReactionDao` to fetch their reactions. This commit corrects this by using the dedicated `PinnedMessageReactionDao`. --- .../lib/src/dao/pinned_message_dao.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart b/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart index 611648f915..c22b6ddba3 100644 --- a/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/pinned_message_dao.dart @@ -43,8 +43,10 @@ class PinnedMessageDao extends DatabaseAccessor final userEntity = rows.readTableOrNull(_users); final pinnedByEntity = rows.readTableOrNull(_pinnedByUsers); final msgEntity = rows.readTable(pinnedMessages); - final latestReactions = await _db.reactionDao.getReactions(msgEntity.id); - final ownReactions = await _db.reactionDao.getReactionsByUserId( + final latestReactions = + await _db.pinnedMessageReactionDao.getReactions(msgEntity.id); + final ownReactions = + await _db.pinnedMessageReactionDao.getReactionsByUserId( msgEntity.id, _db.userId, ); From 9d8ef58e84cece124cb9dc23097e5bdca83a17c1 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 24 Jul 2025 16:04:22 +0200 Subject: [PATCH 26/26] Update packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart --- .../stream_chat_persistence/lib/src/db/drift_chat_database.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart index 8b740c80c6..eaca779f8e 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart @@ -57,7 +57,7 @@ class DriftChatDatabase extends _$DriftChatDatabase { // you should bump this number whenever you change or add a table definition. @override - int get schemaVersion => 23; + int get schemaVersion => 1000 + 23; @override MigrationStrategy get migration => MigrationStrategy(