Merge branch 'develop' into feat/filters
This commit is contained in:
@@ -1,4 +1,14 @@
|
||||
## Upcoming
|
||||
## Upcoming
|
||||
|
||||
🛑️ Breaking Changes from `2.2.1`
|
||||
|
||||
- Added 6 new methods in `ChatPersistenceClient`.
|
||||
- `bulkUpdateMessages`
|
||||
- `bulkUpdatePinnedMessages`
|
||||
- `bulkUpdateMembers`
|
||||
- `bulkUpdateReads`
|
||||
- `updatePinnedMessageReactions`
|
||||
- `deletePinnedMessageReactionsByMessageId`
|
||||
|
||||
✅ Added
|
||||
|
||||
@@ -19,11 +29,16 @@
|
||||
|
||||
✅ Added
|
||||
|
||||
- `User` and `OwnUser` classes now have an `image` property. Setting an image will also set the 'image' key on `extraData`, so `user.image` and `user.extraData['image']` is the same.
|
||||
- `User` and `OwnUser` classes now have a `name` property. Setting a name will also set the 'name' key on `extraData`, so `user.name` and `user.extraData['name']` is the same.
|
||||
- `Channel` class now has extra `image` getter and setter. As well as an `updateImage` to do a partial update after a channel has been initialized.
|
||||
- `Channel` class now has extra `name` getter and setter. As well as an `updateName` to do a partial update after a channel has been initialized.
|
||||
- `User` and `OwnUser` classes now have an `image` property. Setting an image will also set the 'image' key
|
||||
on `extraData`, so `user.image` and `user.extraData['image']` is the same.
|
||||
- `User` and `OwnUser` classes now have a `name` property. Setting a name will also set the 'name' key on `extraData`,
|
||||
so `user.name` and `user.extraData['name']` is the same.
|
||||
- `Channel` class now has extra `image` getter and setter. As well as an `updateImage` to do a partial update after a
|
||||
channel has been initialized.
|
||||
- `Channel` class now has extra `name` getter and setter. As well as an `updateName` to do a partial update after a
|
||||
channel has been initialized.
|
||||
- Added slow mode which allows a cooldown period after a user sends a message.
|
||||
|
||||
## 2.1.1
|
||||
|
||||
🐞 Fixed
|
||||
@@ -48,7 +63,7 @@
|
||||
|
||||
🐞 Fixed
|
||||
|
||||
- [#563](https://github.com/GetStream/stream-chat-flutter/issues/563): `Channel.stopWatching()` not working
|
||||
- [#563](https://github.com/GetStream/stream-chat-flutter/issues/563): `Channel.stopWatching()` not working
|
||||
- [#575](https://github.com/GetStream/stream-chat-flutter/issues/575): Wrong `OwnUser.*`
|
||||
|
||||
## 2.0.0
|
||||
@@ -76,11 +91,11 @@
|
||||
|
||||
🐞 Fixed
|
||||
|
||||
- [#369](https://github.com/GetStream/stream-chat-flutter/issues/369): Client does not return without internet connection
|
||||
- [#369](https://github.com/GetStream/stream-chat-flutter/issues/369): Client does not return without internet
|
||||
connection
|
||||
- several minor fixes
|
||||
- performance improvements
|
||||
|
||||
|
||||
✅ Added
|
||||
|
||||
- New `Location` enum is introduced for easily changing the client location/baseUrl.
|
||||
@@ -95,6 +110,7 @@
|
||||
## 2.0.0-nullsafety.8
|
||||
|
||||
🐞 Fixed
|
||||
|
||||
- Export `PushProvider` enum
|
||||
|
||||
## 2.0.0-nullsafety.7
|
||||
@@ -130,6 +146,7 @@
|
||||
|
||||
- Fix thread reply not working with attachments
|
||||
- Minor fixes
|
||||
|
||||
## 2.0.0-nullsafety.5
|
||||
|
||||
- Minor fixes
|
||||
|
||||
@@ -143,11 +143,19 @@ abstract class ChatPersistenceClient {
|
||||
|
||||
/// Updates the message data of a particular channel [cid] with
|
||||
/// the new [messages] data
|
||||
Future<void> updateMessages(String cid, List<Message> messages);
|
||||
Future<void> updateMessages(String cid, List<Message> messages) =>
|
||||
bulkUpdateMessages({cid: messages});
|
||||
|
||||
/// Bulk updates the message data of multiple channels.
|
||||
Future<void> bulkUpdateMessages(Map<String, List<Message>> messages);
|
||||
|
||||
/// Updates the pinned message data of a particular channel [cid] with
|
||||
/// the new [messages] data
|
||||
Future<void> updatePinnedMessages(String cid, List<Message> messages);
|
||||
Future<void> updatePinnedMessages(String cid, List<Message> messages) =>
|
||||
bulkUpdatePinnedMessages({cid: messages});
|
||||
|
||||
/// Bulk updates the message data of multiple channels.
|
||||
Future<void> bulkUpdatePinnedMessages(Map<String, List<Message>> messages);
|
||||
|
||||
/// Returns all the threads by parent message of a particular channel by
|
||||
/// providing channel [cid]
|
||||
@@ -158,11 +166,19 @@ abstract class ChatPersistenceClient {
|
||||
|
||||
/// Updates all the members of a particular channle [cid]
|
||||
/// with the new [members] data
|
||||
Future<void> updateMembers(String cid, List<Member> members);
|
||||
Future<void> updateMembers(String cid, List<Member> members) =>
|
||||
bulkUpdateMembers({cid: members});
|
||||
|
||||
/// Bulk updates the members data of multiple channels.
|
||||
Future<void> bulkUpdateMembers(Map<String, List<Member>> members);
|
||||
|
||||
/// Updates the read data of a particular channel [cid] with
|
||||
/// the new [reads] data
|
||||
Future<void> updateReads(String cid, List<Read> reads);
|
||||
Future<void> updateReads(String cid, List<Read> reads) =>
|
||||
bulkUpdateReads({cid: reads});
|
||||
|
||||
/// Bulk updates the read data of multiple channels.
|
||||
Future<void> bulkUpdateReads(Map<String, List<Read>> reads);
|
||||
|
||||
/// Updates the users data with the new [users] data
|
||||
Future<void> updateUsers(List<User> users);
|
||||
@@ -170,9 +186,15 @@ abstract class ChatPersistenceClient {
|
||||
/// Updates the reactions data with the new [reactions] data
|
||||
Future<void> updateReactions(List<Reaction> reactions);
|
||||
|
||||
/// Updates the pinned message reactions data with the new [reactions] data
|
||||
Future<void> updatePinnedMessageReactions(List<Reaction> reactions);
|
||||
|
||||
/// Deletes all the reactions by [messageIds]
|
||||
Future<void> deleteReactionsByMessageId(List<String> messageIds);
|
||||
|
||||
/// Deletes all the pinned messages reactions by [messageIds]
|
||||
Future<void> deletePinnedMessageReactionsByMessageId(List<String> messageIds);
|
||||
|
||||
/// Deletes all the members by channel [cids]
|
||||
Future<void> deleteMembersByCids(List<String> cids);
|
||||
|
||||
@@ -182,85 +204,92 @@ abstract class ChatPersistenceClient {
|
||||
|
||||
/// Update list of channel states
|
||||
Future<void> updateChannelStates(List<ChannelState> channelStates) async {
|
||||
final deleteReactions = deleteReactionsByMessageId(channelStates
|
||||
.expand((it) => it.messages)
|
||||
.map((m) => m.id)
|
||||
.toList(growable: false));
|
||||
final reactionsToDelete = <String>[];
|
||||
final pinnedReactionsToDelete = <String>[];
|
||||
final membersToDelete = <String>[];
|
||||
|
||||
final cleanedChannelStates =
|
||||
channelStates.where((it) => it.channel != null);
|
||||
final channels = <ChannelModel>[];
|
||||
final channelWithMessages = <String, List<Message>>{};
|
||||
final channelWithPinnedMessages = <String, List<Message>>{};
|
||||
final channelWithReads = <String, List<Read>>{};
|
||||
final channelWithMembers = <String, List<Member>>{};
|
||||
|
||||
final deleteMembers = deleteMembersByCids(
|
||||
cleanedChannelStates.map((it) => it.channel!.cid).toList(growable: false),
|
||||
);
|
||||
final users = <User>[];
|
||||
final reactions = <Reaction>[];
|
||||
final pinnedReactions = <Reaction>[];
|
||||
|
||||
for (final state in channelStates) {
|
||||
final channel = state.channel;
|
||||
if (channel != null) {
|
||||
channels.add(channel);
|
||||
|
||||
final cid = channel.cid;
|
||||
final reads = state.read;
|
||||
final members = state.members;
|
||||
final messages = state.messages;
|
||||
final pinnedMessages = state.pinnedMessages;
|
||||
|
||||
// Preparing deletion data
|
||||
membersToDelete.add(cid);
|
||||
reactionsToDelete.addAll(state.messages.map((it) => it.id));
|
||||
pinnedReactionsToDelete.addAll(state.pinnedMessages.map((it) => it.id));
|
||||
|
||||
// preparing addition data
|
||||
channelWithReads[cid] = reads;
|
||||
channelWithMembers[cid] = members;
|
||||
channelWithMessages[cid] = messages;
|
||||
channelWithPinnedMessages[cid] = pinnedMessages;
|
||||
|
||||
List<Reaction> expandReactions(Message message) {
|
||||
final own = message.ownReactions;
|
||||
final latest = message.latestReactions;
|
||||
return [
|
||||
if (own != null) ...own.where((r) => r.userId != null),
|
||||
if (latest != null) ...latest.where((r) => r.userId != null),
|
||||
];
|
||||
}
|
||||
|
||||
reactions.addAll(messages.expand(expandReactions));
|
||||
pinnedReactions.addAll(pinnedMessages.expand(expandReactions));
|
||||
|
||||
users.addAll([
|
||||
channel.createdBy,
|
||||
...reads.map((it) => it.user),
|
||||
...members.map((it) => it.user),
|
||||
...reactions.map((it) => it.user),
|
||||
...pinnedReactions.map((it) => it.user),
|
||||
].withNullifyer);
|
||||
}
|
||||
}
|
||||
|
||||
// Removing old members and reactions data as they may have
|
||||
// changes over the time.
|
||||
await Future.wait([
|
||||
deleteReactions,
|
||||
deleteMembers,
|
||||
deleteMembersByCids(membersToDelete),
|
||||
deleteReactionsByMessageId(reactionsToDelete),
|
||||
deletePinnedMessageReactionsByMessageId(pinnedReactionsToDelete),
|
||||
]);
|
||||
|
||||
final channels = cleanedChannelStates.map((it) => it.channel).withNullifyer;
|
||||
|
||||
final reactions = cleanedChannelStates
|
||||
.expand((it) => it.messages)
|
||||
.expand((it) => [
|
||||
if (it.ownReactions != null)
|
||||
...it.ownReactions!.where((r) => r.userId != null),
|
||||
if (it.latestReactions != null)
|
||||
...it.latestReactions!.where((r) => r.userId != null),
|
||||
])
|
||||
.withNullifyer;
|
||||
|
||||
final users = cleanedChannelStates
|
||||
.map((cs) => [
|
||||
cs.channel?.createdBy,
|
||||
...cs.messages
|
||||
.map((m) => [
|
||||
m.user,
|
||||
if (m.latestReactions != null)
|
||||
...m.latestReactions!.map((r) => r.user),
|
||||
if (m.ownReactions != null)
|
||||
...m.ownReactions!.map((r) => r.user),
|
||||
])
|
||||
.expand((v) => v),
|
||||
...cs.read.map((r) => r.user),
|
||||
...cs.members.map((m) => m.user),
|
||||
])
|
||||
.expand((it) => it)
|
||||
.withNullifyer;
|
||||
|
||||
final updateMessagesFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final messages = it.messages;
|
||||
return updateMessages(cid, messages.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updatePinnedMessagesFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final messages = it.pinnedMessages;
|
||||
return updatePinnedMessages(cid, messages.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updateReadsFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final reads = it.read;
|
||||
return updateReads(cid, reads.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updateMembersFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final members = it.members;
|
||||
return updateMembers(cid, members.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
// Updating first as does not depend on any other table.
|
||||
await Future.wait([
|
||||
...updateMessagesFuture,
|
||||
...updatePinnedMessagesFuture,
|
||||
...updateReadsFuture,
|
||||
...updateMembersFuture,
|
||||
updateUsers(users.toList(growable: false)),
|
||||
updateChannels(channels.toList(growable: false)),
|
||||
]);
|
||||
|
||||
// All has a foreign key relation with channels table.
|
||||
await Future.wait([
|
||||
bulkUpdateReads(channelWithReads),
|
||||
bulkUpdateMembers(channelWithMembers),
|
||||
bulkUpdateMessages(channelWithMessages),
|
||||
bulkUpdatePinnedMessages(channelWithPinnedMessages),
|
||||
]);
|
||||
|
||||
// Both has a foreign key relation with messages, pinnedMessages table.
|
||||
await Future.wait([
|
||||
updateReactions(reactions.toList(growable: false)),
|
||||
updatePinnedMessageReactions(
|
||||
pinnedReactions.toList(growable: false),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@ class TestPersistenceClient extends ChatPersistenceClient {
|
||||
Future<void> deleteReactionsByMessageId(List<String> messageIds) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> deletePinnedMessageReactionsByMessageId(
|
||||
List<String> messageIds) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> disconnect({bool flush = false}) => throw UnimplementedError();
|
||||
|
||||
@@ -101,26 +106,30 @@ class TestPersistenceClient extends ChatPersistenceClient {
|
||||
Future<void> updateLastSyncAt(DateTime lastSyncAt) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future<void> updateMembers(String cid, List<Member> members) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> updateMessages(String cid, List<Message> messages) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> updatePinnedMessages(String cid, List<Message> messages) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> updateReactions(List<Reaction> reactions) => Future.value();
|
||||
|
||||
@override
|
||||
Future<void> updateReads(String cid, List<Read> reads) => Future.value();
|
||||
Future<void> updatePinnedMessageReactions(List<Reaction> reactions) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> updateUsers(List<User> users) => Future.value();
|
||||
|
||||
@override
|
||||
Future<void> bulkUpdateMembers(Map<String, List<Member>> members) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> bulkUpdateMessages(Map<String, List<Message>> messages) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> bulkUpdatePinnedMessages(Map<String, List<Message>> messages) =>
|
||||
Future.value();
|
||||
|
||||
@override
|
||||
Future<void> bulkUpdateReads(Map<String, List<Read>> reads) => Future.value();
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## Upcoming
|
||||
|
||||
- [[#604]](https://github.com/GetStream/stream-chat-flutter/issues/604) Fix cascade deletion by
|
||||
enabling `pragma foreign_keys`.
|
||||
- Added a new table `PinnedMessageReactions` and dao `PinnedMessageReactionDao` specifically for pinned messages.
|
||||
- Updated `stream_chat`: `^2.2.0` -> `TODO`
|
||||
|
||||
## 2.2.0
|
||||
|
||||
- Updated llc dependency
|
||||
@@ -11,14 +18,17 @@
|
||||
## 2.1.0
|
||||
|
||||
✅ Added
|
||||
|
||||
- Added support for `Message.i18n`
|
||||
- Added support for `User.language`
|
||||
|
||||
## 2.0.0
|
||||
|
||||
* Migrate this package to null safety
|
||||
* Minor fixes and improvements
|
||||
|
||||
## 2.0.0-nullsafety.8
|
||||
|
||||
* Updated llc dependency
|
||||
* Upgraded moor dependencies and generated files with the latest dependency
|
||||
|
||||
|
||||
@@ -42,10 +42,9 @@ class ChannelDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
|
||||
/// Updates all the channels using the new [channelList] data
|
||||
Future<void> updateChannels(List<ChannelModel> channelList) => batch(
|
||||
(it) => it.insertAll(
|
||||
(it) => it.insertAllOnConflictUpdate(
|
||||
channels,
|
||||
channelList.map((c) => c.toEntity()).toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -45,13 +45,12 @@ class ChannelQueryDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
}
|
||||
|
||||
await batch((it) {
|
||||
it.insertAll(
|
||||
it.insertAllOnConflictUpdate(
|
||||
channelQueries,
|
||||
cids
|
||||
.map((cid) =>
|
||||
ChannelQueryEntity(queryHash: hash, channelCid: cid))
|
||||
.toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ class ConnectionEventDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
/// Update stored connection event with latest data
|
||||
Future<int> updateConnectionEvent(Event event) => transaction(() async {
|
||||
final connectionInfo = await select(connectionEvents).getSingleOrNull();
|
||||
return into(connectionEvents).insert(
|
||||
return into(connectionEvents).insertOnConflictUpdate(
|
||||
ConnectionEventEntity(
|
||||
id: 1,
|
||||
type: event.type,
|
||||
@@ -38,7 +38,6 @@ class ConnectionEventDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
unreadChannels:
|
||||
event.unreadChannels ?? connectionInfo?.unreadChannels,
|
||||
),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export 'connection_event_dao.dart';
|
||||
export 'member_dao.dart';
|
||||
export 'message_dao.dart';
|
||||
export 'pinned_message_dao.dart';
|
||||
export 'pinned_message_reaction_dao.dart';
|
||||
export 'reaction_dao.dart';
|
||||
export 'read_dao.dart';
|
||||
export 'user_dao.dart';
|
||||
|
||||
@@ -30,14 +30,19 @@ class MemberDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
}).get();
|
||||
|
||||
/// Updates all the members using the new [memberList] data
|
||||
Future<void> updateMembers(String cid, List<Member> memberList) async =>
|
||||
batch(
|
||||
(it) => it.insertAll(
|
||||
members,
|
||||
memberList.map((m) => m.toEntity(cid: cid)).toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
),
|
||||
);
|
||||
Future<void> updateMembers(String cid, List<Member> memberList) =>
|
||||
bulkUpdateMembers({cid: memberList});
|
||||
|
||||
/// Bulk updates the members data of multiple channels
|
||||
Future<void> bulkUpdateMembers(Map<String, List<Member>> channelWithMembers) {
|
||||
final entities = channelWithMembers.entries
|
||||
.map((entry) => entry.value.map(
|
||||
(member) => member.toEntity(cid: entry.key),
|
||||
))
|
||||
.expand((it) => it)
|
||||
.toList(growable: false);
|
||||
return batch((batch) => batch.insertAllOnConflictUpdate(members, entities));
|
||||
}
|
||||
|
||||
/// Deletes all the members whose [Members.channelCid] is present in [cids]
|
||||
Future<void> deleteMemberByCids(List<String> cids) async => batch((it) {
|
||||
|
||||
@@ -169,13 +169,21 @@ class MessageDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
|
||||
/// Updates the message data of a particular channel with
|
||||
/// the new [messageList] data
|
||||
Future<void> updateMessages(String cid, List<Message> messageList) => batch(
|
||||
(batch) {
|
||||
batch.insertAll(
|
||||
messages,
|
||||
messageList.map((it) => it.toEntity(cid: cid)).toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
);
|
||||
},
|
||||
);
|
||||
Future<void> updateMessages(String cid, List<Message> messageList) =>
|
||||
bulkUpdateMessages({cid: messageList});
|
||||
|
||||
/// Bulk updates the message data of multiple channels
|
||||
Future<void> bulkUpdateMessages(
|
||||
Map<String, List<Message>> channelWithMessages,
|
||||
) {
|
||||
final entities = channelWithMessages.entries
|
||||
.map((entry) => entry.value.map(
|
||||
(message) => message.toEntity(cid: entry.key),
|
||||
))
|
||||
.expand((it) => it)
|
||||
.toList(growable: false);
|
||||
return batch(
|
||||
(batch) => batch.insertAllOnConflictUpdate(messages, entities),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,10 @@ class PinnedMessageDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
final userEntity = rows.readTableOrNull(users);
|
||||
final pinnedByEntity = rows.readTableOrNull(_pinnedByUsers);
|
||||
final msgEntity = rows.readTable(pinnedMessages);
|
||||
final latestReactions = await _db.reactionDao.getReactions(msgEntity.id);
|
||||
final ownReactions = await _db.reactionDao.getReactionsByUserId(
|
||||
final latestReactions =
|
||||
await _db.pinnedMessageReactionDao.getReactions(msgEntity.id);
|
||||
final ownReactions =
|
||||
await _db.pinnedMessageReactionDao.getReactionsByUserId(
|
||||
msgEntity.id,
|
||||
_db.userId,
|
||||
);
|
||||
@@ -168,13 +170,21 @@ class PinnedMessageDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
|
||||
/// Updates the message data of a particular channel with
|
||||
/// the new [messageList] data
|
||||
Future<void> updateMessages(String cid, List<Message> messageList) => batch(
|
||||
(batch) {
|
||||
batch.insertAll(
|
||||
pinnedMessages,
|
||||
messageList.map((it) => it.toPinnedEntity(cid: cid)).toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
);
|
||||
},
|
||||
);
|
||||
Future<void> updateMessages(String cid, List<Message> messageList) =>
|
||||
bulkUpdateMessages({cid: messageList});
|
||||
|
||||
/// Bulk updates the message data of multiple channels
|
||||
Future<void> bulkUpdateMessages(
|
||||
Map<String, List<Message>> channelWithMessages,
|
||||
) {
|
||||
final entities = channelWithMessages.entries
|
||||
.map((entry) => entry.value.map(
|
||||
(message) => message.toPinnedEntity(cid: entry.key),
|
||||
))
|
||||
.expand((it) => it)
|
||||
.toList(growable: false);
|
||||
return batch(
|
||||
(batch) => batch.insertAllOnConflictUpdate(pinnedMessages, entities),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/entity/pinned_message_reactions.dart';
|
||||
import 'package:stream_chat_persistence/src/entity/users.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/mapper.dart';
|
||||
|
||||
part 'pinned_message_reaction_dao.g.dart';
|
||||
|
||||
/// The Data Access Object for operations in [PinnedMessageReactions] table.
|
||||
@UseDao(tables: [PinnedMessageReactions, Users])
|
||||
class PinnedMessageReactionDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
with _$PinnedMessageReactionDaoMixin {
|
||||
/// Creates a new reaction dao instance
|
||||
PinnedMessageReactionDao(MoorChatDatabase db) : super(db);
|
||||
|
||||
/// Returns all the reactions of a particular message by matching
|
||||
/// [Reactions.messageId] with [messageId]
|
||||
Future<List<Reaction>> getReactions(String messageId) =>
|
||||
(select(pinnedMessageReactions).join([
|
||||
leftOuterJoin(users, pinnedMessageReactions.userId.equalsExp(users.id)),
|
||||
])
|
||||
..where(pinnedMessageReactions.messageId.equals(messageId))
|
||||
..orderBy([OrderingTerm.asc(pinnedMessageReactions.createdAt)]))
|
||||
.map((rows) {
|
||||
final userEntity = rows.readTableOrNull(users);
|
||||
final reactionEntity = rows.readTable(pinnedMessageReactions);
|
||||
return reactionEntity.toReaction(user: userEntity?.toUser());
|
||||
}).get();
|
||||
|
||||
/// Returns all the reactions of a particular message
|
||||
/// added by a particular user by matching
|
||||
/// [Reactions.messageId] with [messageId] and
|
||||
/// [Reactions.userId] with [userId]
|
||||
Future<List<Reaction>> getReactionsByUserId(
|
||||
String messageId,
|
||||
String userId,
|
||||
) async {
|
||||
final reactions = await getReactions(messageId);
|
||||
return reactions.where((it) => it.userId == userId).toList();
|
||||
}
|
||||
|
||||
/// Updates the reactions data with the new [reactionList] data
|
||||
Future<void> updateReactions(List<Reaction> reactionList) => batch((it) {
|
||||
it.insertAllOnConflictUpdate(
|
||||
pinnedMessageReactions,
|
||||
reactionList.map((r) => r.toPinnedEntity()).toList(),
|
||||
);
|
||||
});
|
||||
|
||||
/// Deletes all the reactions whose [Reactions.messageId] is
|
||||
/// present in [messageIds]
|
||||
Future<void> deleteReactionsByMessageIds(List<String> messageIds) =>
|
||||
batch((it) {
|
||||
it.deleteWhere<PinnedMessageReactions, PinnedMessageReactionEntity>(
|
||||
pinnedMessageReactions,
|
||||
(r) => r.messageId.isIn(messageIds),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'pinned_message_reaction_dao.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// DaoGenerator
|
||||
// **************************************************************************
|
||||
|
||||
mixin _$PinnedMessageReactionDaoMixin on DatabaseAccessor<MoorChatDatabase> {
|
||||
$PinnedMessageReactionsTable get pinnedMessageReactions =>
|
||||
attachedDatabase.pinnedMessageReactions;
|
||||
$UsersTable get users => attachedDatabase.users;
|
||||
}
|
||||
@@ -42,10 +42,9 @@ class ReactionDao extends DatabaseAccessor<MoorChatDatabase>
|
||||
|
||||
/// Updates the reactions data with the new [reactionList] data
|
||||
Future<void> updateReactions(List<Reaction> reactionList) => batch((it) {
|
||||
it.insertAll(
|
||||
it.insertAllOnConflictUpdate(
|
||||
reactions,
|
||||
reactionList.map((r) => r.toEntity()).toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -29,11 +29,17 @@ class ReadDao extends DatabaseAccessor<MoorChatDatabase> with _$ReadDaoMixin {
|
||||
|
||||
/// Updates the read data of a particular channel with
|
||||
/// the new [readList] data
|
||||
Future<void> updateReads(String cid, List<Read> readList) => batch(
|
||||
(it) => it.insertAll(
|
||||
reads,
|
||||
readList.map((r) => r.toEntity(cid: cid)).toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
),
|
||||
);
|
||||
Future<void> updateReads(String cid, List<Read> readList) =>
|
||||
bulkUpdateReads({cid: readList});
|
||||
|
||||
/// Bulk updates the reads data of multiple channels
|
||||
Future<void> bulkUpdateReads(Map<String, List<Read>> channelWithReads) {
|
||||
final entities = channelWithReads.entries
|
||||
.map((entry) => entry.value.map(
|
||||
(read) => read.toEntity(cid: entry.key),
|
||||
))
|
||||
.expand((it) => it)
|
||||
.toList(growable: false);
|
||||
return batch((batch) => batch.insertAllOnConflictUpdate(reads, entities));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,9 @@ class UserDao extends DatabaseAccessor<MoorChatDatabase> with _$UserDaoMixin {
|
||||
|
||||
/// Updates the users data with the new [userList] data
|
||||
Future<void> updateUsers(List<User> userList) => batch(
|
||||
(it) => it.insertAll(
|
||||
(it) => it.insertAllOnConflictUpdate(
|
||||
users,
|
||||
userList.map((u) => u.toEntity()).toList(),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ part 'moor_chat_database.g.dart';
|
||||
Channels,
|
||||
Messages,
|
||||
PinnedMessages,
|
||||
PinnedMessageReactions,
|
||||
Reactions,
|
||||
Users,
|
||||
Members,
|
||||
@@ -25,6 +26,7 @@ part 'moor_chat_database.g.dart';
|
||||
ChannelDao,
|
||||
MessageDao,
|
||||
PinnedMessageDao,
|
||||
PinnedMessageReactionDao,
|
||||
MemberDao,
|
||||
ReactionDao,
|
||||
ReadDao,
|
||||
@@ -51,10 +53,13 @@ class MoorChatDatabase extends _$MoorChatDatabase {
|
||||
|
||||
// you should bump this number whenever you change or add a table definition.
|
||||
@override
|
||||
int get schemaVersion => 5;
|
||||
int get schemaVersion => 6;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
beforeOpen: (details) async {
|
||||
await customStatement('PRAGMA foreign_keys = ON');
|
||||
},
|
||||
onUpgrade: (openingDetails, before, after) async {
|
||||
if (before != after) {
|
||||
final m = createMigrator();
|
||||
|
||||
@@ -645,7 +645,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
final String? pinnedByUserId;
|
||||
|
||||
/// The channel cid of which this message is part of
|
||||
final String? channelCid;
|
||||
final String channelCid;
|
||||
|
||||
/// A Map of [messageText] translations.
|
||||
final Map<String, String>? i18n;
|
||||
@@ -675,7 +675,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
this.pinnedAt,
|
||||
this.pinExpires,
|
||||
this.pinnedByUserId,
|
||||
this.channelCid,
|
||||
required this.channelCid,
|
||||
this.i18n,
|
||||
this.extraData});
|
||||
factory MessageEntity.fromData(
|
||||
@@ -728,7 +728,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
pinnedByUserId: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}pinned_by_user_id']),
|
||||
channelCid: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']),
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid'])!,
|
||||
i18n: $MessagesTable.$converter5.mapToDart(const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}i18n'])),
|
||||
extraData: $MessagesTable.$converter6.mapToDart(const StringType()
|
||||
@@ -800,9 +800,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
if (!nullToAbsent || pinnedByUserId != null) {
|
||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId);
|
||||
}
|
||||
if (!nullToAbsent || channelCid != null) {
|
||||
map['channel_cid'] = Variable<String?>(channelCid);
|
||||
}
|
||||
map['channel_cid'] = Variable<String>(channelCid);
|
||||
if (!nullToAbsent || i18n != null) {
|
||||
final converter = $MessagesTable.$converter5;
|
||||
map['i18n'] = Variable<String?>(converter.mapToSql(i18n));
|
||||
@@ -842,7 +840,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
pinnedAt: serializer.fromJson<DateTime?>(json['pinnedAt']),
|
||||
pinExpires: serializer.fromJson<DateTime?>(json['pinExpires']),
|
||||
pinnedByUserId: serializer.fromJson<String?>(json['pinnedByUserId']),
|
||||
channelCid: serializer.fromJson<String?>(json['channelCid']),
|
||||
channelCid: serializer.fromJson<String>(json['channelCid']),
|
||||
i18n: serializer.fromJson<Map<String, String>?>(json['i18n']),
|
||||
extraData: serializer.fromJson<Map<String, Object?>?>(json['extraData']),
|
||||
);
|
||||
@@ -873,7 +871,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
'pinnedAt': serializer.toJson<DateTime?>(pinnedAt),
|
||||
'pinExpires': serializer.toJson<DateTime?>(pinExpires),
|
||||
'pinnedByUserId': serializer.toJson<String?>(pinnedByUserId),
|
||||
'channelCid': serializer.toJson<String?>(channelCid),
|
||||
'channelCid': serializer.toJson<String>(channelCid),
|
||||
'i18n': serializer.toJson<Map<String, String>?>(i18n),
|
||||
'extraData': serializer.toJson<Map<String, Object?>?>(extraData),
|
||||
};
|
||||
@@ -902,7 +900,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
Value<DateTime?> pinnedAt = const Value.absent(),
|
||||
Value<DateTime?> pinExpires = const Value.absent(),
|
||||
Value<String?> pinnedByUserId = const Value.absent(),
|
||||
Value<String?> channelCid = const Value.absent(),
|
||||
String? channelCid,
|
||||
Value<Map<String, String>?> i18n = const Value.absent(),
|
||||
Value<Map<String, Object?>?> extraData = const Value.absent()}) =>
|
||||
MessageEntity(
|
||||
@@ -934,7 +932,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
||||
pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires,
|
||||
pinnedByUserId:
|
||||
pinnedByUserId.present ? pinnedByUserId.value : this.pinnedByUserId,
|
||||
channelCid: channelCid.present ? channelCid.value : this.channelCid,
|
||||
channelCid: channelCid ?? this.channelCid,
|
||||
i18n: i18n.present ? i18n.value : this.i18n,
|
||||
extraData: extraData.present ? extraData.value : this.extraData,
|
||||
);
|
||||
@@ -1068,7 +1066,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
||||
final Value<DateTime?> pinnedAt;
|
||||
final Value<DateTime?> pinExpires;
|
||||
final Value<String?> pinnedByUserId;
|
||||
final Value<String?> channelCid;
|
||||
final Value<String> channelCid;
|
||||
final Value<Map<String, String>?> i18n;
|
||||
final Value<Map<String, Object?>?> extraData;
|
||||
const MessagesCompanion({
|
||||
@@ -1121,12 +1119,13 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
||||
this.pinnedAt = const Value.absent(),
|
||||
this.pinExpires = const Value.absent(),
|
||||
this.pinnedByUserId = const Value.absent(),
|
||||
this.channelCid = const Value.absent(),
|
||||
required String channelCid,
|
||||
this.i18n = const Value.absent(),
|
||||
this.extraData = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
attachments = Value(attachments),
|
||||
mentionedUsers = Value(mentionedUsers);
|
||||
mentionedUsers = Value(mentionedUsers),
|
||||
channelCid = Value(channelCid);
|
||||
static Insertable<MessageEntity> custom({
|
||||
Expression<String>? id,
|
||||
Expression<String?>? messageText,
|
||||
@@ -1150,7 +1149,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
||||
Expression<DateTime?>? pinnedAt,
|
||||
Expression<DateTime?>? pinExpires,
|
||||
Expression<String?>? pinnedByUserId,
|
||||
Expression<String?>? channelCid,
|
||||
Expression<String>? channelCid,
|
||||
Expression<Map<String, String>?>? i18n,
|
||||
Expression<Map<String, Object?>?>? extraData,
|
||||
}) {
|
||||
@@ -1206,7 +1205,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
||||
Value<DateTime?>? pinnedAt,
|
||||
Value<DateTime?>? pinExpires,
|
||||
Value<String?>? pinnedByUserId,
|
||||
Value<String?>? channelCid,
|
||||
Value<String>? channelCid,
|
||||
Value<Map<String, String>?>? i18n,
|
||||
Value<Map<String, Object?>?>? extraData}) {
|
||||
return MessagesCompanion(
|
||||
@@ -1317,7 +1316,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId.value);
|
||||
}
|
||||
if (channelCid.present) {
|
||||
map['channel_cid'] = Variable<String?>(channelCid.value);
|
||||
map['channel_cid'] = Variable<String>(channelCid.value);
|
||||
}
|
||||
if (i18n.present) {
|
||||
final converter = $MessagesTable.$converter5;
|
||||
@@ -1491,11 +1490,10 @@ class $MessagesTable extends Messages
|
||||
typeName: 'TEXT', requiredDuringInsert: false);
|
||||
final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid');
|
||||
late final GeneratedColumn<String?> channelCid = GeneratedColumn<String?>(
|
||||
'channel_cid', aliasedName, true,
|
||||
'channel_cid', aliasedName, false,
|
||||
typeName: 'TEXT',
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints:
|
||||
'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE');
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'REFERENCES channels(cid) ON DELETE CASCADE');
|
||||
final VerificationMeta _i18nMeta = const VerificationMeta('i18n');
|
||||
late final GeneratedColumnWithTypeConverter<Map<String, String>, String?>
|
||||
i18n = GeneratedColumn<String?>('i18n', aliasedName, true,
|
||||
@@ -1634,6 +1632,8 @@ class $MessagesTable extends Messages
|
||||
_channelCidMeta,
|
||||
channelCid.isAcceptableOrUnknown(
|
||||
data['channel_cid']!, _channelCidMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_channelCidMeta);
|
||||
}
|
||||
context.handle(_i18nMeta, const VerificationResult.success());
|
||||
context.handle(_extraDataMeta, const VerificationResult.success());
|
||||
@@ -1739,7 +1739,7 @@ class PinnedMessageEntity extends DataClass
|
||||
final String? pinnedByUserId;
|
||||
|
||||
/// The channel cid of which this message is part of
|
||||
final String? channelCid;
|
||||
final String channelCid;
|
||||
|
||||
/// A Map of [messageText] translations.
|
||||
final Map<String, String>? i18n;
|
||||
@@ -1769,7 +1769,7 @@ class PinnedMessageEntity extends DataClass
|
||||
this.pinnedAt,
|
||||
this.pinExpires,
|
||||
this.pinnedByUserId,
|
||||
this.channelCid,
|
||||
required this.channelCid,
|
||||
this.i18n,
|
||||
this.extraData});
|
||||
factory PinnedMessageEntity.fromData(
|
||||
@@ -1825,7 +1825,7 @@ class PinnedMessageEntity extends DataClass
|
||||
pinnedByUserId: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}pinned_by_user_id']),
|
||||
channelCid: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']),
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid'])!,
|
||||
i18n: $PinnedMessagesTable.$converter5.mapToDart(const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}i18n'])),
|
||||
extraData: $PinnedMessagesTable.$converter6.mapToDart(const StringType()
|
||||
@@ -1897,9 +1897,7 @@ class PinnedMessageEntity extends DataClass
|
||||
if (!nullToAbsent || pinnedByUserId != null) {
|
||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId);
|
||||
}
|
||||
if (!nullToAbsent || channelCid != null) {
|
||||
map['channel_cid'] = Variable<String?>(channelCid);
|
||||
}
|
||||
map['channel_cid'] = Variable<String>(channelCid);
|
||||
if (!nullToAbsent || i18n != null) {
|
||||
final converter = $PinnedMessagesTable.$converter5;
|
||||
map['i18n'] = Variable<String?>(converter.mapToSql(i18n));
|
||||
@@ -1939,7 +1937,7 @@ class PinnedMessageEntity extends DataClass
|
||||
pinnedAt: serializer.fromJson<DateTime?>(json['pinnedAt']),
|
||||
pinExpires: serializer.fromJson<DateTime?>(json['pinExpires']),
|
||||
pinnedByUserId: serializer.fromJson<String?>(json['pinnedByUserId']),
|
||||
channelCid: serializer.fromJson<String?>(json['channelCid']),
|
||||
channelCid: serializer.fromJson<String>(json['channelCid']),
|
||||
i18n: serializer.fromJson<Map<String, String>?>(json['i18n']),
|
||||
extraData: serializer.fromJson<Map<String, Object?>?>(json['extraData']),
|
||||
);
|
||||
@@ -1970,7 +1968,7 @@ class PinnedMessageEntity extends DataClass
|
||||
'pinnedAt': serializer.toJson<DateTime?>(pinnedAt),
|
||||
'pinExpires': serializer.toJson<DateTime?>(pinExpires),
|
||||
'pinnedByUserId': serializer.toJson<String?>(pinnedByUserId),
|
||||
'channelCid': serializer.toJson<String?>(channelCid),
|
||||
'channelCid': serializer.toJson<String>(channelCid),
|
||||
'i18n': serializer.toJson<Map<String, String>?>(i18n),
|
||||
'extraData': serializer.toJson<Map<String, Object?>?>(extraData),
|
||||
};
|
||||
@@ -1999,7 +1997,7 @@ class PinnedMessageEntity extends DataClass
|
||||
Value<DateTime?> pinnedAt = const Value.absent(),
|
||||
Value<DateTime?> pinExpires = const Value.absent(),
|
||||
Value<String?> pinnedByUserId = const Value.absent(),
|
||||
Value<String?> channelCid = const Value.absent(),
|
||||
String? channelCid,
|
||||
Value<Map<String, String>?> i18n = const Value.absent(),
|
||||
Value<Map<String, Object?>?> extraData = const Value.absent()}) =>
|
||||
PinnedMessageEntity(
|
||||
@@ -2031,7 +2029,7 @@ class PinnedMessageEntity extends DataClass
|
||||
pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires,
|
||||
pinnedByUserId:
|
||||
pinnedByUserId.present ? pinnedByUserId.value : this.pinnedByUserId,
|
||||
channelCid: channelCid.present ? channelCid.value : this.channelCid,
|
||||
channelCid: channelCid ?? this.channelCid,
|
||||
i18n: i18n.present ? i18n.value : this.i18n,
|
||||
extraData: extraData.present ? extraData.value : this.extraData,
|
||||
);
|
||||
@@ -2165,7 +2163,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
||||
final Value<DateTime?> pinnedAt;
|
||||
final Value<DateTime?> pinExpires;
|
||||
final Value<String?> pinnedByUserId;
|
||||
final Value<String?> channelCid;
|
||||
final Value<String> channelCid;
|
||||
final Value<Map<String, String>?> i18n;
|
||||
final Value<Map<String, Object?>?> extraData;
|
||||
const PinnedMessagesCompanion({
|
||||
@@ -2218,12 +2216,13 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
||||
this.pinnedAt = const Value.absent(),
|
||||
this.pinExpires = const Value.absent(),
|
||||
this.pinnedByUserId = const Value.absent(),
|
||||
this.channelCid = const Value.absent(),
|
||||
required String channelCid,
|
||||
this.i18n = const Value.absent(),
|
||||
this.extraData = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
attachments = Value(attachments),
|
||||
mentionedUsers = Value(mentionedUsers);
|
||||
mentionedUsers = Value(mentionedUsers),
|
||||
channelCid = Value(channelCid);
|
||||
static Insertable<PinnedMessageEntity> custom({
|
||||
Expression<String>? id,
|
||||
Expression<String?>? messageText,
|
||||
@@ -2247,7 +2246,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
||||
Expression<DateTime?>? pinnedAt,
|
||||
Expression<DateTime?>? pinExpires,
|
||||
Expression<String?>? pinnedByUserId,
|
||||
Expression<String?>? channelCid,
|
||||
Expression<String>? channelCid,
|
||||
Expression<Map<String, String>?>? i18n,
|
||||
Expression<Map<String, Object?>?>? extraData,
|
||||
}) {
|
||||
@@ -2303,7 +2302,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
||||
Value<DateTime?>? pinnedAt,
|
||||
Value<DateTime?>? pinExpires,
|
||||
Value<String?>? pinnedByUserId,
|
||||
Value<String?>? channelCid,
|
||||
Value<String>? channelCid,
|
||||
Value<Map<String, String>?>? i18n,
|
||||
Value<Map<String, Object?>?>? extraData}) {
|
||||
return PinnedMessagesCompanion(
|
||||
@@ -2414,7 +2413,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId.value);
|
||||
}
|
||||
if (channelCid.present) {
|
||||
map['channel_cid'] = Variable<String?>(channelCid.value);
|
||||
map['channel_cid'] = Variable<String>(channelCid.value);
|
||||
}
|
||||
if (i18n.present) {
|
||||
final converter = $PinnedMessagesTable.$converter5;
|
||||
@@ -2589,11 +2588,10 @@ class $PinnedMessagesTable extends PinnedMessages
|
||||
typeName: 'TEXT', requiredDuringInsert: false);
|
||||
final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid');
|
||||
late final GeneratedColumn<String?> channelCid = GeneratedColumn<String?>(
|
||||
'channel_cid', aliasedName, true,
|
||||
'channel_cid', aliasedName, false,
|
||||
typeName: 'TEXT',
|
||||
requiredDuringInsert: false,
|
||||
$customConstraints:
|
||||
'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE');
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'REFERENCES channels(cid) ON DELETE CASCADE');
|
||||
final VerificationMeta _i18nMeta = const VerificationMeta('i18n');
|
||||
late final GeneratedColumnWithTypeConverter<Map<String, String>, String?>
|
||||
i18n = GeneratedColumn<String?>('i18n', aliasedName, true,
|
||||
@@ -2734,6 +2732,8 @@ class $PinnedMessagesTable extends PinnedMessages
|
||||
_channelCidMeta,
|
||||
channelCid.isAcceptableOrUnknown(
|
||||
data['channel_cid']!, _channelCidMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_channelCidMeta);
|
||||
}
|
||||
context.handle(_i18nMeta, const VerificationResult.success());
|
||||
context.handle(_extraDataMeta, const VerificationResult.success());
|
||||
@@ -2769,6 +2769,340 @@ class $PinnedMessagesTable extends PinnedMessages
|
||||
MapConverter<Object?>();
|
||||
}
|
||||
|
||||
class PinnedMessageReactionEntity extends DataClass
|
||||
implements Insertable<PinnedMessageReactionEntity> {
|
||||
/// The id of the user that sent the reaction
|
||||
final String userId;
|
||||
|
||||
/// The messageId to which the reaction belongs
|
||||
final String messageId;
|
||||
|
||||
/// The type of the reaction
|
||||
final String type;
|
||||
|
||||
/// The DateTime on which the reaction is created
|
||||
final DateTime createdAt;
|
||||
|
||||
/// The score of the reaction (ie. number of reactions sent)
|
||||
final int score;
|
||||
|
||||
/// Reaction custom extraData
|
||||
final Map<String, Object?>? extraData;
|
||||
PinnedMessageReactionEntity(
|
||||
{required this.userId,
|
||||
required this.messageId,
|
||||
required this.type,
|
||||
required this.createdAt,
|
||||
required this.score,
|
||||
this.extraData});
|
||||
factory PinnedMessageReactionEntity.fromData(
|
||||
Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String? prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
return PinnedMessageReactionEntity(
|
||||
userId: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}user_id'])!,
|
||||
messageId: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}message_id'])!,
|
||||
type: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}type'])!,
|
||||
createdAt: const DateTimeType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}created_at'])!,
|
||||
score: const IntType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}score'])!,
|
||||
extraData: $PinnedMessageReactionsTable.$converter0.mapToDart(
|
||||
const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}extra_data'])),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['user_id'] = Variable<String>(userId);
|
||||
map['message_id'] = Variable<String>(messageId);
|
||||
map['type'] = Variable<String>(type);
|
||||
map['created_at'] = Variable<DateTime>(createdAt);
|
||||
map['score'] = Variable<int>(score);
|
||||
if (!nullToAbsent || extraData != null) {
|
||||
final converter = $PinnedMessageReactionsTable.$converter0;
|
||||
map['extra_data'] = Variable<String?>(converter.mapToSql(extraData));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
factory PinnedMessageReactionEntity.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return PinnedMessageReactionEntity(
|
||||
userId: serializer.fromJson<String>(json['userId']),
|
||||
messageId: serializer.fromJson<String>(json['messageId']),
|
||||
type: serializer.fromJson<String>(json['type']),
|
||||
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
||||
score: serializer.fromJson<int>(json['score']),
|
||||
extraData: serializer.fromJson<Map<String, Object?>?>(json['extraData']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'userId': serializer.toJson<String>(userId),
|
||||
'messageId': serializer.toJson<String>(messageId),
|
||||
'type': serializer.toJson<String>(type),
|
||||
'createdAt': serializer.toJson<DateTime>(createdAt),
|
||||
'score': serializer.toJson<int>(score),
|
||||
'extraData': serializer.toJson<Map<String, Object?>?>(extraData),
|
||||
};
|
||||
}
|
||||
|
||||
PinnedMessageReactionEntity copyWith(
|
||||
{String? userId,
|
||||
String? messageId,
|
||||
String? type,
|
||||
DateTime? createdAt,
|
||||
int? score,
|
||||
Value<Map<String, Object?>?> extraData = const Value.absent()}) =>
|
||||
PinnedMessageReactionEntity(
|
||||
userId: userId ?? this.userId,
|
||||
messageId: messageId ?? this.messageId,
|
||||
type: type ?? this.type,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
score: score ?? this.score,
|
||||
extraData: extraData.present ? extraData.value : this.extraData,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('PinnedMessageReactionEntity(')
|
||||
..write('userId: $userId, ')
|
||||
..write('messageId: $messageId, ')
|
||||
..write('type: $type, ')
|
||||
..write('createdAt: $createdAt, ')
|
||||
..write('score: $score, ')
|
||||
..write('extraData: $extraData')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(
|
||||
userId.hashCode,
|
||||
$mrjc(
|
||||
messageId.hashCode,
|
||||
$mrjc(
|
||||
type.hashCode,
|
||||
$mrjc(createdAt.hashCode,
|
||||
$mrjc(score.hashCode, extraData.hashCode))))));
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is PinnedMessageReactionEntity &&
|
||||
other.userId == this.userId &&
|
||||
other.messageId == this.messageId &&
|
||||
other.type == this.type &&
|
||||
other.createdAt == this.createdAt &&
|
||||
other.score == this.score &&
|
||||
other.extraData == this.extraData);
|
||||
}
|
||||
|
||||
class PinnedMessageReactionsCompanion
|
||||
extends UpdateCompanion<PinnedMessageReactionEntity> {
|
||||
final Value<String> userId;
|
||||
final Value<String> messageId;
|
||||
final Value<String> type;
|
||||
final Value<DateTime> createdAt;
|
||||
final Value<int> score;
|
||||
final Value<Map<String, Object?>?> extraData;
|
||||
const PinnedMessageReactionsCompanion({
|
||||
this.userId = const Value.absent(),
|
||||
this.messageId = const Value.absent(),
|
||||
this.type = const Value.absent(),
|
||||
this.createdAt = const Value.absent(),
|
||||
this.score = const Value.absent(),
|
||||
this.extraData = const Value.absent(),
|
||||
});
|
||||
PinnedMessageReactionsCompanion.insert({
|
||||
required String userId,
|
||||
required String messageId,
|
||||
required String type,
|
||||
this.createdAt = const Value.absent(),
|
||||
this.score = const Value.absent(),
|
||||
this.extraData = const Value.absent(),
|
||||
}) : userId = Value(userId),
|
||||
messageId = Value(messageId),
|
||||
type = Value(type);
|
||||
static Insertable<PinnedMessageReactionEntity> custom({
|
||||
Expression<String>? userId,
|
||||
Expression<String>? messageId,
|
||||
Expression<String>? type,
|
||||
Expression<DateTime>? createdAt,
|
||||
Expression<int>? score,
|
||||
Expression<Map<String, Object?>?>? extraData,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (userId != null) 'user_id': userId,
|
||||
if (messageId != null) 'message_id': messageId,
|
||||
if (type != null) 'type': type,
|
||||
if (createdAt != null) 'created_at': createdAt,
|
||||
if (score != null) 'score': score,
|
||||
if (extraData != null) 'extra_data': extraData,
|
||||
});
|
||||
}
|
||||
|
||||
PinnedMessageReactionsCompanion copyWith(
|
||||
{Value<String>? userId,
|
||||
Value<String>? messageId,
|
||||
Value<String>? type,
|
||||
Value<DateTime>? createdAt,
|
||||
Value<int>? score,
|
||||
Value<Map<String, Object?>?>? extraData}) {
|
||||
return PinnedMessageReactionsCompanion(
|
||||
userId: userId ?? this.userId,
|
||||
messageId: messageId ?? this.messageId,
|
||||
type: type ?? this.type,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
score: score ?? this.score,
|
||||
extraData: extraData ?? this.extraData,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (userId.present) {
|
||||
map['user_id'] = Variable<String>(userId.value);
|
||||
}
|
||||
if (messageId.present) {
|
||||
map['message_id'] = Variable<String>(messageId.value);
|
||||
}
|
||||
if (type.present) {
|
||||
map['type'] = Variable<String>(type.value);
|
||||
}
|
||||
if (createdAt.present) {
|
||||
map['created_at'] = Variable<DateTime>(createdAt.value);
|
||||
}
|
||||
if (score.present) {
|
||||
map['score'] = Variable<int>(score.value);
|
||||
}
|
||||
if (extraData.present) {
|
||||
final converter = $PinnedMessageReactionsTable.$converter0;
|
||||
map['extra_data'] =
|
||||
Variable<String?>(converter.mapToSql(extraData.value));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('PinnedMessageReactionsCompanion(')
|
||||
..write('userId: $userId, ')
|
||||
..write('messageId: $messageId, ')
|
||||
..write('type: $type, ')
|
||||
..write('createdAt: $createdAt, ')
|
||||
..write('score: $score, ')
|
||||
..write('extraData: $extraData')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $PinnedMessageReactionsTable extends PinnedMessageReactions
|
||||
with TableInfo<$PinnedMessageReactionsTable, PinnedMessageReactionEntity> {
|
||||
final GeneratedDatabase _db;
|
||||
final String? _alias;
|
||||
$PinnedMessageReactionsTable(this._db, [this._alias]);
|
||||
final VerificationMeta _userIdMeta = const VerificationMeta('userId');
|
||||
late final GeneratedColumn<String?> userId = GeneratedColumn<String?>(
|
||||
'user_id', aliasedName, false,
|
||||
typeName: 'TEXT', requiredDuringInsert: true);
|
||||
final VerificationMeta _messageIdMeta = const VerificationMeta('messageId');
|
||||
late final GeneratedColumn<String?> messageId = GeneratedColumn<String?>(
|
||||
'message_id', aliasedName, false,
|
||||
typeName: 'TEXT',
|
||||
requiredDuringInsert: true,
|
||||
$customConstraints: 'REFERENCES pinned_messages(id) ON DELETE CASCADE');
|
||||
final VerificationMeta _typeMeta = const VerificationMeta('type');
|
||||
late final GeneratedColumn<String?> type = GeneratedColumn<String?>(
|
||||
'type', aliasedName, false,
|
||||
typeName: 'TEXT', requiredDuringInsert: true);
|
||||
final VerificationMeta _createdAtMeta = const VerificationMeta('createdAt');
|
||||
late final GeneratedColumn<DateTime?> createdAt = GeneratedColumn<DateTime?>(
|
||||
'created_at', aliasedName, false,
|
||||
typeName: 'INTEGER',
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: currentDateAndTime);
|
||||
final VerificationMeta _scoreMeta = const VerificationMeta('score');
|
||||
late final GeneratedColumn<int?> score = GeneratedColumn<int?>(
|
||||
'score', aliasedName, false,
|
||||
typeName: 'INTEGER',
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant(0));
|
||||
final VerificationMeta _extraDataMeta = const VerificationMeta('extraData');
|
||||
late final GeneratedColumnWithTypeConverter<Map<String, Object?>, String?>
|
||||
extraData = GeneratedColumn<String?>('extra_data', aliasedName, true,
|
||||
typeName: 'TEXT', requiredDuringInsert: false)
|
||||
.withConverter<Map<String, Object?>>(
|
||||
$PinnedMessageReactionsTable.$converter0);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
[userId, messageId, type, createdAt, score, extraData];
|
||||
@override
|
||||
String get aliasedName => _alias ?? 'pinned_message_reactions';
|
||||
@override
|
||||
String get actualTableName => 'pinned_message_reactions';
|
||||
@override
|
||||
VerificationContext validateIntegrity(
|
||||
Insertable<PinnedMessageReactionEntity> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('user_id')) {
|
||||
context.handle(_userIdMeta,
|
||||
userId.isAcceptableOrUnknown(data['user_id']!, _userIdMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_userIdMeta);
|
||||
}
|
||||
if (data.containsKey('message_id')) {
|
||||
context.handle(_messageIdMeta,
|
||||
messageId.isAcceptableOrUnknown(data['message_id']!, _messageIdMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_messageIdMeta);
|
||||
}
|
||||
if (data.containsKey('type')) {
|
||||
context.handle(
|
||||
_typeMeta, type.isAcceptableOrUnknown(data['type']!, _typeMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_typeMeta);
|
||||
}
|
||||
if (data.containsKey('created_at')) {
|
||||
context.handle(_createdAtMeta,
|
||||
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
||||
}
|
||||
if (data.containsKey('score')) {
|
||||
context.handle(
|
||||
_scoreMeta, score.isAcceptableOrUnknown(data['score']!, _scoreMeta));
|
||||
}
|
||||
context.handle(_extraDataMeta, const VerificationResult.success());
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {messageId, type, userId};
|
||||
@override
|
||||
PinnedMessageReactionEntity map(Map<String, dynamic> data,
|
||||
{String? tablePrefix}) {
|
||||
return PinnedMessageReactionEntity.fromData(data, _db,
|
||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||
}
|
||||
|
||||
@override
|
||||
$PinnedMessageReactionsTable createAlias(String alias) {
|
||||
return $PinnedMessageReactionsTable(_db, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<Map<String, Object?>, String> $converter0 =
|
||||
MapConverter<Object?>();
|
||||
}
|
||||
|
||||
class ReactionEntity extends DataClass implements Insertable<ReactionEntity> {
|
||||
/// The id of the user that sent the reaction
|
||||
final String userId;
|
||||
@@ -4897,6 +5231,8 @@ abstract class _$MoorChatDatabase extends GeneratedDatabase {
|
||||
late final $ChannelsTable channels = $ChannelsTable(this);
|
||||
late final $MessagesTable messages = $MessagesTable(this);
|
||||
late final $PinnedMessagesTable pinnedMessages = $PinnedMessagesTable(this);
|
||||
late final $PinnedMessageReactionsTable pinnedMessageReactions =
|
||||
$PinnedMessageReactionsTable(this);
|
||||
late final $ReactionsTable reactions = $ReactionsTable(this);
|
||||
late final $UsersTable users = $UsersTable(this);
|
||||
late final $MembersTable members = $MembersTable(this);
|
||||
@@ -4909,6 +5245,8 @@ abstract class _$MoorChatDatabase extends GeneratedDatabase {
|
||||
late final MessageDao messageDao = MessageDao(this as MoorChatDatabase);
|
||||
late final PinnedMessageDao pinnedMessageDao =
|
||||
PinnedMessageDao(this as MoorChatDatabase);
|
||||
late final PinnedMessageReactionDao pinnedMessageReactionDao =
|
||||
PinnedMessageReactionDao(this as MoorChatDatabase);
|
||||
late final MemberDao memberDao = MemberDao(this as MoorChatDatabase);
|
||||
late final ReactionDao reactionDao = ReactionDao(this as MoorChatDatabase);
|
||||
late final ReadDao readDao = ReadDao(this as MoorChatDatabase);
|
||||
@@ -4923,6 +5261,7 @@ abstract class _$MoorChatDatabase extends GeneratedDatabase {
|
||||
channels,
|
||||
messages,
|
||||
pinnedMessages,
|
||||
pinnedMessageReactions,
|
||||
reactions,
|
||||
users,
|
||||
members,
|
||||
|
||||
@@ -3,6 +3,7 @@ export 'channels.dart';
|
||||
export 'connection_events.dart';
|
||||
export 'members.dart';
|
||||
export 'messages.dart';
|
||||
export 'pinned_message_reactions.dart';
|
||||
export 'pinned_messages.dart';
|
||||
export 'reactions.dart';
|
||||
export 'reads.dart';
|
||||
|
||||
@@ -39,8 +39,5 @@ class Members extends Table {
|
||||
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {
|
||||
userId,
|
||||
channelCid,
|
||||
};
|
||||
Set<Column> get primaryKey => {userId, channelCid};
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ class Messages extends Table {
|
||||
TextColumn get pinnedByUserId => text().nullable()();
|
||||
|
||||
/// The channel cid of which this message is part of
|
||||
TextColumn get channelCid => text().nullable().customConstraint(
|
||||
'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE')();
|
||||
TextColumn get channelCid =>
|
||||
text().customConstraint('REFERENCES channels(cid) ON DELETE CASCADE')();
|
||||
|
||||
/// A Map of [messageText] translations.
|
||||
TextColumn get i18n => text().nullable().map(MapConverter<String>())();
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// coverage:ignore-file
|
||||
import 'package:moor/moor.dart';
|
||||
|
||||
import 'package:stream_chat_persistence/src/entity/reactions.dart';
|
||||
|
||||
/// Represents a [PinnedMessageReactions] table in [MoorChatDatabase].
|
||||
@DataClassName('PinnedMessageReactionEntity')
|
||||
class PinnedMessageReactions extends Reactions {
|
||||
/// The messageId to which the reaction belongs
|
||||
@override
|
||||
TextColumn get messageId => text()
|
||||
.customConstraint('REFERENCES pinned_messages(id) ON DELETE CASCADE')();
|
||||
}
|
||||
@@ -3,6 +3,7 @@ export 'event_mapper.dart';
|
||||
export 'member_mapper.dart';
|
||||
export 'message_mapper.dart';
|
||||
export 'pinned_message_mapper.dart';
|
||||
export 'pinned_message_reaction_mapper.dart';
|
||||
export 'reaction_mapper.dart';
|
||||
export 'read_mapper.dart';
|
||||
export 'user_mapper.dart';
|
||||
|
||||
@@ -51,7 +51,7 @@ extension MessageEntityX on MessageEntity {
|
||||
/// Useful mapping functions for [Message]
|
||||
extension MessageX on Message {
|
||||
/// Maps a [Message] into [MessageEntity]
|
||||
MessageEntity toEntity({String? cid}) => MessageEntity(
|
||||
MessageEntity toEntity({required String cid}) => MessageEntity(
|
||||
id: id,
|
||||
attachments: attachments.map((it) => jsonEncode(it.toData())).toList(),
|
||||
channelCid: cid,
|
||||
|
||||
@@ -51,7 +51,8 @@ extension PinnedMessageEntityX on PinnedMessageEntity {
|
||||
/// Useful mapping functions for [Message]
|
||||
extension PMessageX on Message {
|
||||
/// Maps a [Message] into [PinnedMessageEntity]
|
||||
PinnedMessageEntity toPinnedEntity({String? cid}) => PinnedMessageEntity(
|
||||
PinnedMessageEntity toPinnedEntity({required String cid}) =>
|
||||
PinnedMessageEntity(
|
||||
id: id,
|
||||
attachments: attachments.map((it) => jsonEncode(it.toData())).toList(),
|
||||
channelCid: cid,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
|
||||
/// Useful mapping functions for [PinnedMessageReactionEntity]
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
/// Useful mapping functions for [Reaction]
|
||||
extension PReactionX on Reaction {
|
||||
/// Maps a [Reaction] into [ReactionEntity]
|
||||
PinnedMessageReactionEntity toPinnedEntity() => PinnedMessageReactionEntity(
|
||||
extraData: extraData,
|
||||
type: type,
|
||||
createdAt: createdAt,
|
||||
userId: userId!,
|
||||
messageId: messageId!,
|
||||
score: score,
|
||||
);
|
||||
}
|
||||
@@ -296,25 +296,34 @@ class StreamChatPersistenceClient extends ChatPersistenceClient {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateMembers(String cid, List<Member> members) {
|
||||
Future<void> bulkUpdateMembers(Map<String, List<Member>> members) {
|
||||
assert(_debugIsConnected, '');
|
||||
_logger.info('updateMembers');
|
||||
return _readProtected(() => db!.memberDao.updateMembers(cid, members));
|
||||
_logger.info('bulkUpdateMembers');
|
||||
return _readProtected(() => db!.memberDao.bulkUpdateMembers(members));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateMessages(String cid, List<Message> messages) {
|
||||
Future<void> bulkUpdateMessages(Map<String, List<Message>> messages) {
|
||||
assert(_debugIsConnected, '');
|
||||
_logger.info('updateMessages');
|
||||
return _readProtected(() => db!.messageDao.updateMessages(cid, messages));
|
||||
_logger.info('bulkUpdateMessages');
|
||||
return _readProtected(() => db!.messageDao.bulkUpdateMessages(messages));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePinnedMessages(String cid, List<Message> messages) {
|
||||
Future<void> bulkUpdatePinnedMessages(Map<String, List<Message>> messages) {
|
||||
assert(_debugIsConnected, '');
|
||||
_logger.info('updatePinnedMessages');
|
||||
_logger.info('bulkUpdatePinnedMessages');
|
||||
return _readProtected(
|
||||
() => db!.pinnedMessageDao.updateMessages(cid, messages),
|
||||
() => db!.pinnedMessageDao.bulkUpdateMessages(messages),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePinnedMessageReactions(List<Reaction> reactions) {
|
||||
assert(_debugIsConnected, '');
|
||||
_logger.info('updatePinnedMessageReactions');
|
||||
return _readProtected(
|
||||
() => db!.pinnedMessageReactionDao.updateReactions(reactions),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -326,10 +335,10 @@ class StreamChatPersistenceClient extends ChatPersistenceClient {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateReads(String cid, List<Read> reads) {
|
||||
Future<void> bulkUpdateReads(Map<String, List<Read>> reads) {
|
||||
assert(_debugIsConnected, '');
|
||||
_logger.info('updateReads');
|
||||
return _readProtected(() => db!.readDao.updateReads(cid, reads));
|
||||
_logger.info('bulkUpdateReads');
|
||||
return _readProtected(() => db!.readDao.bulkUpdateReads(reads));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -339,6 +348,18 @@ class StreamChatPersistenceClient extends ChatPersistenceClient {
|
||||
return _readProtected(() => db!.userDao.updateUsers(users));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deletePinnedMessageReactionsByMessageId(
|
||||
List<String> messageIds,
|
||||
) {
|
||||
assert(_debugIsConnected, '');
|
||||
_logger.info('deletePinnedMessageReactionsByMessageId');
|
||||
return _readProtected(
|
||||
() =>
|
||||
db!.pinnedMessageReactionDao.deleteReactionsByMessageIds(messageIds),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteReactionsByMessageId(List<String> messageIds) {
|
||||
assert(_debugIsConnected, '');
|
||||
|
||||
@@ -34,6 +34,12 @@ class MockChatDatabase extends Mock implements MoorChatDatabase {
|
||||
@override
|
||||
ReactionDao get reactionDao => _reactionDao ??= MockReactionDao();
|
||||
|
||||
PinnedMessageReactionDao? _pinnedMessageReactionDao;
|
||||
|
||||
@override
|
||||
PinnedMessageReactionDao get pinnedMessageReactionDao =>
|
||||
_pinnedMessageReactionDao ??= MockPinnedMessageReactionDao();
|
||||
|
||||
ReadDao? _readDao;
|
||||
|
||||
@override
|
||||
@@ -70,6 +76,9 @@ class MockMemberDao extends Mock implements MemberDao {}
|
||||
|
||||
class MockReactionDao extends Mock implements ReactionDao {}
|
||||
|
||||
class MockPinnedMessageReactionDao extends Mock
|
||||
implements PinnedMessageReactionDao {}
|
||||
|
||||
class MockReadDao extends Mock implements ReadDao {}
|
||||
|
||||
class MockChannelQueryDao extends Mock implements ChannelQueryDao {}
|
||||
|
||||
@@ -61,12 +61,73 @@ void main() {
|
||||
expect(updatedChannel.cid, cid);
|
||||
expect(updatedChannel.type, type);
|
||||
|
||||
//Saving a dummy user
|
||||
const userId = 'userId';
|
||||
final dummyUser = User(id: userId);
|
||||
await database.userDao.updateUsers([dummyUser]);
|
||||
|
||||
// Saving a dummy member
|
||||
final dummyMember = Member(userId: userId, user: dummyUser);
|
||||
await database.memberDao.updateMembers(cid, [dummyMember]);
|
||||
|
||||
// Should match the dummy member
|
||||
final updatedMembers = await database.memberDao.getMembersByCid(cid);
|
||||
expect(updatedMembers.length, 1);
|
||||
expect(updatedMembers.first.userId, userId);
|
||||
|
||||
// Saving a dummy message
|
||||
const messageId = 'messageId';
|
||||
final dummyMessage = Message(id: messageId, user: dummyUser);
|
||||
await database.messageDao.updateMessages(cid, [dummyMessage]);
|
||||
|
||||
// Should match the dummy message
|
||||
final updatedMessages = await database.messageDao.getMessagesByCid(cid);
|
||||
expect(updatedMessages.length, 1);
|
||||
expect(updatedMessages.first.id, messageId);
|
||||
|
||||
// Saving a dummy read
|
||||
final dummyRead = Read(lastRead: DateTime.now(), user: dummyUser);
|
||||
await database.readDao.updateReads(cid, [dummyRead]);
|
||||
|
||||
// Should match the dummy read
|
||||
final updatedReads = await database.readDao.getReadsByCid(cid);
|
||||
expect(updatedReads.length, 1);
|
||||
expect(updatedReads.first.user, dummyUser);
|
||||
|
||||
// Saving a dummy reaction
|
||||
final dummyReaction =
|
||||
Reaction(type: 'type', messageId: messageId, userId: userId);
|
||||
await database.reactionDao.updateReactions([dummyReaction]);
|
||||
|
||||
// Should match the dummy reaction
|
||||
final updatedReactions =
|
||||
await database.reactionDao.getReactionsByUserId(messageId, userId);
|
||||
expect(updatedReactions.length, 1);
|
||||
expect(updatedReactions.first.messageId, messageId);
|
||||
|
||||
// Deleting the dummyChannel using cid
|
||||
await channelDao.deleteChannelByCids([cid]);
|
||||
|
||||
// Fetched channel Should be null
|
||||
final channel = await channelDao.getChannelByCid(cid);
|
||||
expect(channel, isNull);
|
||||
|
||||
// Fetched members for passed cid should be empty
|
||||
final members = await database.memberDao.getMembersByCid(cid);
|
||||
expect(members, isEmpty);
|
||||
|
||||
// Fetched messages for passed cid should be empty
|
||||
final messages = await database.messageDao.getMessagesByCid(cid);
|
||||
expect(messages, isEmpty);
|
||||
|
||||
// Fetched reads for passed cid should be empty
|
||||
final reads = await database.readDao.getReadsByCid(cid);
|
||||
expect(reads, isEmpty);
|
||||
|
||||
// Fetched readtions for passed message id and user id should be empty
|
||||
final reactions =
|
||||
await database.reactionDao.getReactionsByUserId(messageId, userId);
|
||||
expect(reactions, isEmpty);
|
||||
});
|
||||
|
||||
test('cids', () async {
|
||||
|
||||
@@ -18,6 +18,7 @@ void main() {
|
||||
});
|
||||
|
||||
Future<List<Member>> _prepareTestData(String cid) async {
|
||||
final channels = [ChannelModel(cid: cid)];
|
||||
final users = List.generate(3, (index) => User(id: 'testUserId$index'));
|
||||
final memberList = List.generate(
|
||||
3,
|
||||
@@ -34,12 +35,13 @@ void main() {
|
||||
),
|
||||
);
|
||||
await database.userDao.updateUsers(users);
|
||||
await database.channelDao.updateChannels(channels);
|
||||
await memberDao.updateMembers(cid, memberList);
|
||||
return memberList;
|
||||
}
|
||||
|
||||
test('getMembersByCid', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Should be empty initially
|
||||
final members = await memberDao.getMembersByCid(cid);
|
||||
@@ -70,7 +72,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('updateMembers', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Preparing test data
|
||||
final memberList = await _prepareTestData(cid);
|
||||
@@ -132,7 +134,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('deleteMemberByCids', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Preparing test data
|
||||
final members = await _prepareTestData(cid);
|
||||
|
||||
@@ -23,6 +23,7 @@ void main() {
|
||||
bool mapAllThreadToFirstMessage = false,
|
||||
int count = 3,
|
||||
}) async {
|
||||
final channels = [ChannelModel(cid: cid)];
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final messages = List.generate(
|
||||
count,
|
||||
@@ -98,13 +99,20 @@ void main() {
|
||||
if (quoted) ...quotedMessages,
|
||||
if (threads) ...threadMessages
|
||||
];
|
||||
final reaction = Reaction(
|
||||
type: 'type',
|
||||
messageId: allMessages.first.id,
|
||||
user: users.first,
|
||||
);
|
||||
await database.userDao.updateUsers(users);
|
||||
await database.channelDao.updateChannels(channels);
|
||||
await messageDao.updateMessages(cid, allMessages);
|
||||
await database.reactionDao.updateReactions([reaction]);
|
||||
return allMessages;
|
||||
}
|
||||
|
||||
test('deleteMessageByIds', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(cid);
|
||||
@@ -113,66 +121,112 @@ void main() {
|
||||
final messages = await messageDao.getMessagesByCid(cid);
|
||||
expect(messages.length, insertedMessages.length);
|
||||
|
||||
final firstMessageId = messages.first.id;
|
||||
|
||||
// Fetched reactions list should have one reaction for given message id
|
||||
final reactions = await database.reactionDao.getReactions(firstMessageId);
|
||||
expect(reactions.length, 1);
|
||||
|
||||
// Deleting 2 messages from DB
|
||||
await messageDao.deleteMessageByIds(
|
||||
['testMessageId${cid}0', 'testMessageId${cid}1'],
|
||||
[firstMessageId, 'testMessageId${cid}1'],
|
||||
);
|
||||
|
||||
// New fetched messages length should 2 less than the
|
||||
// previous fetched messages
|
||||
final newMessages = await messageDao.getMessagesByCid(cid);
|
||||
expect(newMessages.length, messages.length - 2);
|
||||
|
||||
// Reaction for the first message should be deleted too
|
||||
final newReactions =
|
||||
await database.reactionDao.getReactions(firstMessageId);
|
||||
expect(newReactions, isEmpty);
|
||||
});
|
||||
|
||||
group('deleteMessageByCids', () {
|
||||
const cid1 = 'testCid1';
|
||||
const cid2 = 'testCid2';
|
||||
const cid1 = 'test:Cid1';
|
||||
const cid2 = 'test:Cid2';
|
||||
|
||||
test('should delete all the messages of first channel', () async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
test(
|
||||
'should delete all the messages and reactions of first channel',
|
||||
() async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await messageDao.deleteMessageByCids([cid1]);
|
||||
// Fetched reactions list should have one reaction for given message id
|
||||
final cid1firstMessageId = cid1Messages.first.id;
|
||||
final cid1Reactions =
|
||||
await database.reactionDao.getReactions(cid1firstMessageId);
|
||||
expect(cid1Reactions.length, 1);
|
||||
|
||||
// Fetched messages length of only cid1 should be empty
|
||||
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isNotEmpty);
|
||||
});
|
||||
// Deleting all the messages of cid1
|
||||
await messageDao.deleteMessageByCids([cid1]);
|
||||
|
||||
test('should delete all the messages of both channel', () async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
// Fetched messages length of only cid1 should be empty
|
||||
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isNotEmpty);
|
||||
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
// Reaction for the first message should be deleted too
|
||||
final cid1FetchedReactions =
|
||||
await database.reactionDao.getReactions(cid1firstMessageId);
|
||||
expect(cid1FetchedReactions, isEmpty);
|
||||
},
|
||||
);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await messageDao.deleteMessageByCids([cid1, cid2]);
|
||||
test(
|
||||
'should delete all the messages and reactions of both channel',
|
||||
() async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
|
||||
// Fetched messages length of both cid1 and cid2 should be empty
|
||||
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isEmpty);
|
||||
});
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
|
||||
// Fetched reactions list should have one reaction for given message id
|
||||
final cid1FirstMessageId = cid1Messages.first.id;
|
||||
final cid1Reactions =
|
||||
await database.reactionDao.getReactions(cid1FirstMessageId);
|
||||
expect(cid1Reactions.length, 1);
|
||||
final cid2FirstMessageId = cid2Messages.first.id;
|
||||
final cid2Reactions =
|
||||
await database.reactionDao.getReactions(cid2FirstMessageId);
|
||||
expect(cid2Reactions.length, 1);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await messageDao.deleteMessageByCids([cid1, cid2]);
|
||||
|
||||
// Fetched messages length of both cid1 and cid2 should be empty
|
||||
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isEmpty);
|
||||
|
||||
// Reaction for the first message should be deleted too
|
||||
final cid1FetchedReactions =
|
||||
await database.reactionDao.getReactions(cid1FirstMessageId);
|
||||
expect(cid1FetchedReactions, isEmpty);
|
||||
final cid2FetchedReactions =
|
||||
await database.reactionDao.getReactions(cid2FirstMessageId);
|
||||
expect(cid2FetchedReactions, isEmpty);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('getMessageById', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const id = 'testMessageId${cid}0';
|
||||
|
||||
// Should be null initially
|
||||
@@ -190,7 +244,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getThreadMessages', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Messages should be empty initially
|
||||
final messages = await messageDao.getThreadMessages(cid);
|
||||
@@ -209,7 +263,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getThreadMessagesByParentId', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const parentId = 'testMessageId${cid}0';
|
||||
|
||||
// Messages should be empty initially
|
||||
@@ -228,7 +282,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getThreadMessagesByParentId along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const parentId = 'testMessageId${cid}0';
|
||||
const options = PaginationParams(
|
||||
limit: 15,
|
||||
@@ -262,7 +316,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getMessagesByCid', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await messageDao.getMessagesByCid(cid);
|
||||
@@ -283,7 +337,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getMessagesByCid along with quotedMessage', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await messageDao.getMessagesByCid(cid);
|
||||
@@ -301,7 +355,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getMessagesByCid along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const limit = 15;
|
||||
const lessThan = 'testMessageId${cid}25';
|
||||
const greaterThanOrEqual = 'testMessageId${cid}5';
|
||||
@@ -333,7 +387,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('updateMessages', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(cid);
|
||||
|
||||
@@ -23,6 +23,7 @@ void main() {
|
||||
bool mapAllThreadToFirstMessage = false,
|
||||
int count = 3,
|
||||
}) async {
|
||||
final channels = [ChannelModel(cid: cid)];
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final messages = List.generate(
|
||||
count,
|
||||
@@ -83,13 +84,20 @@ void main() {
|
||||
if (quoted) ...quotedMessages,
|
||||
if (threads) ...threadMessages
|
||||
];
|
||||
final reaction = Reaction(
|
||||
type: 'type',
|
||||
messageId: allMessages.first.id,
|
||||
user: users.first,
|
||||
);
|
||||
await database.userDao.updateUsers(users);
|
||||
await database.channelDao.updateChannels(channels);
|
||||
await pinnedMessageDao.updateMessages(cid, allMessages);
|
||||
await database.pinnedMessageReactionDao.updateReactions([reaction]);
|
||||
return allMessages;
|
||||
}
|
||||
|
||||
test('deleteMessageByIds', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(cid);
|
||||
@@ -98,66 +106,117 @@ void main() {
|
||||
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||
expect(messages.length, insertedMessages.length);
|
||||
|
||||
final firstMessageId = messages.first.id;
|
||||
|
||||
// Fetched reactions list should have one reaction for given message id
|
||||
final reactions =
|
||||
await database.pinnedMessageReactionDao.getReactions(firstMessageId);
|
||||
expect(reactions.length, 1);
|
||||
|
||||
// Deleting 2 messages from DB
|
||||
await pinnedMessageDao.deleteMessageByIds(
|
||||
['testMessageId${cid}0', 'testMessageId${cid}1'],
|
||||
[firstMessageId, 'testMessageId${cid}1'],
|
||||
);
|
||||
|
||||
// New fetched messages length should 2 less than the
|
||||
// previous fetched messages
|
||||
final newMessages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||
expect(newMessages.length, messages.length - 2);
|
||||
|
||||
// Reaction for the first message should be deleted too
|
||||
final newReactions =
|
||||
await database.pinnedMessageReactionDao.getReactions(firstMessageId);
|
||||
expect(newReactions, isEmpty);
|
||||
});
|
||||
|
||||
group('deleteMessageByCids', () {
|
||||
const cid1 = 'testCid1';
|
||||
const cid2 = 'testCid2';
|
||||
const cid1 = 'test:Cid1';
|
||||
const cid2 = 'test:Cid2';
|
||||
|
||||
test('should delete all the messages of first channel', () async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
test(
|
||||
'should delete all the messages and reactions of first channel',
|
||||
() async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await pinnedMessageDao.deleteMessageByCids([cid1]);
|
||||
// Fetched reactions list should have one reaction for given message id
|
||||
final cid1firstMessageId = cid1Messages.first.id;
|
||||
final cid1Reactions = await database.pinnedMessageReactionDao
|
||||
.getReactions(cid1firstMessageId);
|
||||
expect(cid1Reactions.length, 1);
|
||||
|
||||
// Fetched messages length of only cid1 should be empty
|
||||
final cid1FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isNotEmpty);
|
||||
});
|
||||
// Deleting all the messages of cid1
|
||||
await pinnedMessageDao.deleteMessageByCids([cid1]);
|
||||
|
||||
test('should delete all the messages of both channel', () async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
// Fetched messages length of only cid1 should be empty
|
||||
final cid1FetchedMessages =
|
||||
await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages =
|
||||
await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isNotEmpty);
|
||||
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
// Reaction for the first message should be deleted too
|
||||
final cid1FetchedReactions = await database.pinnedMessageReactionDao
|
||||
.getReactions(cid1firstMessageId);
|
||||
expect(cid1FetchedReactions, isEmpty);
|
||||
},
|
||||
);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await pinnedMessageDao.deleteMessageByCids([cid1, cid2]);
|
||||
test(
|
||||
'should delete all the messages and reactions of both channel',
|
||||
() async {
|
||||
// Preparing test data
|
||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||
|
||||
// Fetched messages length of both cid1 and cid2 should be empty
|
||||
final cid1FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isEmpty);
|
||||
});
|
||||
// Fetched message list should match the test message list length
|
||||
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
|
||||
// Fetched reactions list should have one reaction for given message id
|
||||
final cid1FirstMessageId = cid1Messages.first.id;
|
||||
final cid1Reactions = await database.pinnedMessageReactionDao
|
||||
.getReactions(cid1FirstMessageId);
|
||||
expect(cid1Reactions.length, 1);
|
||||
final cid2FirstMessageId = cid2Messages.first.id;
|
||||
final cid2Reactions = await database.pinnedMessageReactionDao
|
||||
.getReactions(cid2FirstMessageId);
|
||||
expect(cid2Reactions.length, 1);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await pinnedMessageDao.deleteMessageByCids([cid1, cid2]);
|
||||
|
||||
// Fetched messages length of both cid1 and cid2 should be empty
|
||||
final cid1FetchedMessages =
|
||||
await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages =
|
||||
await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1FetchedMessages, isEmpty);
|
||||
expect(cid2FetchedMessages, isEmpty);
|
||||
|
||||
// Reaction for the first message should be deleted too
|
||||
final cid1FetchedReactions = await database.pinnedMessageReactionDao
|
||||
.getReactions(cid1FirstMessageId);
|
||||
expect(cid1FetchedReactions, isEmpty);
|
||||
final cid2FetchedReactions = await database.pinnedMessageReactionDao
|
||||
.getReactions(cid2FirstMessageId);
|
||||
expect(cid2FetchedReactions, isEmpty);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('getMessageById', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const id = 'testMessageId${cid}0';
|
||||
|
||||
// Should be null initially
|
||||
@@ -175,7 +234,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getThreadMessages', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Messages should be empty initially
|
||||
final messages = await pinnedMessageDao.getThreadMessages(cid);
|
||||
@@ -194,7 +253,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getThreadMessagesByParentId', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const parentId = 'testMessageId${cid}0';
|
||||
|
||||
// Messages should be empty initially
|
||||
@@ -214,7 +273,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getThreadMessagesByParentId along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const parentId = 'testMessageId${cid}0';
|
||||
const options = PaginationParams(
|
||||
limit: 15,
|
||||
@@ -248,7 +307,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getMessagesByCid', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||
@@ -269,7 +328,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getMessagesByCid along with quotedMessage', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||
@@ -287,7 +346,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('getMessagesByCid along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
const limit = 15;
|
||||
const lessThan = 'testMessageId${cid}25';
|
||||
const greaterThanOrEqual = 'testMessageId${cid}5';
|
||||
@@ -319,7 +378,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('updateMessages', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(cid);
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/dao/pinned_message_reaction_dao.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../../stream_chat_persistence_client_test.dart';
|
||||
|
||||
void main() {
|
||||
late PinnedMessageReactionDao pinnedMessageReactionDao;
|
||||
late MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = testDatabaseProvider('testUserId');
|
||||
pinnedMessageReactionDao = database.pinnedMessageReactionDao;
|
||||
});
|
||||
|
||||
Future<List<Reaction>> _prepareReactionData(
|
||||
String messageId, {
|
||||
String? userId,
|
||||
int count = 3,
|
||||
}) async {
|
||||
const cid = 'test:Cid';
|
||||
final channels = [ChannelModel(cid: cid)];
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final message = Message(
|
||||
id: messageId,
|
||||
type: 'testType',
|
||||
user: users.first,
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
showInChannel: math.Random().nextBool(),
|
||||
replyCount: 3,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: const {'extra_test_field': 'extraTestData'},
|
||||
text: 'Dummy text',
|
||||
pinned: math.Random().nextBool(),
|
||||
pinnedAt: DateTime.now(),
|
||||
pinnedBy: users.first,
|
||||
);
|
||||
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'},
|
||||
),
|
||||
);
|
||||
|
||||
await database.userDao.updateUsers(users);
|
||||
await database.channelDao.updateChannels(channels);
|
||||
await database.pinnedMessageDao.updateMessages(cid, [message]);
|
||||
await pinnedMessageReactionDao.updateReactions(reactions);
|
||||
|
||||
return reactions;
|
||||
}
|
||||
|
||||
test('getReactions', () async {
|
||||
const messageId = 'testMessageId';
|
||||
|
||||
// Should be empty initially
|
||||
final reactions = await pinnedMessageReactionDao.getReactions(messageId);
|
||||
expect(reactions, isEmpty);
|
||||
|
||||
// Adding sample reactions
|
||||
final insertedReactions = await _prepareReactionData(messageId);
|
||||
expect(insertedReactions, isNotEmpty);
|
||||
|
||||
// Fetched reaction length should match inserted reactions length.
|
||||
// Every reaction messageId should match the provided messageId.
|
||||
final fetchedReactions =
|
||||
await pinnedMessageReactionDao.getReactions(messageId);
|
||||
expect(fetchedReactions.length, insertedReactions.length);
|
||||
expect(fetchedReactions.every((it) => it.messageId == messageId), true);
|
||||
});
|
||||
|
||||
test('getReactionsByUserId', () async {
|
||||
const messageId = 'testMessageId';
|
||||
const userId = 'testUserId';
|
||||
|
||||
// Should be empty initially
|
||||
final reactions =
|
||||
await pinnedMessageReactionDao.getReactionsByUserId(messageId, userId);
|
||||
expect(reactions, isEmpty);
|
||||
|
||||
// Adding sample reactions
|
||||
final insertedReactions =
|
||||
await _prepareReactionData(messageId, userId: userId);
|
||||
expect(insertedReactions, isNotEmpty);
|
||||
|
||||
// Fetched reaction length should match inserted reactions length.
|
||||
// Every reaction messageId should match the provided messageId.
|
||||
// Every reaction userId should match the provided userId.
|
||||
final fetchedReactions =
|
||||
await pinnedMessageReactionDao.getReactionsByUserId(messageId, userId);
|
||||
expect(fetchedReactions.length, insertedReactions.length);
|
||||
expect(fetchedReactions.every((it) => it.messageId == messageId), true);
|
||||
expect(fetchedReactions.every((it) => it.userId == userId), true);
|
||||
});
|
||||
|
||||
test('updateReactions', () async {
|
||||
const messageId = 'testMessageId';
|
||||
|
||||
// Preparing test data
|
||||
final reactions = await _prepareReactionData(messageId);
|
||||
|
||||
// Modifying one of the reaction and also adding one new
|
||||
final copyReaction = reactions.first.copyWith(score: 33);
|
||||
final newReaction = Reaction(
|
||||
type: 'testType3',
|
||||
createdAt: DateTime.now(),
|
||||
userId: 'testUserId3',
|
||||
messageId: messageId,
|
||||
score: 30,
|
||||
extraData: {'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.
|
||||
// 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,
|
||||
);
|
||||
expect(
|
||||
fetchedReactions
|
||||
.where((it) =>
|
||||
it.userId == newReaction.userId && it.type == newReaction.type)
|
||||
.isNotEmpty,
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
group('deleteReactionsByMessageIds', () {
|
||||
const messageId1 = 'testMessageId1';
|
||||
const messageId2 = 'testMessageId2';
|
||||
test('should delete all the reactions of first message', () async {
|
||||
// Preparing test data
|
||||
final insertedReactions1 = await _prepareReactionData(messageId1);
|
||||
final insertedReactions2 = await _prepareReactionData(messageId2);
|
||||
|
||||
// Fetched reaction list length should match
|
||||
// the inserted reactions list length
|
||||
final reactions1 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId1);
|
||||
final reactions2 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId2);
|
||||
expect(reactions1.length, insertedReactions1.length);
|
||||
expect(reactions2.length, insertedReactions2.length);
|
||||
|
||||
// Deleting all the reactions of messageId1
|
||||
await pinnedMessageReactionDao.deleteReactionsByMessageIds([messageId1]);
|
||||
|
||||
// Fetched reactions length of only messageId1 should be empty
|
||||
final fetchedReactions1 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId1);
|
||||
final fetchedReactions2 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId2);
|
||||
expect(fetchedReactions1, isEmpty);
|
||||
expect(fetchedReactions2, isNotEmpty);
|
||||
});
|
||||
test('should delete all the messages of both message', () async {
|
||||
// Preparing test data
|
||||
final insertedReactions1 = await _prepareReactionData(messageId1);
|
||||
final insertedReactions2 = await _prepareReactionData(messageId2);
|
||||
|
||||
// Fetched reaction list length should match
|
||||
// the inserted reactions list length
|
||||
final reactions1 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId1);
|
||||
final reactions2 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId2);
|
||||
expect(reactions1.length, insertedReactions1.length);
|
||||
expect(reactions2.length, insertedReactions2.length);
|
||||
|
||||
// Deleting all the reactions of messageId1 and messageId2
|
||||
await pinnedMessageReactionDao
|
||||
.deleteReactionsByMessageIds([messageId1, messageId2]);
|
||||
|
||||
// Fetched reactions length of both messages should be empty
|
||||
final fetchedReactions1 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId1);
|
||||
final fetchedReactions2 =
|
||||
await pinnedMessageReactionDao.getReactions(messageId2);
|
||||
expect(fetchedReactions1, isEmpty);
|
||||
expect(fetchedReactions2, isEmpty);
|
||||
});
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -21,6 +21,8 @@ void main() {
|
||||
String? userId,
|
||||
int count = 3,
|
||||
}) async {
|
||||
const cid = 'test:Cid';
|
||||
final channels = [ChannelModel(cid: cid)];
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final message = Message(
|
||||
id: messageId,
|
||||
@@ -50,7 +52,8 @@ void main() {
|
||||
);
|
||||
|
||||
await database.userDao.updateUsers(users);
|
||||
await database.messageDao.updateMessages('testCid', [message]);
|
||||
await database.channelDao.updateChannels(channels);
|
||||
await database.messageDao.updateMessages(cid, [message]);
|
||||
await reactionDao.updateReactions(reactions);
|
||||
|
||||
return reactions;
|
||||
|
||||
@@ -16,6 +16,7 @@ void main() {
|
||||
});
|
||||
|
||||
Future<List<Read>> _prepareReadData(String cid, {int count = 3}) async {
|
||||
final channels = [ChannelModel(cid: cid)];
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final reads = List.generate(
|
||||
count,
|
||||
@@ -27,12 +28,13 @@ void main() {
|
||||
);
|
||||
|
||||
await database.userDao.updateUsers(users);
|
||||
await database.channelDao.updateChannels(channels);
|
||||
await readDao.updateReads(cid, reads);
|
||||
return reads;
|
||||
}
|
||||
|
||||
test('getReadsByCid', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Should be empty initially
|
||||
final reads = await readDao.getReadsByCid(cid);
|
||||
@@ -55,7 +57,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('updateReads', () async {
|
||||
const cid = 'testCid';
|
||||
const cid = 'test:Cid';
|
||||
|
||||
// Preparing test data
|
||||
final insertedReads = await _prepareReadData(cid);
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/pinned_message_reaction_mapper.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
test('toReaction should map the entity into Reaction', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final message = Message(id: 'testMessageId');
|
||||
final entity = PinnedMessageReactionEntity(
|
||||
userId: user.id,
|
||||
messageId: message.id,
|
||||
type: 'haha',
|
||||
score: 33,
|
||||
createdAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
);
|
||||
|
||||
final reaction = entity.toReaction(user: user);
|
||||
expect(reaction, isA<Reaction>());
|
||||
expect(reaction.userId, entity.userId);
|
||||
expect(reaction.messageId, entity.messageId);
|
||||
expect(reaction.type, entity.type);
|
||||
expect(reaction.score, entity.score);
|
||||
expect(reaction.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(reaction.extraData, entity.extraData);
|
||||
});
|
||||
|
||||
test('toEntity should map reaction into PinnedMessageReactionEntity', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final message = Message(id: 'testMessageId');
|
||||
final reaction = Reaction(
|
||||
userId: user.id,
|
||||
messageId: message.id,
|
||||
type: 'haha',
|
||||
score: 33,
|
||||
createdAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
);
|
||||
|
||||
final entity = reaction.toPinnedEntity();
|
||||
expect(entity, isA<PinnedMessageReactionEntity>());
|
||||
expect(entity.userId, reaction.userId);
|
||||
expect(entity.messageId, reaction.messageId);
|
||||
expect(entity.type, reaction.type);
|
||||
expect(entity.score, reaction.score);
|
||||
expect(entity.createdAt, isSameDateAs(reaction.createdAt));
|
||||
expect(entity.extraData, reaction.extraData);
|
||||
});
|
||||
}
|
||||
@@ -397,23 +397,26 @@ void main() {
|
||||
test('updateMessages', () async {
|
||||
const cid = 'testCid';
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
when(() => mockDatabase.messageDao.updateMessages(cid, messages))
|
||||
|
||||
when(() => mockDatabase.messageDao.bulkUpdateMessages({cid: messages}))
|
||||
.thenAnswer((_) => Future.value());
|
||||
|
||||
await client.updateMessages(cid, messages);
|
||||
verify(() => mockDatabase.messageDao.updateMessages(cid, messages))
|
||||
verify(() => mockDatabase.messageDao.bulkUpdateMessages({cid: messages}))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('updatePinnedMessages', () async {
|
||||
const cid = 'testCid';
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
when(() => mockDatabase.pinnedMessageDao.updateMessages(cid, messages))
|
||||
.thenAnswer((_) => Future.value());
|
||||
when(
|
||||
() => mockDatabase.pinnedMessageDao.bulkUpdateMessages({cid: messages}),
|
||||
).thenAnswer((_) => Future.value());
|
||||
|
||||
await client.updatePinnedMessages(cid, messages);
|
||||
verify(() => mockDatabase.pinnedMessageDao.updateMessages(cid, messages))
|
||||
.called(1);
|
||||
verify(
|
||||
() => mockDatabase.pinnedMessageDao.bulkUpdateMessages({cid: messages}),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('getChannelThreads', () async {
|
||||
@@ -456,11 +459,11 @@ void main() {
|
||||
test('updateMembers', () async {
|
||||
const cid = 'testCid';
|
||||
final members = List.generate(3, (index) => Member());
|
||||
when(() => mockDatabase.memberDao.updateMembers(cid, members))
|
||||
when(() => mockDatabase.memberDao.bulkUpdateMembers({cid: members}))
|
||||
.thenAnswer((_) => Future.value());
|
||||
|
||||
await client.updateMembers(cid, members);
|
||||
verify(() => mockDatabase.memberDao.updateMembers(cid, members))
|
||||
verify(() => mockDatabase.memberDao.bulkUpdateMembers({cid: members}))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
@@ -473,11 +476,12 @@ void main() {
|
||||
lastRead: DateTime.now(),
|
||||
),
|
||||
);
|
||||
when(() => mockDatabase.readDao.updateReads(cid, reads))
|
||||
when(() => mockDatabase.readDao.bulkUpdateReads({cid: reads}))
|
||||
.thenAnswer((_) => Future.value());
|
||||
|
||||
await client.updateReads(cid, reads);
|
||||
verify(() => mockDatabase.readDao.updateReads(cid, reads)).called(1);
|
||||
verify(() => mockDatabase.readDao.bulkUpdateReads({cid: reads}))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('updateUsers', () async {
|
||||
@@ -502,6 +506,21 @@ void main() {
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('updatePinnedMessageReactions', () async {
|
||||
final reactions = List.generate(
|
||||
3,
|
||||
(index) => Reaction(type: 'testType$index'),
|
||||
);
|
||||
when(() =>
|
||||
mockDatabase.pinnedMessageReactionDao.updateReactions(reactions))
|
||||
.thenAnswer((_) => Future.value());
|
||||
|
||||
await client.updatePinnedMessageReactions(reactions);
|
||||
verify(() =>
|
||||
mockDatabase.pinnedMessageReactionDao.updateReactions(reactions))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteReactionsByMessageId', () async {
|
||||
final messageIds = <String>[];
|
||||
when(() =>
|
||||
@@ -514,6 +533,17 @@ void main() {
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deletePinnedMessageReactionsByMessageId', () async {
|
||||
final messageIds = <String>[];
|
||||
when(() => mockDatabase.pinnedMessageReactionDao
|
||||
.deleteReactionsByMessageIds(messageIds))
|
||||
.thenAnswer((_) => Future.value());
|
||||
|
||||
await client.deletePinnedMessageReactionsByMessageId(messageIds);
|
||||
verify(() => mockDatabase.pinnedMessageReactionDao
|
||||
.deleteReactionsByMessageIds(messageIds)).called(1);
|
||||
});
|
||||
|
||||
test('deleteMembersByCids', () async {
|
||||
final cids = <String>[];
|
||||
when(() => mockDatabase.memberDao.deleteMemberByCids(cids))
|
||||
|
||||
Reference in New Issue
Block a user