diff --git a/migrations/v10-migration.md b/migrations/v10-migration.md index 0575d9eac..951fd6c34 100644 --- a/migrations/v10-migration.md +++ b/migrations/v10-migration.md @@ -8,6 +8,10 @@ This guide includes breaking changes grouped by release phase: +### ๐Ÿšง v10.0.0-beta.4 + +- [SendReaction](#-sendreaction) + ### ๐Ÿšง v10.0.0-beta.3 - [AttachmentPickerType](#-attachmentpickertype) @@ -24,6 +28,65 @@ This guide includes breaking changes grouped by release phase: --- +## ๐Ÿงช Migration for v10.0.0-beta.4 + +### ๐Ÿ›  SendReaction + +#### Key Changes: + +- `sendReaction` method now accepts a full `Reaction` object instead of individual parameters. + +#### Migration Steps: + +**Before:** +```dart +// Using individual parameters +channel.sendReaction( + message, + 'like', + score: 1, + extraData: {'custom_field': 'value'}, +); + +client.sendReaction( + messageId, + 'love', + enforceUnique: true, + extraData: {'custom_field': 'value'}, +); +``` + +**After:** +```dart +// Using Reaction object +channel.sendReaction( + message, + Reaction( + type: 'like', + score: 1, + emojiCode: '๐Ÿ‘', + extraData: {'custom_field': 'value'}, + ), +); + +client.sendReaction( + messageId, + Reaction( + type: 'love', + emojiCode: 'โค๏ธ', + extraData: {'custom_field': 'value'}, + ), + enforceUnique: true, +); +``` + +> โš ๏ธ **Important:** +> - The `sendReaction` method now requires a `Reaction` object +> - Optional parameters like `enforceUnique` and `skipPush` remain as method parameters +> - You can now specify custom emoji codes for reactions using the `emojiCode` field + +--- + ## ๐Ÿงช Migration for v10.0.0-beta.3 ### ๐Ÿ›  AttachmentPickerType diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index 4462d77e8..a101b3992 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -1,5 +1,11 @@ ## Upcoming Beta +๐Ÿ›‘๏ธ Breaking + +- **Changed `sendReaction` method signature**: The `sendReaction` method on both `Client` and + `Channel` now accepts a full `Reaction` object instead of individual parameters (`type`, `score`, + `extraData`). This change provides more flexibility and better type safety. + โœ… Added - Added comprehensive location sharing support with static and live location features: diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index bab7aa8f3..efb70cf0f 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1407,28 +1407,17 @@ class Channel { /// Set [enforceUnique] to true to remove the existing user reaction. Future sendReaction( Message message, - String type, { - int score = 1, - Map extraData = const {}, + Reaction reaction, { + bool skipPush = false, bool enforceUnique = false, }) async { _checkInitialized(); - final currentUser = _client.state.currentUser; - if (currentUser == null) { - throw StateError( - 'Cannot send reaction: current user is not available. ' - 'Ensure the client is connected and a user is set.', - ); - } final messageId = message.id; - final reaction = Reaction( - type: type, + // ignore: parameter_assignments + reaction = reaction.copyWith( messageId: messageId, - user: currentUser, - score: score, - createdAt: DateTime.timestamp(), - extraData: extraData, + user: _client.state.currentUser, ); final updatedMessage = message.addMyReaction( @@ -1441,9 +1430,8 @@ class Channel { try { final reactionResp = await _client.sendReaction( messageId, - reaction.type, - score: reaction.score, - extraData: reaction.extraData, + reaction, + skipPush: skipPush, enforceUnique: enforceUnique, ); return reactionResp; @@ -1459,6 +1447,8 @@ class Channel { Message message, Reaction reaction, ) async { + _checkInitialized(); + final updatedMessage = message.deleteMyReaction( reactionType: reaction.type, ); @@ -2843,24 +2833,25 @@ class ChannelClientState { void _listenReactionDeleted() { _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 (eventReaction, eventMessage) = (event.reaction, event.message); + if (eventReaction == null || eventMessage == 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; - }); + final currentUserId = _channel.client.state.currentUser?.id; + + final currentMessage = switch (currentUserId) { + final userId? when userId == eventReaction.userId => + message.deleteMyReaction(reactionType: eventReaction.type), + _ => message, + }; return updateMessage( eventMessage.copyWith( - ownReactions: updatedOwnReactions?.toList(), + ownReactions: currentMessage.ownReactions, ), ); } @@ -2871,17 +2862,25 @@ class ChannelClientState { void _listenReactionNew() { _subscriptions.add(_channel.on(EventType.reactionNew).listen((event) { - final eventMessage = event.message; - if (eventMessage == null) return; + final (eventReaction, eventMessage) = (event.reaction, event.message); + if (eventReaction == null || eventMessage == null) return; final messageId = eventMessage.id; final parentId = eventMessage.parentId; for (final message in [...messages, ...?threads[parentId]]) { if (message.id == messageId) { + final currentUserId = _channel.client.state.currentUser?.id; + + final currentMessage = switch (currentUserId) { + final userId? when userId == eventReaction.userId => + message.addMyReaction(eventReaction), + _ => message, + }; + return updateMessage( eventMessage.copyWith( - ownReactions: message.ownReactions, + ownReactions: currentMessage.ownReactions, ), ); } @@ -2892,17 +2891,26 @@ class ChannelClientState { void _listenReactionUpdated() { _subscriptions.add( _channel.on(EventType.reactionUpdated).listen((event) { - final eventMessage = event.message; - if (eventMessage == null) return; + final (eventReaction, eventMessage) = (event.reaction, event.message); + if (eventReaction == null || eventMessage == null) return; final messageId = eventMessage.id; final parentId = eventMessage.parentId; for (final message in [...messages, ...?threads[parentId]]) { if (message.id == messageId) { + final currentUserId = _channel.client.state.currentUser?.id; + + final currentMessage = switch (currentUserId) { + final userId? when userId == eventReaction.userId => + // reaction.updated is only called if enforce_unique is true + message.addMyReaction(eventReaction, enforceUnique: true), + _ => message, + }; + return updateMessage( eventMessage.copyWith( - ownReactions: message.ownReactions, + ownReactions: currentMessage.ownReactions, ), ); } diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index e059436ff..f68e8282b 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -34,6 +34,7 @@ import 'package:stream_chat/src/core/models/own_user.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/reaction.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'; @@ -1587,23 +1588,16 @@ class StreamChatClient { /// Set [enforceUnique] to true to remove the existing user reaction Future sendReaction( String messageId, - String reactionType, { - int score = 1, - Map extraData = const {}, + Reaction reaction, { + bool skipPush = false, bool enforceUnique = false, - }) { - final _extraData = { - 'score': score, - ...extraData, - }; - - return _chatApi.message.sendReaction( - messageId, - reactionType, - extraData: _extraData, - enforceUnique: enforceUnique, - ); - } + }) => + _chatApi.message.sendReaction( + messageId, + reaction, + skipPush: skipPush, + enforceUnique: enforceUnique, + ); /// Delete a [reactionType] from this [messageId] Future deleteReaction( 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 afd00caed..f1f7fd1ad 100644 --- a/packages/stream_chat/lib/src/core/api/message_api.dart +++ b/packages/stream_chat/lib/src/core/api/message_api.dart @@ -8,6 +8,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/filter.dart'; import 'package:stream_chat/src/core/models/message.dart'; +import 'package:stream_chat/src/core/models/reaction.dart'; /// Defines the api dedicated to messages operations class MessageApi { @@ -208,19 +209,17 @@ class MessageApi { /// Set [enforceUnique] to true to remove the existing user reaction Future sendReaction( String messageId, - String reactionType, { - Map extraData = const {}, + Reaction reaction, { + bool skipPush = false, bool enforceUnique = false, }) async { - final reaction = Map.from(extraData) - ..addAll({'type': reactionType}); - final response = await _client.post( '/messages/$messageId/reaction', - data: { - 'reaction': reaction, + data: json.encode({ + 'reaction': reaction.toJson(), + 'skip_push': skipPush, 'enforce_unique': enforceUnique, - }, + }), ); return SendReactionResponse.fromJson(response.data); } diff --git a/packages/stream_chat/lib/src/core/models/reaction.dart b/packages/stream_chat/lib/src/core/models/reaction.dart index 474b6dff6..dc62fd7ce 100644 --- a/packages/stream_chat/lib/src/core/models/reaction.dart +++ b/packages/stream_chat/lib/src/core/models/reaction.dart @@ -1,3 +1,4 @@ +import 'package:equatable/equatable.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:stream_chat/src/core/models/user.dart'; import 'package:stream_chat/src/core/util/serializer.dart'; @@ -6,18 +7,21 @@ part 'reaction.g.dart'; /// The class that defines a reaction @JsonSerializable() -class Reaction { +class Reaction extends Equatable { /// Constructor used for json serialization Reaction({ this.messageId, - DateTime? createdAt, required this.type, this.user, String? userId, - this.score = 0, + this.score = 1, + this.emojiCode, + DateTime? createdAt, + DateTime? updatedAt, this.extraData = const {}, }) : userId = userId ?? user?.id, - createdAt = createdAt ?? DateTime.now(); + createdAt = createdAt ?? DateTime.timestamp(), + updatedAt = updatedAt ?? DateTime.timestamp(); /// Create a new instance from a json factory Reaction.fromJson(Map json) => @@ -27,37 +31,48 @@ class Reaction { )); /// The messageId to which the reaction belongs + @JsonKey(includeToJson: false) final String? messageId; /// The type of the reaction final String type; - /// The date of the reaction - @JsonKey(includeToJson: false) - final DateTime createdAt; + /// The score of the reaction (ie. number of reactions sent) + final int score; + + /// The emoji code of the reaction (used for notifications) + @JsonKey(includeIfNull: false) + final String? emojiCode; /// The user that sent the reaction @JsonKey(includeToJson: false) final User? user; - /// The score of the reaction (ie. number of reactions sent) - final int score; - /// The userId that sent the reaction @JsonKey(includeToJson: false) final String? userId; + /// The date of the reaction + @JsonKey(includeToJson: false) + final DateTime createdAt; + + /// The date of the reaction update + @JsonKey(includeToJson: false) + final DateTime updatedAt; + /// Reaction custom extraData final Map extraData; /// Map of custom user extraData static const topLevelFields = [ 'message_id', - 'created_at', 'type', 'user', 'user_id', 'score', + 'emoji_code', + 'created_at', + 'updated_at', ]; /// Serialize to json @@ -68,20 +83,24 @@ class Reaction { /// Creates a copy of [Reaction] with specified attributes overridden. Reaction copyWith({ String? messageId, - DateTime? createdAt, String? type, User? user, String? userId, int? score, + String? emojiCode, + DateTime? createdAt, + DateTime? updatedAt, Map? extraData, }) => Reaction( messageId: messageId ?? this.messageId, - createdAt: createdAt ?? this.createdAt, type: type ?? this.type, user: user ?? this.user, userId: userId ?? this.userId, score: score ?? this.score, + emojiCode: emojiCode ?? this.emojiCode, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, extraData: extraData ?? this.extraData, ); @@ -89,11 +108,26 @@ class Reaction { /// given [other] reaction. Reaction merge(Reaction other) => copyWith( messageId: other.messageId, - createdAt: other.createdAt, type: other.type, user: other.user, userId: other.userId, score: other.score, + emojiCode: other.emojiCode, + createdAt: other.createdAt, + updatedAt: other.updatedAt, extraData: other.extraData, ); + + @override + List get props => [ + messageId, + type, + user, + userId, + score, + emojiCode, + createdAt, + updatedAt, + extraData, + ]; } diff --git a/packages/stream_chat/lib/src/core/models/reaction.g.dart b/packages/stream_chat/lib/src/core/models/reaction.g.dart index 3be01abc3..f29c4e093 100644 --- a/packages/stream_chat/lib/src/core/models/reaction.g.dart +++ b/packages/stream_chat/lib/src/core/models/reaction.g.dart @@ -8,21 +8,25 @@ part of 'reaction.dart'; Reaction _$ReactionFromJson(Map json) => Reaction( messageId: json['message_id'] as String?, - createdAt: json['created_at'] == null - ? null - : DateTime.parse(json['created_at'] as String), type: json['type'] as String, user: json['user'] == null ? null : User.fromJson(json['user'] as Map), userId: json['user_id'] as String?, - score: (json['score'] as num?)?.toInt() ?? 0, + score: (json['score'] as num?)?.toInt() ?? 1, + emojiCode: json['emoji_code'] 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), extraData: json['extra_data'] as Map? ?? const {}, ); Map _$ReactionToJson(Reaction instance) => { - 'message_id': instance.messageId, 'type': instance.type, 'score': instance.score, + if (instance.emojiCode case final value?) 'emoji_code': value, 'extra_data': instance.extraData, }; diff --git a/packages/stream_chat/test/fixtures/reaction.json b/packages/stream_chat/test/fixtures/reaction.json index ce87ca1d2..c0e8ef35c 100644 --- a/packages/stream_chat/test/fixtures/reaction.json +++ b/packages/stream_chat/test/fixtures/reaction.json @@ -13,6 +13,7 @@ }, "type": "wow", "score": 1, + "emoji_code": "\uD83D\uDE2E", "created_at": "2020-01-28T22:17:31.108742Z", "updated_at": "2020-01-28T22:17:31.108742Z" } \ No newline at end of file diff --git a/packages/stream_chat/test/src/client/channel_test.dart b/packages/stream_chat/test/src/client/channel_test.dart index a07f7fbba..f8bbb21e6 100644 --- a/packages/stream_chat/test/src/client/channel_test.dart +++ b/packages/stream_chat/test/src/client/channel_test.dart @@ -1505,67 +1505,24 @@ void main() { group('`.sendReaction`', () { test('should work fine', () async { - const type = 'test-reaction-type'; final message = Message( id: 'test-message-id', state: MessageState.sent, ); - final reaction = Reaction(type: type, messageId: message.id); + const type = 'like'; + const emojiCode = '๐Ÿ‘'; + const score = 4; - when(() => client.sendReaction(message.id, type)).thenAnswer( - (_) async => SendReactionResponse() - ..message = message - ..reaction = reaction, - ); - - expectLater( - // skipping first seed message list -> [] messages - channel.state?.messagesStream.skip(1), - emitsInOrder([ - [ - isSameMessageAs( - message.copyWith( - state: MessageState.sent, - reactionGroups: {type: ReactionGroup(count: 1, sumScores: 1)}, - latestReactions: [reaction], - ownReactions: [reaction], - ), - matchReactions: true, - matchMessageState: true, - ), - ], - ]), - ); - - final res = await channel.sendReaction(message, type); - - expect(res, isNotNull); - expect(res.reaction.type, type); - expect(res.reaction.messageId, message.id); - - verify(() => client.sendReaction(message.id, type)).called(1); - }); - - test('should work fine with score passed explicitly', () async { - const type = 'test-reaction-type'; - final message = Message( - id: 'test-message-id', - state: MessageState.sent, - ); - - const score = 5; final reaction = Reaction( type: type, messageId: message.id, + emojiCode: emojiCode, score: score, + user: client.state.currentUser, ); - when(() => client.sendReaction( - message.id, - type, - score: score, - )).thenAnswer( + when(() => client.sendReaction(message.id, reaction)).thenAnswer( (_) async => SendReactionResponse() ..message = message ..reaction = reaction, @@ -1579,12 +1536,7 @@ void main() { isSameMessageAs( message.copyWith( state: MessageState.sent, - reactionGroups: { - type: ReactionGroup( - count: 1, - sumScores: score, - ) - }, + reactionGroups: {type: ReactionGroup(count: 1, sumScores: 1)}, latestReactions: [reaction], ownReactions: [reaction], ), @@ -1595,99 +1547,15 @@ void main() { ]), ); - final res = await channel.sendReaction( - message, - type, - score: score, - ); + final res = await channel.sendReaction(message, reaction); expect(res, isNotNull); expect(res.reaction.type, type); expect(res.reaction.messageId, message.id); + expect(res.reaction.emojiCode, emojiCode); expect(res.reaction.score, score); - verify(() => client.sendReaction( - message.id, - type, - score: score, - )).called(1); - }); - - test('should work fine with score passed explicitly and in extraData', - () async { - const type = 'test-reaction-type'; - final message = Message( - id: 'test-message-id', - state: MessageState.sent, - ); - - const score = 5; - const extraDataScore = 3; - const extraData = { - 'score': extraDataScore, - }; - final reaction = Reaction( - type: type, - messageId: message.id, - score: extraDataScore, - ); - - when(() => client.sendReaction( - message.id, - type, - score: score, - extraData: extraData, - )).thenAnswer( - (_) async => SendReactionResponse() - ..message = message - ..reaction = reaction, - ); - - expectLater( - // skipping first seed message list -> [] messages - channel.state?.messagesStream.skip(1), - emitsInOrder([ - [ - isSameMessageAs( - message.copyWith( - state: MessageState.sent, - reactionGroups: { - type: ReactionGroup( - count: 1, - sumScores: extraDataScore, - ) - }, - latestReactions: [reaction], - ownReactions: [reaction], - ), - matchReactions: true, - matchMessageState: true, - ), - ], - ]), - ); - - final res = await channel.sendReaction( - message, - type, - score: score, - extraData: extraData, - ); - - expect(res, isNotNull); - expect(res.reaction.type, type); - expect(res.reaction.messageId, message.id); - expect( - res.reaction.score, - extraDataScore, - ); - - verify(() => client.sendReaction( - message.id, - type, - score: score, - extraData: extraData, - )).called(1); + verify(() => client.sendReaction(message.id, reaction)).called(1); }); test( @@ -1699,9 +1567,13 @@ void main() { state: MessageState.sent, ); - final reaction = Reaction(type: type, messageId: message.id); + final reaction = Reaction( + type: type, + messageId: message.id, + user: client.state.currentUser, + ); - when(() => client.sendReaction(message.id, type)) + when(() => client.sendReaction(message.id, reaction)) .thenThrow(StreamChatNetworkError(ChatErrorCode.inputError)); expectLater( @@ -1736,25 +1608,24 @@ void main() { ); try { - await channel.sendReaction(message, type); + await channel.sendReaction(message, reaction); } catch (e) { expect(e, isA()); } - verify(() => client.sendReaction(message.id, type)).called(1); + verify(() => client.sendReaction(message.id, reaction)).called(1); }, ); test( '''should override previous reaction if present and `enforceUnique` is true''', () async { - const userId = 'test-user-id'; const messageId = 'test-message-id'; const prevType = 'test-reaction-type'; final prevReaction = Reaction( type: prevType, messageId: messageId, - userId: userId, + user: client.state.currentUser, ); final message = Message( id: messageId, @@ -1773,7 +1644,7 @@ void main() { final newReaction = Reaction( type: type, messageId: messageId, - userId: userId, + user: client.state.currentUser, ); final newMessage = message.copyWith( ownReactions: [newReaction], @@ -1784,7 +1655,7 @@ void main() { when(() => client.sendReaction( messageId, - type, + newReaction, enforceUnique: enforceUnique, )).thenAnswer( (_) async => SendReactionResponse() @@ -1808,7 +1679,7 @@ void main() { final res = await channel.sendReaction( message, - type, + newReaction, enforceUnique: enforceUnique, ); @@ -1818,7 +1689,7 @@ void main() { verify(() => client.sendReaction( messageId, - type, + newReaction, enforceUnique: enforceUnique, )).called(1); }, @@ -1834,9 +1705,13 @@ void main() { state: MessageState.sent, ); - final reaction = Reaction(type: type, messageId: message.id); + final reaction = Reaction( + type: type, + messageId: message.id, + user: client.state.currentUser, + ); - when(() => client.sendReaction(message.id, type)).thenAnswer( + when(() => client.sendReaction(message.id, reaction)).thenAnswer( (_) async => SendReactionResponse() ..message = message ..reaction = reaction, @@ -1869,13 +1744,13 @@ void main() { ]), ); - final res = await channel.sendReaction(message, type); + final res = await channel.sendReaction(message, reaction); expect(res, isNotNull); expect(res.reaction.type, type); expect(res.reaction.messageId, message.id); - verify(() => client.sendReaction(message.id, type)).called(1); + verify(() => client.sendReaction(message.id, reaction)).called(1); }); test( @@ -1888,9 +1763,13 @@ void main() { state: MessageState.sent, ); - final reaction = Reaction(type: type, messageId: message.id); + final reaction = Reaction( + type: type, + messageId: message.id, + user: client.state.currentUser, + ); - when(() => client.sendReaction(message.id, type)) + when(() => client.sendReaction(message.id, reaction)) .thenThrow(StreamChatNetworkError(ChatErrorCode.inputError)); expectLater( @@ -1929,26 +1808,25 @@ void main() { ); try { - await channel.sendReaction(message, type); + await channel.sendReaction(message, reaction); } catch (e) { expect(e, isA()); } - verify(() => client.sendReaction(message.id, type)).called(1); + verify(() => client.sendReaction(message.id, reaction)).called(1); }, ); test( '''should override previous thread reaction if present and `enforceUnique` is true''', () async { - const userId = 'test-user-id'; const messageId = 'test-message-id'; const parentId = 'test-parent-id'; const prevType = 'test-reaction-type'; final prevReaction = Reaction( type: prevType, messageId: messageId, - userId: userId, + user: client.state.currentUser, ); final message = Message( id: messageId, @@ -1968,7 +1846,7 @@ void main() { final newReaction = Reaction( type: type, messageId: messageId, - userId: userId, + user: client.state.currentUser, ); final newMessage = message.copyWith( ownReactions: [newReaction], @@ -1979,7 +1857,7 @@ void main() { when(() => client.sendReaction( messageId, - type, + newReaction, enforceUnique: enforceUnique, )).thenAnswer( (_) async => SendReactionResponse() @@ -2006,7 +1884,7 @@ void main() { final res = await channel.sendReaction( message, - type, + newReaction, enforceUnique: enforceUnique, ); @@ -2016,7 +1894,7 @@ void main() { verify(() => client.sendReaction( messageId, - type, + newReaction, enforceUnique: enforceUnique, )).called(1); }, diff --git a/packages/stream_chat/test/src/client/client_test.dart b/packages/stream_chat/test/src/client/client_test.dart index 95f48ab2c..dd29a9e4c 100644 --- a/packages/stream_chat/test/src/client/client_test.dart +++ b/packages/stream_chat/test/src/client/client_test.dart @@ -3231,109 +3231,35 @@ void main() { verifyNoMoreInteractions(api.channel); }); - group('`.sendReaction`', () { - test('`.sendReaction with default params`', () async { - const messageId = 'test-message-id'; - const reactionType = 'like'; - const extraData = {'score': 1}; - - when(() => api.message.sendReaction( - messageId, - reactionType, - extraData: extraData, - )).thenAnswer((_) async => SendReactionResponse() - ..message = Message(id: messageId) - ..reaction = Reaction(type: reactionType, messageId: messageId)); - - final res = await client.sendReaction(messageId, reactionType); - expect(res, isNotNull); - expect(res.message.id, messageId); - expect(res.reaction.type, reactionType); - expect(res.reaction.messageId, messageId); - - verify(() => api.message.sendReaction( - messageId, - reactionType, - extraData: extraData, - )).called(1); - verifyNoMoreInteractions(api.message); - }); - - test('`.sendReaction with score`', () async { - const messageId = 'test-message-id'; - const reactionType = 'like'; - const score = 3; - const extraData = {'score': score}; - - when(() => api.message.sendReaction( - messageId, - reactionType, - extraData: extraData, - )).thenAnswer((_) async => SendReactionResponse() - ..message = Message(id: messageId) - ..reaction = Reaction( - type: reactionType, - messageId: messageId, - score: score, - )); - - final res = await client.sendReaction( - messageId, - reactionType, - score: score, - ); - expect(res, isNotNull); - expect(res.message.id, messageId); - expect(res.reaction.type, reactionType); - expect(res.reaction.messageId, messageId); - expect(res.reaction.score, score); - - verify(() => api.message.sendReaction( - messageId, - reactionType, - extraData: extraData, - )).called(1); - verifyNoMoreInteractions(api.message); - }); + test('`.sendReaction`', () async { + const messageId = 'test-message-id'; + const reactionType = 'like'; + const emojiCode = '๐Ÿ‘'; + const score = 4; - test('`.sendReaction with score passed in extradata also`', () async { - const messageId = 'test-message-id'; - const reactionType = 'like'; - const score = 3; - const extraDataScore = 5; - const extraData = {'score': extraDataScore}; + final reaction = Reaction( + type: reactionType, + messageId: messageId, + emojiCode: emojiCode, + score: score, + ); - when(() => api.message.sendReaction( - messageId, - reactionType, - extraData: extraData, - )).thenAnswer((_) async => SendReactionResponse() + when(() => api.message.sendReaction(messageId, reaction)).thenAnswer( + (_) async => SendReactionResponse() ..message = Message(id: messageId) - ..reaction = Reaction( - type: reactionType, - messageId: messageId, - score: extraDataScore, - )); + ..reaction = reaction, + ); - final res = await client.sendReaction( - messageId, - reactionType, - score: score, - extraData: extraData, - ); - expect(res, isNotNull); - expect(res.message.id, messageId); - expect(res.reaction.type, reactionType); - expect(res.reaction.messageId, messageId); - expect(res.reaction.score, extraDataScore); + final res = await client.sendReaction(messageId, reaction); + expect(res, isNotNull); + expect(res.message.id, messageId); + expect(res.reaction.type, reactionType); + expect(res.reaction.emojiCode, emojiCode); + expect(res.reaction.score, score); + expect(res.reaction.messageId, messageId); - verify(() => api.message.sendReaction( - messageId, - reactionType, - extraData: extraData, - )).called(1); - verifyNoMoreInteractions(api.message); - }); + verify(() => api.message.sendReaction(messageId, reaction)).called(1); + verifyNoMoreInteractions(api.message); }); test('`.deleteReaction`', () async { diff --git a/packages/stream_chat/test/src/core/api/message_api_test.dart b/packages/stream_chat/test/src/core/api/message_api_test.dart index 6f224e876..ac726ccdb 100644 --- a/packages/stream_chat/test/src/core/api/message_api_test.dart +++ b/packages/stream_chat/test/src/core/api/message_api_test.dart @@ -253,7 +253,6 @@ void main() { test('sendReaction', () async { const messageId = 'test-message-id'; const reactionType = 'test-reaction-type'; - const extraData = {'test-key': 'test-data'}; const path = '/messages/$messageId/reaction'; @@ -262,21 +261,17 @@ void main() { when(() => client.post( path, - data: { - 'reaction': Map.from(extraData) - ..addAll({'type': reactionType}), + data: jsonEncode({ + 'reaction': reaction.toJson(), + 'skip_push': false, 'enforce_unique': false, - }, + }), )).thenAnswer((_) async => successResponse(path, data: { 'message': message.toJson(), - 'reaction': reaction.toJson(), + 'reaction': {...reaction.toJson(), 'message_id': messageId}, })); - final res = await messageApi.sendReaction( - messageId, - reactionType, - extraData: extraData, - ); + final res = await messageApi.sendReaction(messageId, reaction); expect(res, isNotNull); expect(res.message.id, messageId); @@ -290,7 +285,6 @@ void main() { test('sendReaction with enforceUnique: true', () async { const messageId = 'test-message-id'; const reactionType = 'test-reaction-type'; - const extraData = {'test-key': 'test-data'}; const path = '/messages/$messageId/reaction'; @@ -299,20 +293,19 @@ void main() { when(() => client.post( path, - data: { - 'reaction': Map.from(extraData) - ..addAll({'type': reactionType}), + data: jsonEncode({ + 'reaction': reaction.toJson(), + 'skip_push': false, 'enforce_unique': true, - }, + }), )).thenAnswer((_) async => successResponse(path, data: { 'message': message.toJson(), - 'reaction': reaction.toJson(), + 'reaction': {...reaction.toJson(), 'message_id': messageId}, })); final res = await messageApi.sendReaction( messageId, - reactionType, - extraData: extraData, + reaction, enforceUnique: true, ); @@ -362,7 +355,11 @@ void main() { ...const PaginationParams().toJson(), }, )).thenAnswer((_) async => successResponse(path, data: { - 'reactions': [...reactions.map((it) => it.toJson())] + 'reactions': [ + ...reactions.map( + (it) => {...it.toJson(), 'message_id': messageId}, + ), + ] })); final res = await messageApi.getReactions(messageId, pagination: options); diff --git a/packages/stream_chat/test/src/core/models/reaction_test.dart b/packages/stream_chat/test/src/core/models/reaction_test.dart index 285d8a461..6abd278d1 100644 --- a/packages/stream_chat/test/src/core/models/reaction_test.dart +++ b/packages/stream_chat/test/src/core/models/reaction_test.dart @@ -10,6 +10,7 @@ void main() { final reaction = Reaction.fromJson(jsonFixture('reaction.json')); expect(reaction.messageId, '76cd8c82-b557-4e48-9d12-87995d3a0e04'); expect(reaction.createdAt, DateTime.parse('2020-01-28T22:17:31.108742Z')); + expect(reaction.updatedAt, DateTime.parse('2020-01-28T22:17:31.108742Z')); expect(reaction.type, 'wow'); expect( reaction.user?.toJson(), @@ -21,13 +22,14 @@ void main() { ); expect(reaction.score, 1); expect(reaction.userId, '2de0297c-f3f2-489d-b930-ef77342edccf'); - expect(reaction.extraData, {'updated_at': '2020-01-28T22:17:31.108742Z'}); + expect(reaction.emojiCode, '๐Ÿ˜ฎ'); }); test('should serialize to json correctly', () { final reaction = Reaction( messageId: '76cd8c82-b557-4e48-9d12-87995d3a0e04', createdAt: DateTime.parse('2020-01-28T22:17:31.108742Z'), + updatedAt: DateTime.parse('2020-01-28T22:17:31.108742Z'), type: 'wow', user: User( id: '2de0297c-f3f2-489d-b930-ef77342edccf', @@ -35,16 +37,16 @@ void main() { name: 'Daisy Morgan', ), userId: '2de0297c-f3f2-489d-b930-ef77342edccf', - extraData: {'bananas': 'yes'}, - score: 1, + extraData: const {'bananas': 'yes'}, + emojiCode: '๐Ÿ˜ฎ', ); expect( reaction.toJson(), { - 'message_id': '76cd8c82-b557-4e48-9d12-87995d3a0e04', 'type': 'wow', 'score': 1, + 'emoji_code': '๐Ÿ˜ฎ', 'bananas': 'yes', }, ); @@ -56,6 +58,8 @@ void main() { expect(newReaction.messageId, '76cd8c82-b557-4e48-9d12-87995d3a0e04'); expect( newReaction.createdAt, DateTime.parse('2020-01-28T22:17:31.108742Z')); + expect( + newReaction.updatedAt, DateTime.parse('2020-01-28T22:17:31.108742Z')); expect(newReaction.type, 'wow'); expect( newReaction.user?.toJson(), @@ -67,14 +71,15 @@ void main() { ); expect(newReaction.score, 1); expect(newReaction.userId, '2de0297c-f3f2-489d-b930-ef77342edccf'); - expect( - newReaction.extraData, {'updated_at': '2020-01-28T22:17:31.108742Z'}); + expect(newReaction.emojiCode, '๐Ÿ˜ฎ'); final newUserCreateTime = DateTime.now(); newReaction = reaction.copyWith( type: 'lol', + emojiCode: '๐Ÿ˜‚', createdAt: DateTime.parse('2021-01-28T22:17:31.108742Z'), + updatedAt: DateTime.parse('2021-01-28T22:17:31.108742Z'), extraData: {}, messageId: 'test', score: 2, @@ -87,10 +92,15 @@ void main() { ); expect(newReaction.type, 'lol'); + expect(newReaction.emojiCode, '๐Ÿ˜‚'); expect( newReaction.createdAt, DateTime.parse('2021-01-28T22:17:31.108742Z'), ); + expect( + newReaction.updatedAt, + DateTime.parse('2021-01-28T22:17:31.108742Z'), + ); expect(newReaction.extraData, {}); expect(newReaction.messageId, 'test'); expect(newReaction.score, 2); @@ -112,8 +122,9 @@ void main() { final newReaction = reaction.merge( Reaction( type: 'lol', + emojiCode: '๐Ÿ˜‚', createdAt: DateTime.parse('2021-01-28T22:17:31.108742Z'), - extraData: {}, + updatedAt: DateTime.parse('2021-01-28T22:17:31.108742Z'), messageId: 'test', score: 2, user: User( @@ -126,10 +137,15 @@ void main() { ); expect(newReaction.type, 'lol'); + expect(newReaction.emojiCode, '๐Ÿ˜‚'); expect( newReaction.createdAt, DateTime.parse('2021-01-28T22:17:31.108742Z'), ); + expect( + newReaction.updatedAt, + DateTime.parse('2021-01-28T22:17:31.108742Z'), + ); expect(newReaction.extraData, {}); expect(newReaction.messageId, 'test'); expect(newReaction.score, 2); diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 27f602c94..548b91226 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -1,3 +1,10 @@ +## Upcoming Beta + +โœ… Added + +- Added `emojiCode` property to `StreamReactionIcon` to support custom emojis in reactions. +- Updated default reaction builders with standard emoji codes. (`โค๏ธ`, `๐Ÿ‘`, `๐Ÿ‘Ž`, `๐Ÿ˜‚`, `๐Ÿ˜ฎ`) + ## Upcoming โœ… Added diff --git a/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart b/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart index 1e871fd7a..6e6e621e1 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart @@ -1159,7 +1159,7 @@ class _StreamMessageWidgetState extends State return channel.sendReaction( message, - reaction.type, + reaction, enforceUnique: enforceUnique, ); } diff --git a/packages/stream_chat_flutter/lib/src/misc/reaction_icon.dart b/packages/stream_chat_flutter/lib/src/misc/reaction_icon.dart index 09dd2f097..fb5ccde92 100644 --- a/packages/stream_chat_flutter/lib/src/misc/reaction_icon.dart +++ b/packages/stream_chat_flutter/lib/src/misc/reaction_icon.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/icons/stream_svg_icon.dart'; import 'package:stream_chat_flutter/src/theme/stream_chat_theme.dart'; +import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; /// {@template reactionIconBuilder} /// Signature for a function that builds a reaction icon. @@ -20,17 +21,27 @@ class StreamReactionIcon { /// {@macro streamReactionIcon} const StreamReactionIcon({ required this.type, + this.emojiCode, required this.builder, }); /// Creates a reaction icon with a default unknown icon. const StreamReactionIcon.unknown() : type = 'unknown', - builder = _unknownReactionBuilder; + emojiCode = null, + builder = _unknownBuilder; + + /// Converts this [StreamReactionIcon] to a [Reaction] object. + Reaction toReaction() => Reaction(type: type, emojiCode: emojiCode); /// Type of reaction final String type; + /// Optional emoji code for the reaction. + /// + /// Used to display a custom emoji in the notification. + final String? emojiCode; + /// {@macro reactionIconBuilder} final ReactionIconBuilder builder; @@ -46,14 +57,14 @@ class StreamReactionIcon { /// These default reactions can be used directly or as a starting point for /// custom reaction configurations. static const List defaultReactions = [ - StreamReactionIcon(type: 'love', builder: _loveReactionBuilder), - StreamReactionIcon(type: 'like', builder: _likeReactionBuilder), - StreamReactionIcon(type: 'sad', builder: _sadReactionBuilder), - StreamReactionIcon(type: 'haha', builder: _hahaReactionBuilder), - StreamReactionIcon(type: 'wow', builder: _wowReactionBuilder), + StreamReactionIcon(type: 'love', emojiCode: 'โค๏ธ', builder: _loveBuilder), + StreamReactionIcon(type: 'like', emojiCode: '๐Ÿ‘', builder: _likeBuilder), + StreamReactionIcon(type: 'sad', emojiCode: '๐Ÿ‘Ž', builder: _sadBuilder), + StreamReactionIcon(type: 'haha', emojiCode: '๐Ÿ˜‚', builder: _hahaBuilder), + StreamReactionIcon(type: 'wow', emojiCode: '๐Ÿ˜ฎ', builder: _wowBuilder), ]; - static Widget _loveReactionBuilder( + static Widget _loveBuilder( BuildContext context, bool highlighted, double size, @@ -71,7 +82,7 @@ class StreamReactionIcon { ); } - static Widget _likeReactionBuilder( + static Widget _likeBuilder( BuildContext context, bool highlighted, double size, @@ -89,7 +100,7 @@ class StreamReactionIcon { ); } - static Widget _sadReactionBuilder( + static Widget _sadBuilder( BuildContext context, bool highlighted, double size, @@ -107,7 +118,7 @@ class StreamReactionIcon { ); } - static Widget _hahaReactionBuilder( + static Widget _hahaBuilder( BuildContext context, bool highlighted, double size, @@ -125,7 +136,7 @@ class StreamReactionIcon { ); } - static Widget _wowReactionBuilder( + static Widget _wowBuilder( BuildContext context, bool highlighted, double size, @@ -143,7 +154,7 @@ class StreamReactionIcon { ); } - static Widget _unknownReactionBuilder( + static Widget _unknownBuilder( BuildContext context, bool highlighted, double size, diff --git a/packages/stream_chat_flutter/lib/src/reactions/desktop_reactions_builder.dart b/packages/stream_chat_flutter/lib/src/reactions/desktop_reactions_builder.dart index 390a05c11..f22883356 100644 --- a/packages/stream_chat_flutter/lib/src/reactions/desktop_reactions_builder.dart +++ b/packages/stream_chat_flutter/lib/src/reactions/desktop_reactions_builder.dart @@ -183,8 +183,7 @@ class _BottomReaction extends StatelessWidget { } else if (reactionIcon != null) { StreamChannel.of(context).channel.sendReaction( message, - reactionIcon!.type, - score: reaction.score + 1, + reactionIcon!.toReaction(), enforceUnique: StreamChatConfiguration.of(context).enforceUniqueReactions, ); diff --git a/packages/stream_chat_flutter/lib/src/reactions/picker/reaction_picker_icon_list.dart b/packages/stream_chat_flutter/lib/src/reactions/picker/reaction_picker_icon_list.dart index 5c2a4ad06..0fc775fad 100644 --- a/packages/stream_chat_flutter/lib/src/reactions/picker/reaction_picker_icon_list.dart +++ b/packages/stream_chat_flutter/lib/src/reactions/picker/reaction_picker_icon_list.dart @@ -184,7 +184,7 @@ class _ReactionPickerIconListState extends State { final onPressed = switch (widget.onReactionPicked) { final onPicked? => () { - final picked = reaction ?? Reaction(type: icon.type); + final picked = reaction ?? icon.toReaction(); return onPicked(picked); }, _ => null, diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md index 635916032..adc05069b 100644 --- a/packages/stream_chat_persistence/CHANGELOG.md +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -1,6 +1,7 @@ ## Upcoming Beta - Added support for `Location` entity in the database. +- Added support for `emojiCode` and `updatedAt` fields in `Reaction` entity. ## Upcoming 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 eaca779f8..aa8cd3ef7 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 => 1000 + 23; + int get schemaVersion => 1000 + 24; @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 c8770ea2e..2ec585f13 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 @@ -5905,15 +5905,15 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); @override late final GeneratedColumn userId = GeneratedColumn( - 'user_id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + 'user_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _messageIdMeta = const VerificationMeta('messageId'); @override late final GeneratedColumn messageId = GeneratedColumn( - 'message_id', aliasedName, false, + 'message_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'); @@ -5921,6 +5921,12 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions late final GeneratedColumn type = GeneratedColumn( 'type', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _emojiCodeMeta = + const VerificationMeta('emojiCode'); + @override + late final GeneratedColumn emojiCode = GeneratedColumn( + 'emoji_code', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); @override @@ -5929,6 +5935,14 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions 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); static const VerificationMeta _scoreMeta = const VerificationMeta('score'); @override late final GeneratedColumn score = GeneratedColumn( @@ -5943,8 +5957,16 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions .withConverter?>( $PinnedMessageReactionsTable.$converterextraDatan); @override - List get $columns => - [userId, messageId, type, createdAt, score, extraData]; + List get $columns => [ + userId, + messageId, + type, + emojiCode, + createdAt, + updatedAt, + score, + extraData + ]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -5959,14 +5981,10 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions if (data.containsKey('user_id')) { context.handle(_userIdMeta, userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta)); - } else if (isInserting) { - context.missing(_userIdMeta); } if (data.containsKey('message_id')) { context.handle(_messageIdMeta, messageId.isAcceptableOrUnknown(data['message_id']!, _messageIdMeta)); - } else if (isInserting) { - context.missing(_messageIdMeta); } if (data.containsKey('type')) { context.handle( @@ -5974,10 +5992,18 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions } else if (isInserting) { context.missing(_typeMeta); } + if (data.containsKey('emoji_code')) { + context.handle(_emojiCodeMeta, + emojiCode.isAcceptableOrUnknown(data['emoji_code']!, _emojiCodeMeta)); + } 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('score')) { context.handle( _scoreMeta, score.isAcceptableOrUnknown(data['score']!, _scoreMeta)); @@ -5993,13 +6019,17 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; return PinnedMessageReactionEntity( userId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, + .read(DriftSqlType.string, data['${effectivePrefix}user_id']), messageId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}message_id'])!, + .read(DriftSqlType.string, data['${effectivePrefix}message_id']), type: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + emojiCode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}emoji_code']), createdAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, score: attachedDatabase.typeMapping .read(DriftSqlType.int, data['${effectivePrefix}score'])!, extraData: $PinnedMessageReactionsTable.$converterextraDatan.fromSql( @@ -6022,36 +6052,52 @@ class $PinnedMessageReactionsTable extends PinnedMessageReactions class PinnedMessageReactionEntity extends DataClass implements Insertable { /// The id of the user that sent the reaction - final String userId; + final String? userId; /// The messageId to which the reaction belongs - final String messageId; + final String? messageId; /// The type of the reaction final String type; + /// The emoji code for the reaction + final String? emojiCode; + /// The DateTime on which the reaction is created final DateTime createdAt; + /// The DateTime on which the reaction was last updated + final DateTime updatedAt; + /// The score of the reaction (ie. number of reactions sent) final int score; /// Reaction custom extraData final Map? extraData; const PinnedMessageReactionEntity( - {required this.userId, - required this.messageId, + {this.userId, + this.messageId, required this.type, + this.emojiCode, required this.createdAt, + required this.updatedAt, required this.score, this.extraData}); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['user_id'] = Variable(userId); - map['message_id'] = Variable(messageId); + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + if (!nullToAbsent || messageId != null) { + map['message_id'] = Variable(messageId); + } map['type'] = Variable(type); + if (!nullToAbsent || emojiCode != null) { + map['emoji_code'] = Variable(emojiCode); + } map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); map['score'] = Variable(score); if (!nullToAbsent || extraData != null) { map['extra_data'] = Variable( @@ -6064,10 +6110,12 @@ class PinnedMessageReactionEntity extends DataClass {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return PinnedMessageReactionEntity( - userId: serializer.fromJson(json['userId']), - messageId: serializer.fromJson(json['messageId']), + userId: serializer.fromJson(json['userId']), + messageId: serializer.fromJson(json['messageId']), type: serializer.fromJson(json['type']), + emojiCode: serializer.fromJson(json['emojiCode']), createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), score: serializer.fromJson(json['score']), extraData: serializer.fromJson?>(json['extraData']), ); @@ -6076,27 +6124,33 @@ class PinnedMessageReactionEntity extends DataClass Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'userId': serializer.toJson(userId), - 'messageId': serializer.toJson(messageId), + 'userId': serializer.toJson(userId), + 'messageId': serializer.toJson(messageId), 'type': serializer.toJson(type), + 'emojiCode': serializer.toJson(emojiCode), 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), 'score': serializer.toJson(score), 'extraData': serializer.toJson?>(extraData), }; } PinnedMessageReactionEntity copyWith( - {String? userId, - String? messageId, + {Value userId = const Value.absent(), + Value messageId = const Value.absent(), String? type, + Value emojiCode = const Value.absent(), DateTime? createdAt, + DateTime? updatedAt, int? score, Value?> extraData = const Value.absent()}) => PinnedMessageReactionEntity( - userId: userId ?? this.userId, - messageId: messageId ?? this.messageId, + userId: userId.present ? userId.value : this.userId, + messageId: messageId.present ? messageId.value : this.messageId, type: type ?? this.type, + emojiCode: emojiCode.present ? emojiCode.value : this.emojiCode, createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, score: score ?? this.score, extraData: extraData.present ? extraData.value : this.extraData, ); @@ -6106,7 +6160,9 @@ class PinnedMessageReactionEntity extends DataClass 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, + emojiCode: data.emojiCode.present ? data.emojiCode.value : this.emojiCode, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, score: data.score.present ? data.score.value : this.score, extraData: data.extraData.present ? data.extraData.value : this.extraData, ); @@ -6118,7 +6174,9 @@ class PinnedMessageReactionEntity extends DataClass ..write('userId: $userId, ') ..write('messageId: $messageId, ') ..write('type: $type, ') + ..write('emojiCode: $emojiCode, ') ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') ..write('score: $score, ') ..write('extraData: $extraData') ..write(')')) @@ -6126,8 +6184,8 @@ class PinnedMessageReactionEntity extends DataClass } @override - int get hashCode => - Object.hash(userId, messageId, type, createdAt, score, extraData); + int get hashCode => Object.hash(userId, messageId, type, emojiCode, createdAt, + updatedAt, score, extraData); @override bool operator ==(Object other) => identical(this, other) || @@ -6135,17 +6193,21 @@ class PinnedMessageReactionEntity extends DataClass other.userId == this.userId && other.messageId == this.messageId && other.type == this.type && + other.emojiCode == this.emojiCode && other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && other.score == this.score && other.extraData == this.extraData); } class PinnedMessageReactionsCompanion extends UpdateCompanion { - final Value userId; - final Value messageId; + final Value userId; + final Value messageId; final Value type; + final Value emojiCode; final Value createdAt; + final Value updatedAt; final Value score; final Value?> extraData; final Value rowid; @@ -6153,27 +6215,31 @@ class PinnedMessageReactionsCompanion this.userId = const Value.absent(), this.messageId = const Value.absent(), this.type = const Value.absent(), + this.emojiCode = const Value.absent(), this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.score = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); PinnedMessageReactionsCompanion.insert({ - required String userId, - required String messageId, + this.userId = const Value.absent(), + this.messageId = const Value.absent(), required String type, + this.emojiCode = const Value.absent(), this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.score = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), - }) : userId = Value(userId), - messageId = Value(messageId), - type = Value(type); + }) : type = Value(type); static Insertable custom({ Expression? userId, Expression? messageId, Expression? type, + Expression? emojiCode, Expression? createdAt, + Expression? updatedAt, Expression? score, Expression? extraData, Expression? rowid, @@ -6182,7 +6248,9 @@ class PinnedMessageReactionsCompanion if (userId != null) 'user_id': userId, if (messageId != null) 'message_id': messageId, if (type != null) 'type': type, + if (emojiCode != null) 'emoji_code': emojiCode, if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, if (score != null) 'score': score, if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, @@ -6190,10 +6258,12 @@ class PinnedMessageReactionsCompanion } PinnedMessageReactionsCompanion copyWith( - {Value? userId, - Value? messageId, + {Value? userId, + Value? messageId, Value? type, + Value? emojiCode, Value? createdAt, + Value? updatedAt, Value? score, Value?>? extraData, Value? rowid}) { @@ -6201,7 +6271,9 @@ class PinnedMessageReactionsCompanion userId: userId ?? this.userId, messageId: messageId ?? this.messageId, type: type ?? this.type, + emojiCode: emojiCode ?? this.emojiCode, createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, score: score ?? this.score, extraData: extraData ?? this.extraData, rowid: rowid ?? this.rowid, @@ -6220,9 +6292,15 @@ class PinnedMessageReactionsCompanion if (type.present) { map['type'] = Variable(type.value); } + if (emojiCode.present) { + map['emoji_code'] = Variable(emojiCode.value); + } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } if (score.present) { map['score'] = Variable(score.value); } @@ -6243,7 +6321,9 @@ class PinnedMessageReactionsCompanion ..write('userId: $userId, ') ..write('messageId: $messageId, ') ..write('type: $type, ') + ..write('emojiCode: $emojiCode, ') ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') ..write('score: $score, ') ..write('extraData: $extraData, ') ..write('rowid: $rowid') @@ -6261,15 +6341,15 @@ class $ReactionsTable extends Reactions static const VerificationMeta _userIdMeta = const VerificationMeta('userId'); @override late final GeneratedColumn userId = GeneratedColumn( - 'user_id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + 'user_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _messageIdMeta = const VerificationMeta('messageId'); @override late final GeneratedColumn messageId = GeneratedColumn( - 'message_id', aliasedName, false, + 'message_id', aliasedName, true, type: DriftSqlType.string, - requiredDuringInsert: true, + requiredDuringInsert: false, defaultConstraints: GeneratedColumn.constraintIsAlways( 'REFERENCES messages (id) ON DELETE CASCADE')); static const VerificationMeta _typeMeta = const VerificationMeta('type'); @@ -6277,6 +6357,12 @@ class $ReactionsTable extends Reactions late final GeneratedColumn type = GeneratedColumn( 'type', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _emojiCodeMeta = + const VerificationMeta('emojiCode'); + @override + late final GeneratedColumn emojiCode = GeneratedColumn( + 'emoji_code', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); static const VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); @override @@ -6285,6 +6371,14 @@ class $ReactionsTable extends Reactions 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); static const VerificationMeta _scoreMeta = const VerificationMeta('score'); @override late final GeneratedColumn score = GeneratedColumn( @@ -6299,8 +6393,16 @@ class $ReactionsTable extends Reactions .withConverter?>( $ReactionsTable.$converterextraDatan); @override - List get $columns => - [userId, messageId, type, createdAt, score, extraData]; + List get $columns => [ + userId, + messageId, + type, + emojiCode, + createdAt, + updatedAt, + score, + extraData + ]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -6314,14 +6416,10 @@ class $ReactionsTable extends Reactions if (data.containsKey('user_id')) { context.handle(_userIdMeta, userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta)); - } else if (isInserting) { - context.missing(_userIdMeta); } if (data.containsKey('message_id')) { context.handle(_messageIdMeta, messageId.isAcceptableOrUnknown(data['message_id']!, _messageIdMeta)); - } else if (isInserting) { - context.missing(_messageIdMeta); } if (data.containsKey('type')) { context.handle( @@ -6329,10 +6427,18 @@ class $ReactionsTable extends Reactions } else if (isInserting) { context.missing(_typeMeta); } + if (data.containsKey('emoji_code')) { + context.handle(_emojiCodeMeta, + emojiCode.isAcceptableOrUnknown(data['emoji_code']!, _emojiCodeMeta)); + } 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('score')) { context.handle( _scoreMeta, score.isAcceptableOrUnknown(data['score']!, _scoreMeta)); @@ -6347,13 +6453,17 @@ class $ReactionsTable extends Reactions final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; return ReactionEntity( userId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}user_id'])!, + .read(DriftSqlType.string, data['${effectivePrefix}user_id']), messageId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}message_id'])!, + .read(DriftSqlType.string, data['${effectivePrefix}message_id']), type: attachedDatabase.typeMapping .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + emojiCode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}emoji_code']), createdAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, score: attachedDatabase.typeMapping .read(DriftSqlType.int, data['${effectivePrefix}score'])!, extraData: $ReactionsTable.$converterextraDatan.fromSql(attachedDatabase @@ -6375,36 +6485,52 @@ class $ReactionsTable extends Reactions class ReactionEntity extends DataClass implements Insertable { /// The id of the user that sent the reaction - final String userId; + final String? userId; /// The messageId to which the reaction belongs - final String messageId; + final String? messageId; /// The type of the reaction final String type; + /// The emoji code for the reaction + final String? emojiCode; + /// The DateTime on which the reaction is created final DateTime createdAt; + /// The DateTime on which the reaction was last updated + final DateTime updatedAt; + /// The score of the reaction (ie. number of reactions sent) final int score; /// Reaction custom extraData final Map? extraData; const ReactionEntity( - {required this.userId, - required this.messageId, + {this.userId, + this.messageId, required this.type, + this.emojiCode, required this.createdAt, + required this.updatedAt, required this.score, this.extraData}); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['user_id'] = Variable(userId); - map['message_id'] = Variable(messageId); + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + if (!nullToAbsent || messageId != null) { + map['message_id'] = Variable(messageId); + } map['type'] = Variable(type); + if (!nullToAbsent || emojiCode != null) { + map['emoji_code'] = Variable(emojiCode); + } map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); map['score'] = Variable(score); if (!nullToAbsent || extraData != null) { map['extra_data'] = Variable( @@ -6417,10 +6543,12 @@ class ReactionEntity extends DataClass implements Insertable { {ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return ReactionEntity( - userId: serializer.fromJson(json['userId']), - messageId: serializer.fromJson(json['messageId']), + userId: serializer.fromJson(json['userId']), + messageId: serializer.fromJson(json['messageId']), type: serializer.fromJson(json['type']), + emojiCode: serializer.fromJson(json['emojiCode']), createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), score: serializer.fromJson(json['score']), extraData: serializer.fromJson?>(json['extraData']), ); @@ -6429,27 +6557,33 @@ class ReactionEntity extends DataClass implements Insertable { Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'userId': serializer.toJson(userId), - 'messageId': serializer.toJson(messageId), + 'userId': serializer.toJson(userId), + 'messageId': serializer.toJson(messageId), 'type': serializer.toJson(type), + 'emojiCode': serializer.toJson(emojiCode), 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), 'score': serializer.toJson(score), 'extraData': serializer.toJson?>(extraData), }; } ReactionEntity copyWith( - {String? userId, - String? messageId, + {Value userId = const Value.absent(), + Value messageId = const Value.absent(), String? type, + Value emojiCode = const Value.absent(), DateTime? createdAt, + DateTime? updatedAt, int? score, Value?> extraData = const Value.absent()}) => ReactionEntity( - userId: userId ?? this.userId, - messageId: messageId ?? this.messageId, + userId: userId.present ? userId.value : this.userId, + messageId: messageId.present ? messageId.value : this.messageId, type: type ?? this.type, + emojiCode: emojiCode.present ? emojiCode.value : this.emojiCode, createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, score: score ?? this.score, extraData: extraData.present ? extraData.value : this.extraData, ); @@ -6458,7 +6592,9 @@ class ReactionEntity extends DataClass implements Insertable { 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, + emojiCode: data.emojiCode.present ? data.emojiCode.value : this.emojiCode, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, score: data.score.present ? data.score.value : this.score, extraData: data.extraData.present ? data.extraData.value : this.extraData, ); @@ -6470,7 +6606,9 @@ class ReactionEntity extends DataClass implements Insertable { ..write('userId: $userId, ') ..write('messageId: $messageId, ') ..write('type: $type, ') + ..write('emojiCode: $emojiCode, ') ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') ..write('score: $score, ') ..write('extraData: $extraData') ..write(')')) @@ -6478,8 +6616,8 @@ class ReactionEntity extends DataClass implements Insertable { } @override - int get hashCode => - Object.hash(userId, messageId, type, createdAt, score, extraData); + int get hashCode => Object.hash(userId, messageId, type, emojiCode, createdAt, + updatedAt, score, extraData); @override bool operator ==(Object other) => identical(this, other) || @@ -6487,16 +6625,20 @@ class ReactionEntity extends DataClass implements Insertable { other.userId == this.userId && other.messageId == this.messageId && other.type == this.type && + other.emojiCode == this.emojiCode && other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && other.score == this.score && other.extraData == this.extraData); } class ReactionsCompanion extends UpdateCompanion { - final Value userId; - final Value messageId; + final Value userId; + final Value messageId; final Value type; + final Value emojiCode; final Value createdAt; + final Value updatedAt; final Value score; final Value?> extraData; final Value rowid; @@ -6504,27 +6646,31 @@ class ReactionsCompanion extends UpdateCompanion { this.userId = const Value.absent(), this.messageId = const Value.absent(), this.type = const Value.absent(), + this.emojiCode = const Value.absent(), this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.score = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), }); ReactionsCompanion.insert({ - required String userId, - required String messageId, + this.userId = const Value.absent(), + this.messageId = const Value.absent(), required String type, + this.emojiCode = const Value.absent(), this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), this.score = const Value.absent(), this.extraData = const Value.absent(), this.rowid = const Value.absent(), - }) : userId = Value(userId), - messageId = Value(messageId), - type = Value(type); + }) : type = Value(type); static Insertable custom({ Expression? userId, Expression? messageId, Expression? type, + Expression? emojiCode, Expression? createdAt, + Expression? updatedAt, Expression? score, Expression? extraData, Expression? rowid, @@ -6533,7 +6679,9 @@ class ReactionsCompanion extends UpdateCompanion { if (userId != null) 'user_id': userId, if (messageId != null) 'message_id': messageId, if (type != null) 'type': type, + if (emojiCode != null) 'emoji_code': emojiCode, if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, if (score != null) 'score': score, if (extraData != null) 'extra_data': extraData, if (rowid != null) 'rowid': rowid, @@ -6541,10 +6689,12 @@ class ReactionsCompanion extends UpdateCompanion { } ReactionsCompanion copyWith( - {Value? userId, - Value? messageId, + {Value? userId, + Value? messageId, Value? type, + Value? emojiCode, Value? createdAt, + Value? updatedAt, Value? score, Value?>? extraData, Value? rowid}) { @@ -6552,7 +6702,9 @@ class ReactionsCompanion extends UpdateCompanion { userId: userId ?? this.userId, messageId: messageId ?? this.messageId, type: type ?? this.type, + emojiCode: emojiCode ?? this.emojiCode, createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, score: score ?? this.score, extraData: extraData ?? this.extraData, rowid: rowid ?? this.rowid, @@ -6571,9 +6723,15 @@ class ReactionsCompanion extends UpdateCompanion { if (type.present) { map['type'] = Variable(type.value); } + if (emojiCode.present) { + map['emoji_code'] = Variable(emojiCode.value); + } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } if (score.present) { map['score'] = Variable(score.value); } @@ -6593,7 +6751,9 @@ class ReactionsCompanion extends UpdateCompanion { ..write('userId: $userId, ') ..write('messageId: $messageId, ') ..write('type: $type, ') + ..write('emojiCode: $emojiCode, ') ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') ..write('score: $score, ') ..write('extraData: $extraData, ') ..write('rowid: $rowid') @@ -12876,20 +13036,24 @@ typedef $$PollVotesTableProcessedTableManager = ProcessedTableManager< PrefetchHooks Function({bool pollId})>; typedef $$PinnedMessageReactionsTableCreateCompanionBuilder = PinnedMessageReactionsCompanion Function({ - required String userId, - required String messageId, + Value userId, + Value messageId, required String type, + Value emojiCode, Value createdAt, + Value updatedAt, Value score, Value?> extraData, Value rowid, }); typedef $$PinnedMessageReactionsTableUpdateCompanionBuilder = PinnedMessageReactionsCompanion Function({ - Value userId, - Value messageId, + Value userId, + Value messageId, Value type, + Value emojiCode, Value createdAt, + Value updatedAt, Value score, Value?> extraData, Value rowid, @@ -12906,9 +13070,9 @@ final class $$PinnedMessageReactionsTableReferences extends BaseReferences< db.pinnedMessages.createAlias($_aliasNameGenerator( db.pinnedMessageReactions.messageId, db.pinnedMessages.id)); - $$PinnedMessagesTableProcessedTableManager get messageId { - final $_column = $_itemColumn('message_id')!; - + $$PinnedMessagesTableProcessedTableManager? get messageId { + final $_column = $_itemColumn('message_id'); + if ($_column == null) return null; final manager = $$PinnedMessagesTableTableManager($_db, $_db.pinnedMessages) .filter((f) => f.id.sqlEquals($_column)); final item = $_typedResult.readTableOrNull(_messageIdTable($_db)); @@ -12933,9 +13097,15 @@ class $$PinnedMessageReactionsTableFilterComposer ColumnFilters get type => $composableBuilder( column: $table.type, builder: (column) => ColumnFilters(column)); + ColumnFilters get emojiCode => $composableBuilder( + column: $table.emojiCode, 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 score => $composableBuilder( column: $table.score, builder: (column) => ColumnFilters(column)); @@ -12981,9 +13151,15 @@ class $$PinnedMessageReactionsTableOrderingComposer ColumnOrderings get type => $composableBuilder( column: $table.type, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get emojiCode => $composableBuilder( + column: $table.emojiCode, 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 score => $composableBuilder( column: $table.score, builder: (column) => ColumnOrderings(column)); @@ -13026,9 +13202,15 @@ class $$PinnedMessageReactionsTableAnnotationComposer GeneratedColumn get type => $composableBuilder(column: $table.type, builder: (column) => column); + GeneratedColumn get emojiCode => + $composableBuilder(column: $table.emojiCode, 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 score => $composableBuilder(column: $table.score, builder: (column) => column); @@ -13084,10 +13266,12 @@ class $$PinnedMessageReactionsTableTableManager extends RootTableManager< $$PinnedMessageReactionsTableAnnotationComposer( $db: db, $table: table), updateCompanionCallback: ({ - Value userId = const Value.absent(), - Value messageId = const Value.absent(), + Value userId = const Value.absent(), + Value messageId = const Value.absent(), Value type = const Value.absent(), + Value emojiCode = const Value.absent(), Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), Value score = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), @@ -13096,16 +13280,20 @@ class $$PinnedMessageReactionsTableTableManager extends RootTableManager< userId: userId, messageId: messageId, type: type, + emojiCode: emojiCode, createdAt: createdAt, + updatedAt: updatedAt, score: score, extraData: extraData, rowid: rowid, ), createCompanionCallback: ({ - required String userId, - required String messageId, + Value userId = const Value.absent(), + Value messageId = const Value.absent(), required String type, + Value emojiCode = const Value.absent(), Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), Value score = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), @@ -13114,7 +13302,9 @@ class $$PinnedMessageReactionsTableTableManager extends RootTableManager< userId: userId, messageId: messageId, type: type, + emojiCode: emojiCode, createdAt: createdAt, + updatedAt: updatedAt, score: score, extraData: extraData, rowid: rowid, @@ -13178,19 +13368,23 @@ typedef $$PinnedMessageReactionsTableProcessedTableManager PinnedMessageReactionEntity, PrefetchHooks Function({bool messageId})>; typedef $$ReactionsTableCreateCompanionBuilder = ReactionsCompanion Function({ - required String userId, - required String messageId, + Value userId, + Value messageId, required String type, + Value emojiCode, Value createdAt, + Value updatedAt, Value score, Value?> extraData, Value rowid, }); typedef $$ReactionsTableUpdateCompanionBuilder = ReactionsCompanion Function({ - Value userId, - Value messageId, + Value userId, + Value messageId, Value type, + Value emojiCode, Value createdAt, + Value updatedAt, Value score, Value?> extraData, Value rowid, @@ -13204,9 +13398,9 @@ final class $$ReactionsTableReferences extends BaseReferences< db.messages.createAlias( $_aliasNameGenerator(db.reactions.messageId, db.messages.id)); - $$MessagesTableProcessedTableManager get messageId { - final $_column = $_itemColumn('message_id')!; - + $$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)); @@ -13231,9 +13425,15 @@ class $$ReactionsTableFilterComposer ColumnFilters get type => $composableBuilder( column: $table.type, builder: (column) => ColumnFilters(column)); + ColumnFilters get emojiCode => $composableBuilder( + column: $table.emojiCode, 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 score => $composableBuilder( column: $table.score, builder: (column) => ColumnFilters(column)); @@ -13279,9 +13479,15 @@ class $$ReactionsTableOrderingComposer ColumnOrderings get type => $composableBuilder( column: $table.type, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get emojiCode => $composableBuilder( + column: $table.emojiCode, 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 score => $composableBuilder( column: $table.score, builder: (column) => ColumnOrderings(column)); @@ -13324,9 +13530,15 @@ class $$ReactionsTableAnnotationComposer GeneratedColumn get type => $composableBuilder(column: $table.type, builder: (column) => column); + GeneratedColumn get emojiCode => + $composableBuilder(column: $table.emojiCode, 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 score => $composableBuilder(column: $table.score, builder: (column) => column); @@ -13378,10 +13590,12 @@ class $$ReactionsTableTableManager extends RootTableManager< createComputedFieldComposer: () => $$ReactionsTableAnnotationComposer($db: db, $table: table), updateCompanionCallback: ({ - Value userId = const Value.absent(), - Value messageId = const Value.absent(), + Value userId = const Value.absent(), + Value messageId = const Value.absent(), Value type = const Value.absent(), + Value emojiCode = const Value.absent(), Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), Value score = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), @@ -13390,16 +13604,20 @@ class $$ReactionsTableTableManager extends RootTableManager< userId: userId, messageId: messageId, type: type, + emojiCode: emojiCode, createdAt: createdAt, + updatedAt: updatedAt, score: score, extraData: extraData, rowid: rowid, ), createCompanionCallback: ({ - required String userId, - required String messageId, + Value userId = const Value.absent(), + Value messageId = const Value.absent(), required String type, + Value emojiCode = const Value.absent(), Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent(), Value score = const Value.absent(), Value?> extraData = const Value.absent(), Value rowid = const Value.absent(), @@ -13408,7 +13626,9 @@ class $$ReactionsTableTableManager extends RootTableManager< userId: userId, messageId: messageId, type: type, + emojiCode: emojiCode, createdAt: createdAt, + updatedAt: updatedAt, score: score, extraData: extraData, rowid: rowid, diff --git a/packages/stream_chat_persistence/lib/src/entity/pinned_message_reactions.dart b/packages/stream_chat_persistence/lib/src/entity/pinned_message_reactions.dart index e4c9b06e5..6e490cf8f 100644 --- a/packages/stream_chat_persistence/lib/src/entity/pinned_message_reactions.dart +++ b/packages/stream_chat_persistence/lib/src/entity/pinned_message_reactions.dart @@ -8,6 +8,7 @@ import 'package:stream_chat_persistence/src/entity/reactions.dart'; class PinnedMessageReactions extends Reactions { /// The messageId to which the reaction belongs @override - TextColumn get messageId => - text().references(PinnedMessages, #id, onDelete: KeyAction.cascade)(); + TextColumn get messageId => text() + .nullable() + .references(PinnedMessages, #id, onDelete: KeyAction.cascade)(); } diff --git a/packages/stream_chat_persistence/lib/src/entity/reactions.dart b/packages/stream_chat_persistence/lib/src/entity/reactions.dart index 39bf42589..64d23bf97 100644 --- a/packages/stream_chat_persistence/lib/src/entity/reactions.dart +++ b/packages/stream_chat_persistence/lib/src/entity/reactions.dart @@ -7,18 +7,25 @@ import 'package:stream_chat_persistence/src/entity/messages.dart'; @DataClassName('ReactionEntity') class Reactions extends Table { /// The id of the user that sent the reaction - TextColumn get userId => text()(); + TextColumn get userId => text().nullable()(); /// The messageId to which the reaction belongs - TextColumn get messageId => - text().references(Messages, #id, onDelete: KeyAction.cascade)(); + TextColumn get messageId => text() + .nullable() + .references(Messages, #id, onDelete: KeyAction.cascade)(); /// The type of the reaction TextColumn get type => text()(); + /// The emoji code for the reaction + TextColumn get emojiCode => text().nullable()(); + /// The DateTime on which the reaction is created DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); + /// The DateTime on which the reaction was last updated + DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); + /// The score of the reaction (ie. number of reactions sent) IntColumn get score => integer().withDefault(const Constant(0))(); diff --git a/packages/stream_chat_persistence/lib/src/mapper/pinned_message_reaction_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/pinned_message_reaction_mapper.dart index ecab7cb40..00deda65d 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/pinned_message_reaction_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/pinned_message_reaction_mapper.dart @@ -5,13 +5,15 @@ import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; extension PinnedMessageReactionEntityX on PinnedMessageReactionEntity { /// Maps a [PinnedMessageReactionEntity] into [Reaction] Reaction toReaction({User? user}) => Reaction( - extraData: extraData ?? {}, type: type, - createdAt: createdAt, userId: userId, user: user, messageId: messageId, score: score, + emojiCode: emojiCode, + createdAt: createdAt, + updatedAt: updatedAt, + extraData: extraData ?? {}, ); } @@ -19,11 +21,13 @@ extension PinnedMessageReactionEntityX on PinnedMessageReactionEntity { extension PReactionX on Reaction { /// Maps a [Reaction] into [ReactionEntity] PinnedMessageReactionEntity toPinnedEntity() => PinnedMessageReactionEntity( - extraData: extraData, type: type, - createdAt: createdAt, - userId: userId!, - messageId: messageId!, + userId: userId ?? user?.id, + messageId: messageId, score: score, + emojiCode: emojiCode, + createdAt: createdAt, + updatedAt: updatedAt, + extraData: extraData, ); } diff --git a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart index a524fafe1..81b2bd441 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/reaction_mapper.dart @@ -5,13 +5,15 @@ import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; extension ReactionEntityX on ReactionEntity { /// Maps a [ReactionEntity] into [Reaction] Reaction toReaction({User? user}) => Reaction( - extraData: extraData ?? {}, type: type, - createdAt: createdAt, userId: userId, user: user, messageId: messageId, score: score, + emojiCode: emojiCode, + createdAt: createdAt, + updatedAt: updatedAt, + extraData: extraData ?? {}, ); } @@ -19,11 +21,13 @@ extension ReactionEntityX on ReactionEntity { extension ReactionX on Reaction { /// Maps a [Reaction] into [ReactionEntity] ReactionEntity toEntity() => ReactionEntity( - extraData: extraData, type: type, - createdAt: createdAt, - userId: userId!, - messageId: messageId!, + userId: userId ?? user?.id, + messageId: messageId, score: score, + emojiCode: emojiCode, + createdAt: createdAt, + updatedAt: updatedAt, + extraData: extraData, ); } diff --git a/packages/stream_chat_persistence/test/src/dao/pinned_message_reaction_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/pinned_message_reaction_dao_test.dart index 44abc4a64..57482c431 100644 --- a/packages/stream_chat_persistence/test/src/dao/pinned_message_reaction_dao_test.dart +++ b/packages/stream_chat_persistence/test/src/dao/pinned_message_reaction_dao_test.dart @@ -6,6 +6,7 @@ import 'package:stream_chat_persistence/src/dao/pinned_message_reaction_dao.dart import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; import '../../stream_chat_persistence_client_test.dart'; +import '../utils/date_matcher.dart'; void main() { late PinnedMessageReactionDao pinnedMessageReactionDao; @@ -39,16 +40,23 @@ void main() { pinnedAt: DateTime.now(), pinnedBy: users.first, ); + + final now = DateTime.now(); final reactions = List.generate( count, - (index) => Reaction( - type: 'testType$index', - createdAt: DateTime.now(), - userId: userId ?? users[index].id, - messageId: message.id, - score: count + 3, - extraData: {'extra_test_field': 'extraTestData'}, - ), + (index) { + final createdAt = now.add(Duration(minutes: index)); + return Reaction( + type: 'testType$index', + createdAt: createdAt, + updatedAt: createdAt.add(const Duration(minutes: 5)), + userId: userId ?? users[index].id, + messageId: message.id, + score: count + 3, + emojiCode: '๐Ÿ˜‚$index', + extraData: const {'extra_test_field': 'extraTestData'}, + ); + }, ); await database.userDao.updateUsers(users); @@ -76,6 +84,14 @@ void main() { await pinnedMessageReactionDao.getReactions(messageId); expect(fetchedReactions.length, insertedReactions.length); expect(fetchedReactions.every((it) => it.messageId == messageId), true); + + // Verify score and emojiCode are preserved + for (var i = 0; i < fetchedReactions.length; i++) { + final inserted = insertedReactions[i]; + final fetched = fetchedReactions[i]; + expect(fetched.score, inserted.score); + expect(fetched.emojiCode, inserted.emojiCode); + } }); test('getReactionsByUserId', () async { @@ -100,6 +116,14 @@ void main() { expect(fetchedReactions.length, insertedReactions.length); expect(fetchedReactions.every((it) => it.messageId == messageId), true); expect(fetchedReactions.every((it) => it.userId == userId), true); + + // Verify score and emojiCode are preserved + for (var i = 0; i < fetchedReactions.length; i++) { + final inserted = insertedReactions[i]; + final fetched = fetchedReactions[i]; + expect(fetched.score, inserted.score); + expect(fetched.emojiCode, inserted.emojiCode); + } }); test('updateReactions', () async { @@ -109,37 +133,46 @@ void main() { final reactions = await _prepareReactionData(messageId); // Modifying one of the reaction and also adding one new - final copyReaction = reactions.first.copyWith(score: 33); + final now = DateTime.now(); + final copyReaction = reactions.first.copyWith( + score: 33, + emojiCode: '๐ŸŽ‰', + updatedAt: now, + ); final newReaction = Reaction( type: 'testType3', - createdAt: DateTime.now(), + createdAt: now, + updatedAt: now.add(const Duration(minutes: 5)), userId: 'testUserId3', messageId: messageId, score: 30, - extraData: {'extra_test_field': 'extraTestData'}, + emojiCode: '๐ŸŽˆ', + extraData: const {'extra_test_field': 'extraTestData'}, ); await pinnedMessageReactionDao.updateReactions([copyReaction, newReaction]); // Fetched reaction length should be one more than inserted reactions. - // copyReaction `score` modified field should be 33. + // copyReaction modified fields should match // Fetched reactions should contain the newReaction. final fetchedReactions = await pinnedMessageReactionDao.getReactions(messageId); expect(fetchedReactions.length, reactions.length + 1); - expect( - fetchedReactions - .firstWhere((it) => - it.userId == copyReaction.userId && it.type == copyReaction.type) - .score, - 33, + + final fetchedCopyReaction = fetchedReactions.firstWhere( + (it) => it.userId == copyReaction.userId && it.type == copyReaction.type, ); + expect(fetchedCopyReaction.score, 33); + expect(fetchedCopyReaction.emojiCode, '๐ŸŽ‰'); + expect(fetchedCopyReaction.updatedAt, isSameDateAs(now)); + + final fetchedNewReaction = fetchedReactions.firstWhere( + (it) => it.userId == newReaction.userId && it.type == newReaction.type, + ); + expect(fetchedNewReaction.emojiCode, '๐ŸŽˆ'); expect( - fetchedReactions - .where((it) => - it.userId == newReaction.userId && it.type == newReaction.type) - .isNotEmpty, - true, + fetchedNewReaction.updatedAt, + isSameDateAs(now.add(const Duration(minutes: 5))), ); }); @@ -171,7 +204,8 @@ void main() { expect(fetchedReactions1, isEmpty); expect(fetchedReactions2, isNotEmpty); }); - test('should delete all the messages of both message', () async { + + test('should delete all the reactions of both message', () async { // Preparing test data final insertedReactions1 = await _prepareReactionData(messageId1); final insertedReactions2 = await _prepareReactionData(messageId2); diff --git a/packages/stream_chat_persistence/test/src/dao/reaction_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/reaction_dao_test.dart index 7fa3569e4..ddd01f09f 100644 --- a/packages/stream_chat_persistence/test/src/dao/reaction_dao_test.dart +++ b/packages/stream_chat_persistence/test/src/dao/reaction_dao_test.dart @@ -6,6 +6,7 @@ import 'package:stream_chat_persistence/src/dao/reaction_dao.dart'; import 'package:stream_chat_persistence/src/db/drift_chat_database.dart'; import '../../stream_chat_persistence_client_test.dart'; +import '../utils/date_matcher.dart'; void main() { late ReactionDao reactionDao; @@ -39,16 +40,23 @@ void main() { pinnedAt: DateTime.now(), pinnedBy: users.first, ); + + final now = DateTime.now(); final reactions = List.generate( count, - (index) => Reaction( - type: 'testType$index', - createdAt: DateTime.now(), - userId: userId ?? users[index].id, - messageId: message.id, - score: count + 3, - extraData: {'extra_test_field': 'extraTestData'}, - ), + (index) { + final createdAt = now.add(Duration(minutes: index)); + return Reaction( + type: 'testType$index', + createdAt: createdAt, + updatedAt: createdAt.add(const Duration(minutes: 5)), + userId: userId ?? users[index].id, + messageId: message.id, + score: count + 3, + emojiCode: '๐Ÿ˜‚$index', + extraData: const {'extra_test_field': 'extraTestData'}, + ); + }, ); await database.userDao.updateUsers(users); @@ -75,6 +83,14 @@ void main() { final fetchedReactions = await reactionDao.getReactions(messageId); expect(fetchedReactions.length, insertedReactions.length); expect(fetchedReactions.every((it) => it.messageId == messageId), true); + + // Verify score and emojiCode are preserved + for (var i = 0; i < fetchedReactions.length; i++) { + final inserted = insertedReactions[i]; + final fetched = fetchedReactions[i]; + expect(fetched.score, inserted.score); + expect(fetched.emojiCode, inserted.emojiCode); + } }); test('getReactionsByUserId', () async { @@ -98,6 +114,14 @@ void main() { expect(fetchedReactions.length, insertedReactions.length); expect(fetchedReactions.every((it) => it.messageId == messageId), true); expect(fetchedReactions.every((it) => it.userId == userId), true); + + // Verify score and emojiCode are preserved + for (var i = 0; i < fetchedReactions.length; i++) { + final inserted = insertedReactions[i]; + final fetched = fetchedReactions[i]; + expect(fetched.score, inserted.score); + expect(fetched.emojiCode, inserted.emojiCode); + } }); test('updateReactions', () async { @@ -107,36 +131,45 @@ void main() { final reactions = await _prepareReactionData(messageId); // Modifying one of the reaction and also adding one new - final copyReaction = reactions.first.copyWith(score: 33); + final now = DateTime.now(); + final copyReaction = reactions.first.copyWith( + score: 33, + emojiCode: '๐ŸŽ‰', + updatedAt: now, + ); final newReaction = Reaction( type: 'testType3', - createdAt: DateTime.now(), + createdAt: now, + updatedAt: now.add(const Duration(minutes: 5)), userId: 'testUserId3', messageId: messageId, score: 30, - extraData: {'extra_test_field': 'extraTestData'}, + emojiCode: '๐ŸŽˆ', + extraData: const {'extra_test_field': 'extraTestData'}, ); await reactionDao.updateReactions([copyReaction, newReaction]); // Fetched reaction length should be one more than inserted reactions. - // copyReaction `score` modified field should be 33. + // copyReaction modified fields should match // Fetched reactions should contain the newReaction. final fetchedReactions = await reactionDao.getReactions(messageId); expect(fetchedReactions.length, reactions.length + 1); - expect( - fetchedReactions - .firstWhere((it) => - it.userId == copyReaction.userId && it.type == copyReaction.type) - .score, - 33, + + final fetchedCopyReaction = fetchedReactions.firstWhere( + (it) => it.userId == copyReaction.userId && it.type == copyReaction.type, ); + expect(fetchedCopyReaction.score, 33); + expect(fetchedCopyReaction.emojiCode, '๐ŸŽ‰'); + expect(fetchedCopyReaction.updatedAt, isSameDateAs(now)); + + final fetchedNewReaction = fetchedReactions.firstWhere( + (it) => it.userId == newReaction.userId && it.type == newReaction.type, + ); + expect(fetchedNewReaction.emojiCode, '๐ŸŽˆ'); expect( - fetchedReactions - .where((it) => - it.userId == newReaction.userId && it.type == newReaction.type) - .isNotEmpty, - true, + fetchedNewReaction.updatedAt, + isSameDateAs(now.add(const Duration(minutes: 5))), ); }); @@ -164,6 +197,7 @@ void main() { expect(fetchedReactions1, isEmpty); expect(fetchedReactions2, isNotEmpty); }); + test('should delete all the reactions of both message', () async { // Preparing test data final insertedReactions1 = await _prepareReactionData(messageId1); diff --git a/packages/stream_chat_persistence/test/src/mapper/pinned_message_reaction_mapper_test.dart b/packages/stream_chat_persistence/test/src/mapper/pinned_message_reaction_mapper_test.dart index 2753f4f4c..d2b4a6709 100644 --- a/packages/stream_chat_persistence/test/src/mapper/pinned_message_reaction_mapper_test.dart +++ b/packages/stream_chat_persistence/test/src/mapper/pinned_message_reaction_mapper_test.dart @@ -9,12 +9,15 @@ void main() { test('toReaction should map the entity into Reaction', () { final user = User(id: 'testUserId'); final message = Message(id: 'testMessageId'); + final now = DateTime.now(); final entity = PinnedMessageReactionEntity( userId: user.id, messageId: message.id, type: 'haha', score: 33, - createdAt: DateTime.now(), + emojiCode: '๐Ÿ˜‚', + createdAt: now, + updatedAt: now.add(const Duration(minutes: 5)), extraData: {'extra_test_data': 'extraData'}, ); @@ -24,20 +27,25 @@ void main() { expect(reaction.messageId, entity.messageId); expect(reaction.type, entity.type); expect(reaction.score, entity.score); + expect(reaction.emojiCode, entity.emojiCode); expect(reaction.createdAt, isSameDateAs(entity.createdAt)); + expect(reaction.updatedAt, isSameDateAs(entity.updatedAt)); expect(reaction.extraData, entity.extraData); }); test('toEntity should map reaction into PinnedMessageReactionEntity', () { final user = User(id: 'testUserId'); final message = Message(id: 'testMessageId'); + final now = DateTime.now(); final reaction = Reaction( userId: user.id, messageId: message.id, type: 'haha', score: 33, - createdAt: DateTime.now(), - extraData: {'extra_test_data': 'extraData'}, + emojiCode: '๐Ÿ˜‚', + createdAt: now, + updatedAt: now.add(const Duration(minutes: 5)), + extraData: const {'extra_test_data': 'extraData'}, ); final entity = reaction.toPinnedEntity(); @@ -46,7 +54,9 @@ void main() { expect(entity.messageId, reaction.messageId); expect(entity.type, reaction.type); expect(entity.score, reaction.score); + expect(entity.emojiCode, reaction.emojiCode); expect(entity.createdAt, isSameDateAs(reaction.createdAt)); + expect(entity.updatedAt, isSameDateAs(reaction.updatedAt)); expect(entity.extraData, reaction.extraData); }); } diff --git a/packages/stream_chat_persistence/test/src/mapper/reaction_mapper_test.dart b/packages/stream_chat_persistence/test/src/mapper/reaction_mapper_test.dart index 844eb3b86..43a3b93cf 100644 --- a/packages/stream_chat_persistence/test/src/mapper/reaction_mapper_test.dart +++ b/packages/stream_chat_persistence/test/src/mapper/reaction_mapper_test.dart @@ -9,12 +9,15 @@ void main() { test('toReaction should map the entity into Reaction', () { final user = User(id: 'testUserId'); final message = Message(id: 'testMessageId'); + final now = DateTime.now(); final entity = ReactionEntity( userId: user.id, messageId: message.id, type: 'haha', score: 33, - createdAt: DateTime.now(), + emojiCode: '๐Ÿ˜‚', + createdAt: now, + updatedAt: now.add(const Duration(minutes: 5)), extraData: {'extra_test_data': 'extraData'}, ); @@ -24,20 +27,25 @@ void main() { expect(reaction.messageId, entity.messageId); expect(reaction.type, entity.type); expect(reaction.score, entity.score); + expect(reaction.emojiCode, entity.emojiCode); expect(reaction.createdAt, isSameDateAs(entity.createdAt)); + expect(reaction.updatedAt, isSameDateAs(entity.updatedAt)); expect(reaction.extraData, entity.extraData); }); test('toEntity should map reaction into ReactionEntity', () { final user = User(id: 'testUserId'); final message = Message(id: 'testMessageId'); + final now = DateTime.now(); final reaction = Reaction( userId: user.id, messageId: message.id, type: 'haha', score: 33, - createdAt: DateTime.now(), - extraData: {'extra_test_data': 'extraData'}, + emojiCode: '๐Ÿ˜‚', + createdAt: now, + updatedAt: now.add(const Duration(minutes: 5)), + extraData: const {'extra_test_data': 'extraData'}, ); final entity = reaction.toEntity(); @@ -46,7 +54,9 @@ void main() { expect(entity.messageId, reaction.messageId); expect(entity.type, reaction.type); expect(entity.score, reaction.score); + expect(entity.emojiCode, reaction.emojiCode); expect(entity.createdAt, isSameDateAs(reaction.createdAt)); + expect(entity.updatedAt, isSameDateAs(reaction.updatedAt)); expect(entity.extraData, reaction.extraData); }); }