Merge branch 'develop' into fix/message-search-pagination
This commit is contained in:
@@ -107,6 +107,48 @@ The 'exists' filter matches values that exist, or don't exist, based on the spec
|
|||||||
Filter.exists('name', true)
|
Filter.exists('name', true)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Filter.contains
|
||||||
|
|
||||||
|
The 'contains' filter matches any list that contains the specified value.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Filter.contains('teams', 'red')
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filter.empty
|
||||||
|
|
||||||
|
The 'empty' filter constructor returns an empty filter. It's the equivalent of an empty map `{}`;
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Filter.empty();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filter.raw
|
||||||
|
|
||||||
|
The 'raw' filter constructor lets you specify a raw filter. We suggest using this only if you can't manage to build what you want using the other constructors.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Filter.raw(value: {
|
||||||
|
'members': [
|
||||||
|
..._selectedUsers.map((e) => e.id),
|
||||||
|
chatState.currentUser!.id,
|
||||||
|
],
|
||||||
|
'distinct': true,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Filter.custom
|
||||||
|
|
||||||
|
The 'custom' filter is used to create a custom filter in case it does not exists or it's not been added to the SDK yet.
|
||||||
|
Note that the filter must be supported by the Stream backend in order to work.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Filter.custom(
|
||||||
|
operator: '\$max',
|
||||||
|
value: 10,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
### Group Queries
|
### Group Queries
|
||||||
|
|
||||||
#### Filter.and
|
#### Filter.and
|
||||||
|
|||||||
@@ -1,8 +1,20 @@
|
|||||||
## Upcoming
|
## Upcoming
|
||||||
|
|
||||||
|
🛑️ Breaking Changes from `2.2.1`
|
||||||
|
|
||||||
|
- Added 6 new methods in `ChatPersistenceClient`.
|
||||||
|
- `bulkUpdateMessages`
|
||||||
|
- `bulkUpdatePinnedMessages`
|
||||||
|
- `bulkUpdateMembers`
|
||||||
|
- `bulkUpdateReads`
|
||||||
|
- `updatePinnedMessageReactions`
|
||||||
|
- `deletePinnedMessageReactionsByMessageId`
|
||||||
|
|
||||||
✅ Added
|
✅ Added
|
||||||
|
|
||||||
- Add support for `next`, `previous` value pagination in `client.search`, [read more.](https://getstream.io/chat/docs/other-rest/search/#pagination)
|
- Added `Filter.contains` and `Filter.empty`
|
||||||
|
- Added support for `next`, `previous` value pagination in `client.search`
|
||||||
|
, [read more.](https://getstream.io/chat/docs/other-rest/search/#pagination)
|
||||||
|
|
||||||
## 2.2.1
|
## 2.2.1
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ enum FilterOperator {
|
|||||||
|
|
||||||
/// Matches none of the values specified in an array.
|
/// Matches none of the values specified in an array.
|
||||||
nor,
|
nor,
|
||||||
|
|
||||||
|
/// Matches any list that contains the specified value
|
||||||
|
contains,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper extension for [FilterOperator]
|
/// Helper extension for [FilterOperator]
|
||||||
@@ -71,6 +74,7 @@ extension FilterOperatorX on FilterOperator {
|
|||||||
FilterOperator.and: '\$and',
|
FilterOperator.and: '\$and',
|
||||||
FilterOperator.or: '\$or',
|
FilterOperator.or: '\$or',
|
||||||
FilterOperator.nor: '\$nor',
|
FilterOperator.nor: '\$nor',
|
||||||
|
FilterOperator.contains: '\$contains',
|
||||||
}[this]!;
|
}[this]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +161,10 @@ class Filter extends Equatable {
|
|||||||
factory Filter.exists(String key, {bool exists = true}) =>
|
factory Filter.exists(String key, {bool exists = true}) =>
|
||||||
Filter._(operator: FilterOperator.exists, key: key, value: exists);
|
Filter._(operator: FilterOperator.exists, key: key, value: exists);
|
||||||
|
|
||||||
|
/// Matches any list that contains the specified values
|
||||||
|
factory Filter.contains(String key, Object value) =>
|
||||||
|
Filter._(operator: FilterOperator.contains, key: key, value: value);
|
||||||
|
|
||||||
/// Creates a custom [Filter] if there isn't one already available.
|
/// Creates a custom [Filter] if there isn't one already available.
|
||||||
const factory Filter.custom({
|
const factory Filter.custom({
|
||||||
required Object value,
|
required Object value,
|
||||||
@@ -164,6 +172,9 @@ class Filter extends Equatable {
|
|||||||
String? key,
|
String? key,
|
||||||
}) = Filter.__;
|
}) = Filter.__;
|
||||||
|
|
||||||
|
/// An empty filter
|
||||||
|
factory Filter.empty() => const Filter.raw(value: {});
|
||||||
|
|
||||||
/// Creates a custom [Filter] from a raw map value
|
/// Creates a custom [Filter] from a raw map value
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
|
|||||||
@@ -143,11 +143,19 @@ abstract class ChatPersistenceClient {
|
|||||||
|
|
||||||
/// Updates the message data of a particular channel [cid] with
|
/// Updates the message data of a particular channel [cid] with
|
||||||
/// the new [messages] data
|
/// 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
|
/// Updates the pinned message data of a particular channel [cid] with
|
||||||
/// the new [messages] data
|
/// 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
|
/// Returns all the threads by parent message of a particular channel by
|
||||||
/// providing channel [cid]
|
/// providing channel [cid]
|
||||||
@@ -158,11 +166,19 @@ abstract class ChatPersistenceClient {
|
|||||||
|
|
||||||
/// Updates all the members of a particular channle [cid]
|
/// Updates all the members of a particular channle [cid]
|
||||||
/// with the new [members] data
|
/// 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
|
/// Updates the read data of a particular channel [cid] with
|
||||||
/// the new [reads] data
|
/// 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
|
/// Updates the users data with the new [users] data
|
||||||
Future<void> updateUsers(List<User> users);
|
Future<void> updateUsers(List<User> users);
|
||||||
@@ -170,9 +186,15 @@ abstract class ChatPersistenceClient {
|
|||||||
/// Updates the reactions data with the new [reactions] data
|
/// Updates the reactions data with the new [reactions] data
|
||||||
Future<void> updateReactions(List<Reaction> reactions);
|
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]
|
/// Deletes all the reactions by [messageIds]
|
||||||
Future<void> deleteReactionsByMessageId(List<String> 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]
|
/// Deletes all the members by channel [cids]
|
||||||
Future<void> deleteMembersByCids(List<String> cids);
|
Future<void> deleteMembersByCids(List<String> cids);
|
||||||
|
|
||||||
@@ -182,85 +204,92 @@ abstract class ChatPersistenceClient {
|
|||||||
|
|
||||||
/// Update list of channel states
|
/// Update list of channel states
|
||||||
Future<void> updateChannelStates(List<ChannelState> channelStates) async {
|
Future<void> updateChannelStates(List<ChannelState> channelStates) async {
|
||||||
final deleteReactions = deleteReactionsByMessageId(channelStates
|
final reactionsToDelete = <String>[];
|
||||||
.expand((it) => it.messages)
|
final pinnedReactionsToDelete = <String>[];
|
||||||
.map((m) => m.id)
|
final membersToDelete = <String>[];
|
||||||
.toList(growable: false));
|
|
||||||
|
|
||||||
final cleanedChannelStates =
|
final channels = <ChannelModel>[];
|
||||||
channelStates.where((it) => it.channel != null);
|
final channelWithMessages = <String, List<Message>>{};
|
||||||
|
final channelWithPinnedMessages = <String, List<Message>>{};
|
||||||
|
final channelWithReads = <String, List<Read>>{};
|
||||||
|
final channelWithMembers = <String, List<Member>>{};
|
||||||
|
|
||||||
final deleteMembers = deleteMembersByCids(
|
final users = <User>[];
|
||||||
cleanedChannelStates.map((it) => it.channel!.cid).toList(growable: false),
|
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([
|
await Future.wait([
|
||||||
deleteReactions,
|
deleteMembersByCids(membersToDelete),
|
||||||
deleteMembers,
|
deleteReactionsByMessageId(reactionsToDelete),
|
||||||
|
deletePinnedMessageReactionsByMessageId(pinnedReactionsToDelete),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
final channels = cleanedChannelStates.map((it) => it.channel).withNullifyer;
|
// Updating first as does not depend on any other table.
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
await Future.wait([
|
await Future.wait([
|
||||||
...updateMessagesFuture,
|
|
||||||
...updatePinnedMessagesFuture,
|
|
||||||
...updateReadsFuture,
|
|
||||||
...updateMembersFuture,
|
|
||||||
updateUsers(users.toList(growable: false)),
|
updateUsers(users.toList(growable: false)),
|
||||||
updateChannels(channels.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)),
|
updateReactions(reactions.toList(growable: false)),
|
||||||
|
updatePinnedMessageReactions(
|
||||||
|
pinnedReactions.toList(growable: false),
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,6 +138,20 @@ void main() {
|
|||||||
expect(filter.value, value);
|
expect(filter.value, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('empty', () {
|
||||||
|
final filter = Filter.empty();
|
||||||
|
expect(filter.value, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('contains', () {
|
||||||
|
const key = 'testKey';
|
||||||
|
const values = 'testValue';
|
||||||
|
final filter = Filter.contains(key, values);
|
||||||
|
expect(filter.key, key);
|
||||||
|
expect(filter.value, values);
|
||||||
|
expect(filter.operator, FilterOperator.contains.rawValue);
|
||||||
|
});
|
||||||
|
|
||||||
group('groupedOperator', () {
|
group('groupedOperator', () {
|
||||||
final filter1 = Filter.equal('testKey', 'testValue');
|
final filter1 = Filter.equal('testKey', 'testValue');
|
||||||
final filter2 = Filter.in_('testKey', const ['testValue']);
|
final filter2 = Filter.in_('testKey', const ['testValue']);
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ class TestPersistenceClient extends ChatPersistenceClient {
|
|||||||
Future<void> deleteReactionsByMessageId(List<String> messageIds) =>
|
Future<void> deleteReactionsByMessageId(List<String> messageIds) =>
|
||||||
Future.value();
|
Future.value();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deletePinnedMessageReactionsByMessageId(
|
||||||
|
List<String> messageIds) =>
|
||||||
|
Future.value();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> disconnect({bool flush = false}) => throw UnimplementedError();
|
Future<void> disconnect({bool flush = false}) => throw UnimplementedError();
|
||||||
|
|
||||||
@@ -101,26 +106,30 @@ class TestPersistenceClient extends ChatPersistenceClient {
|
|||||||
Future<void> updateLastSyncAt(DateTime lastSyncAt) =>
|
Future<void> updateLastSyncAt(DateTime lastSyncAt) =>
|
||||||
throw UnimplementedError();
|
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
|
@override
|
||||||
Future<void> updateReactions(List<Reaction> reactions) => Future.value();
|
Future<void> updateReactions(List<Reaction> reactions) => Future.value();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updateReads(String cid, List<Read> reads) => Future.value();
|
Future<void> updatePinnedMessageReactions(List<Reaction> reactions) =>
|
||||||
|
Future.value();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updateUsers(List<User> users) => Future.value();
|
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() {
|
void main() {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import 'package:stream_chat_flutter/src/group_avatar.dart';
|
|||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows the current [Channel] image.
|
/// It shows the current [Channel] image.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
|||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
import 'package:stream_chat_flutter/src/extension.dart';
|
import 'package:stream_chat_flutter/src/extension.dart';
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows the current [Channel] information.
|
/// It shows the current [Channel] information.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ typedef ChannelPreviewBuilder = Widget Function(BuildContext, Channel);
|
|||||||
/// Callback for when 'View Info' is tapped
|
/// Callback for when 'View Info' is tapped
|
||||||
typedef ViewInfoCallback = void Function(Channel);
|
typedef ViewInfoCallback = void Function(Channel);
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows the list of current channels.
|
/// It shows the list of current channels.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
|
|||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows the current [Channel] preview.
|
/// It shows the current [Channel] preview.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -110,11 +110,14 @@ const _kMinMediaPickerSize = 360.0;
|
|||||||
const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
|
const _kDefaultMaxAttachmentSize = 20971520; // 20MB in Bytes
|
||||||
|
|
||||||
/// Inactive state
|
/// Inactive state
|
||||||
/// 
|
///
|
||||||
/// 
|
/// 
|
||||||
|
/// 
|
||||||
|
///
|
||||||
/// Focused state
|
/// Focused state
|
||||||
/// 
|
///
|
||||||
/// 
|
/// 
|
||||||
|
/// 
|
||||||
///
|
///
|
||||||
/// Widget used to enter the message and add attachments
|
/// Widget used to enter the message and add attachments
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ class MessageDetails {
|
|||||||
final int index;
|
final int index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows the list of messages of the current channel.
|
/// It shows the list of messages of the current channel.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ enum DisplayWidget {
|
|||||||
show,
|
show,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows a message with reactions, replies and user avatar.
|
/// It shows a message with reactions, replies and user avatar.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:stream_chat_flutter/src/extension.dart';
|
import 'package:stream_chat_flutter/src/extension.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows a reaction picker
|
/// It shows a reaction picker
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
|||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
import 'package:stream_chat_flutter/src/extension.dart';
|
import 'package:stream_chat_flutter/src/extension.dart';
|
||||||
|
|
||||||
/// 
|
/// 
|
||||||
/// 
|
/// 
|
||||||
///
|
///
|
||||||
/// It shows the current thread information.
|
/// It shows the current thread information.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -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
|
## 2.2.0
|
||||||
|
|
||||||
- Updated llc dependency
|
- Updated llc dependency
|
||||||
@@ -11,14 +18,17 @@
|
|||||||
## 2.1.0
|
## 2.1.0
|
||||||
|
|
||||||
✅ Added
|
✅ Added
|
||||||
|
|
||||||
- Added support for `Message.i18n`
|
- Added support for `Message.i18n`
|
||||||
- Added support for `User.language`
|
- Added support for `User.language`
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
* Migrate this package to null safety
|
* Migrate this package to null safety
|
||||||
* Minor fixes and improvements
|
* Minor fixes and improvements
|
||||||
|
|
||||||
## 2.0.0-nullsafety.8
|
## 2.0.0-nullsafety.8
|
||||||
|
|
||||||
* Updated llc dependency
|
* Updated llc dependency
|
||||||
* Upgraded moor dependencies and generated files with the latest 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
|
/// Updates all the channels using the new [channelList] data
|
||||||
Future<void> updateChannels(List<ChannelModel> channelList) => batch(
|
Future<void> updateChannels(List<ChannelModel> channelList) => batch(
|
||||||
(it) => it.insertAll(
|
(it) => it.insertAllOnConflictUpdate(
|
||||||
channels,
|
channels,
|
||||||
channelList.map((c) => c.toEntity()).toList(),
|
channelList.map((c) => c.toEntity()).toList(),
|
||||||
mode: InsertMode.insertOrReplace,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,13 +45,12 @@ class ChannelQueryDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
}
|
}
|
||||||
|
|
||||||
await batch((it) {
|
await batch((it) {
|
||||||
it.insertAll(
|
it.insertAllOnConflictUpdate(
|
||||||
channelQueries,
|
channelQueries,
|
||||||
cids
|
cids
|
||||||
.map((cid) =>
|
.map((cid) =>
|
||||||
ChannelQueryEntity(queryHash: hash, channelCid: cid))
|
ChannelQueryEntity(queryHash: hash, channelCid: cid))
|
||||||
.toList(),
|
.toList(),
|
||||||
mode: InsertMode.insertOrReplace,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class ConnectionEventDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
/// Update stored connection event with latest data
|
/// Update stored connection event with latest data
|
||||||
Future<int> updateConnectionEvent(Event event) => transaction(() async {
|
Future<int> updateConnectionEvent(Event event) => transaction(() async {
|
||||||
final connectionInfo = await select(connectionEvents).getSingleOrNull();
|
final connectionInfo = await select(connectionEvents).getSingleOrNull();
|
||||||
return into(connectionEvents).insert(
|
return into(connectionEvents).insertOnConflictUpdate(
|
||||||
ConnectionEventEntity(
|
ConnectionEventEntity(
|
||||||
id: 1,
|
id: 1,
|
||||||
type: event.type,
|
type: event.type,
|
||||||
@@ -38,7 +38,6 @@ class ConnectionEventDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
unreadChannels:
|
unreadChannels:
|
||||||
event.unreadChannels ?? connectionInfo?.unreadChannels,
|
event.unreadChannels ?? connectionInfo?.unreadChannels,
|
||||||
),
|
),
|
||||||
mode: InsertMode.insertOrReplace,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export 'connection_event_dao.dart';
|
|||||||
export 'member_dao.dart';
|
export 'member_dao.dart';
|
||||||
export 'message_dao.dart';
|
export 'message_dao.dart';
|
||||||
export 'pinned_message_dao.dart';
|
export 'pinned_message_dao.dart';
|
||||||
|
export 'pinned_message_reaction_dao.dart';
|
||||||
export 'reaction_dao.dart';
|
export 'reaction_dao.dart';
|
||||||
export 'read_dao.dart';
|
export 'read_dao.dart';
|
||||||
export 'user_dao.dart';
|
export 'user_dao.dart';
|
||||||
|
|||||||
@@ -30,14 +30,19 @@ class MemberDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
}).get();
|
}).get();
|
||||||
|
|
||||||
/// Updates all the members using the new [memberList] data
|
/// Updates all the members using the new [memberList] data
|
||||||
Future<void> updateMembers(String cid, List<Member> memberList) async =>
|
Future<void> updateMembers(String cid, List<Member> memberList) =>
|
||||||
batch(
|
bulkUpdateMembers({cid: memberList});
|
||||||
(it) => it.insertAll(
|
|
||||||
members,
|
/// Bulk updates the members data of multiple channels
|
||||||
memberList.map((m) => m.toEntity(cid: cid)).toList(),
|
Future<void> bulkUpdateMembers(Map<String, List<Member>> channelWithMembers) {
|
||||||
mode: InsertMode.insertOrReplace,
|
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]
|
/// Deletes all the members whose [Members.channelCid] is present in [cids]
|
||||||
Future<void> deleteMemberByCids(List<String> cids) async => batch((it) {
|
Future<void> deleteMemberByCids(List<String> cids) async => batch((it) {
|
||||||
|
|||||||
@@ -170,13 +170,21 @@ class MessageDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
|
|
||||||
/// Updates the message data of a particular channel with
|
/// Updates the message data of a particular channel with
|
||||||
/// the new [messageList] data
|
/// the new [messageList] data
|
||||||
Future<void> updateMessages(String cid, List<Message> messageList) => batch(
|
Future<void> updateMessages(String cid, List<Message> messageList) =>
|
||||||
(batch) {
|
bulkUpdateMessages({cid: messageList});
|
||||||
batch.insertAll(
|
|
||||||
messages,
|
/// Bulk updates the message data of multiple channels
|
||||||
messageList.map((it) => it.toEntity(cid: cid)).toList(),
|
Future<void> bulkUpdateMessages(
|
||||||
mode: InsertMode.insertOrReplace,
|
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 userEntity = rows.readTableOrNull(users);
|
||||||
final pinnedByEntity = rows.readTableOrNull(_pinnedByUsers);
|
final pinnedByEntity = rows.readTableOrNull(_pinnedByUsers);
|
||||||
final msgEntity = rows.readTable(pinnedMessages);
|
final msgEntity = rows.readTable(pinnedMessages);
|
||||||
final latestReactions = await _db.reactionDao.getReactions(msgEntity.id);
|
final latestReactions =
|
||||||
final ownReactions = await _db.reactionDao.getReactionsByUserId(
|
await _db.pinnedMessageReactionDao.getReactions(msgEntity.id);
|
||||||
|
final ownReactions =
|
||||||
|
await _db.pinnedMessageReactionDao.getReactionsByUserId(
|
||||||
msgEntity.id,
|
msgEntity.id,
|
||||||
_db.userId,
|
_db.userId,
|
||||||
);
|
);
|
||||||
@@ -168,13 +170,21 @@ class PinnedMessageDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
|
|
||||||
/// Updates the message data of a particular channel with
|
/// Updates the message data of a particular channel with
|
||||||
/// the new [messageList] data
|
/// the new [messageList] data
|
||||||
Future<void> updateMessages(String cid, List<Message> messageList) => batch(
|
Future<void> updateMessages(String cid, List<Message> messageList) =>
|
||||||
(batch) {
|
bulkUpdateMessages({cid: messageList});
|
||||||
batch.insertAll(
|
|
||||||
pinnedMessages,
|
/// Bulk updates the message data of multiple channels
|
||||||
messageList.map((it) => it.toPinnedEntity(cid: cid)).toList(),
|
Future<void> bulkUpdateMessages(
|
||||||
mode: InsertMode.insertOrReplace,
|
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
|
/// Updates the reactions data with the new [reactionList] data
|
||||||
Future<void> updateReactions(List<Reaction> reactionList) => batch((it) {
|
Future<void> updateReactions(List<Reaction> reactionList) => batch((it) {
|
||||||
it.insertAll(
|
it.insertAllOnConflictUpdate(
|
||||||
reactions,
|
reactions,
|
||||||
reactionList.map((r) => r.toEntity()).toList(),
|
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
|
/// Updates the read data of a particular channel with
|
||||||
/// the new [readList] data
|
/// the new [readList] data
|
||||||
Future<void> updateReads(String cid, List<Read> readList) => batch(
|
Future<void> updateReads(String cid, List<Read> readList) =>
|
||||||
(it) => it.insertAll(
|
bulkUpdateReads({cid: readList});
|
||||||
reads,
|
|
||||||
readList.map((r) => r.toEntity(cid: cid)).toList(),
|
/// Bulk updates the reads data of multiple channels
|
||||||
mode: InsertMode.insertOrReplace,
|
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
|
/// Updates the users data with the new [userList] data
|
||||||
Future<void> updateUsers(List<User> userList) => batch(
|
Future<void> updateUsers(List<User> userList) => batch(
|
||||||
(it) => it.insertAll(
|
(it) => it.insertAllOnConflictUpdate(
|
||||||
users,
|
users,
|
||||||
userList.map((u) => u.toEntity()).toList(),
|
userList.map((u) => u.toEntity()).toList(),
|
||||||
mode: InsertMode.insertOrReplace,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ part 'moor_chat_database.g.dart';
|
|||||||
Channels,
|
Channels,
|
||||||
Messages,
|
Messages,
|
||||||
PinnedMessages,
|
PinnedMessages,
|
||||||
|
PinnedMessageReactions,
|
||||||
Reactions,
|
Reactions,
|
||||||
Users,
|
Users,
|
||||||
Members,
|
Members,
|
||||||
@@ -25,6 +26,7 @@ part 'moor_chat_database.g.dart';
|
|||||||
ChannelDao,
|
ChannelDao,
|
||||||
MessageDao,
|
MessageDao,
|
||||||
PinnedMessageDao,
|
PinnedMessageDao,
|
||||||
|
PinnedMessageReactionDao,
|
||||||
MemberDao,
|
MemberDao,
|
||||||
ReactionDao,
|
ReactionDao,
|
||||||
ReadDao,
|
ReadDao,
|
||||||
@@ -51,10 +53,13 @@ class MoorChatDatabase extends _$MoorChatDatabase {
|
|||||||
|
|
||||||
// you should bump this number whenever you change or add a table definition.
|
// you should bump this number whenever you change or add a table definition.
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 5;
|
int get schemaVersion => 6;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration => MigrationStrategy(
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
|
beforeOpen: (details) async {
|
||||||
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
|
},
|
||||||
onUpgrade: (openingDetails, before, after) async {
|
onUpgrade: (openingDetails, before, after) async {
|
||||||
if (before != after) {
|
if (before != after) {
|
||||||
final m = createMigrator();
|
final m = createMigrator();
|
||||||
|
|||||||
@@ -645,7 +645,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
|||||||
final String? pinnedByUserId;
|
final String? pinnedByUserId;
|
||||||
|
|
||||||
/// The channel cid of which this message is part of
|
/// The channel cid of which this message is part of
|
||||||
final String? channelCid;
|
final String channelCid;
|
||||||
|
|
||||||
/// A Map of [messageText] translations.
|
/// A Map of [messageText] translations.
|
||||||
final Map<String, String>? i18n;
|
final Map<String, String>? i18n;
|
||||||
@@ -675,7 +675,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
|||||||
this.pinnedAt,
|
this.pinnedAt,
|
||||||
this.pinExpires,
|
this.pinExpires,
|
||||||
this.pinnedByUserId,
|
this.pinnedByUserId,
|
||||||
this.channelCid,
|
required this.channelCid,
|
||||||
this.i18n,
|
this.i18n,
|
||||||
this.extraData});
|
this.extraData});
|
||||||
factory MessageEntity.fromData(
|
factory MessageEntity.fromData(
|
||||||
@@ -728,7 +728,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
|||||||
pinnedByUserId: const StringType()
|
pinnedByUserId: const StringType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}pinned_by_user_id']),
|
.mapFromDatabaseResponse(data['${effectivePrefix}pinned_by_user_id']),
|
||||||
channelCid: const StringType()
|
channelCid: const StringType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']),
|
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid'])!,
|
||||||
i18n: $MessagesTable.$converter5.mapToDart(const StringType()
|
i18n: $MessagesTable.$converter5.mapToDart(const StringType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}i18n'])),
|
.mapFromDatabaseResponse(data['${effectivePrefix}i18n'])),
|
||||||
extraData: $MessagesTable.$converter6.mapToDart(const StringType()
|
extraData: $MessagesTable.$converter6.mapToDart(const StringType()
|
||||||
@@ -800,9 +800,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
|||||||
if (!nullToAbsent || pinnedByUserId != null) {
|
if (!nullToAbsent || pinnedByUserId != null) {
|
||||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId);
|
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) {
|
if (!nullToAbsent || i18n != null) {
|
||||||
final converter = $MessagesTable.$converter5;
|
final converter = $MessagesTable.$converter5;
|
||||||
map['i18n'] = Variable<String?>(converter.mapToSql(i18n));
|
map['i18n'] = Variable<String?>(converter.mapToSql(i18n));
|
||||||
@@ -842,7 +840,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
|||||||
pinnedAt: serializer.fromJson<DateTime?>(json['pinnedAt']),
|
pinnedAt: serializer.fromJson<DateTime?>(json['pinnedAt']),
|
||||||
pinExpires: serializer.fromJson<DateTime?>(json['pinExpires']),
|
pinExpires: serializer.fromJson<DateTime?>(json['pinExpires']),
|
||||||
pinnedByUserId: serializer.fromJson<String?>(json['pinnedByUserId']),
|
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']),
|
i18n: serializer.fromJson<Map<String, String>?>(json['i18n']),
|
||||||
extraData: serializer.fromJson<Map<String, Object?>?>(json['extraData']),
|
extraData: serializer.fromJson<Map<String, Object?>?>(json['extraData']),
|
||||||
);
|
);
|
||||||
@@ -873,7 +871,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
|||||||
'pinnedAt': serializer.toJson<DateTime?>(pinnedAt),
|
'pinnedAt': serializer.toJson<DateTime?>(pinnedAt),
|
||||||
'pinExpires': serializer.toJson<DateTime?>(pinExpires),
|
'pinExpires': serializer.toJson<DateTime?>(pinExpires),
|
||||||
'pinnedByUserId': serializer.toJson<String?>(pinnedByUserId),
|
'pinnedByUserId': serializer.toJson<String?>(pinnedByUserId),
|
||||||
'channelCid': serializer.toJson<String?>(channelCid),
|
'channelCid': serializer.toJson<String>(channelCid),
|
||||||
'i18n': serializer.toJson<Map<String, String>?>(i18n),
|
'i18n': serializer.toJson<Map<String, String>?>(i18n),
|
||||||
'extraData': serializer.toJson<Map<String, Object?>?>(extraData),
|
'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?> pinnedAt = const Value.absent(),
|
||||||
Value<DateTime?> pinExpires = const Value.absent(),
|
Value<DateTime?> pinExpires = const Value.absent(),
|
||||||
Value<String?> pinnedByUserId = 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, String>?> i18n = const Value.absent(),
|
||||||
Value<Map<String, Object?>?> extraData = const Value.absent()}) =>
|
Value<Map<String, Object?>?> extraData = const Value.absent()}) =>
|
||||||
MessageEntity(
|
MessageEntity(
|
||||||
@@ -934,7 +932,7 @@ class MessageEntity extends DataClass implements Insertable<MessageEntity> {
|
|||||||
pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires,
|
pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires,
|
||||||
pinnedByUserId:
|
pinnedByUserId:
|
||||||
pinnedByUserId.present ? pinnedByUserId.value : this.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,
|
i18n: i18n.present ? i18n.value : this.i18n,
|
||||||
extraData: extraData.present ? extraData.value : this.extraData,
|
extraData: extraData.present ? extraData.value : this.extraData,
|
||||||
);
|
);
|
||||||
@@ -1068,7 +1066,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
|||||||
final Value<DateTime?> pinnedAt;
|
final Value<DateTime?> pinnedAt;
|
||||||
final Value<DateTime?> pinExpires;
|
final Value<DateTime?> pinExpires;
|
||||||
final Value<String?> pinnedByUserId;
|
final Value<String?> pinnedByUserId;
|
||||||
final Value<String?> channelCid;
|
final Value<String> channelCid;
|
||||||
final Value<Map<String, String>?> i18n;
|
final Value<Map<String, String>?> i18n;
|
||||||
final Value<Map<String, Object?>?> extraData;
|
final Value<Map<String, Object?>?> extraData;
|
||||||
const MessagesCompanion({
|
const MessagesCompanion({
|
||||||
@@ -1121,12 +1119,13 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
|||||||
this.pinnedAt = const Value.absent(),
|
this.pinnedAt = const Value.absent(),
|
||||||
this.pinExpires = const Value.absent(),
|
this.pinExpires = const Value.absent(),
|
||||||
this.pinnedByUserId = const Value.absent(),
|
this.pinnedByUserId = const Value.absent(),
|
||||||
this.channelCid = const Value.absent(),
|
required String channelCid,
|
||||||
this.i18n = const Value.absent(),
|
this.i18n = const Value.absent(),
|
||||||
this.extraData = const Value.absent(),
|
this.extraData = const Value.absent(),
|
||||||
}) : id = Value(id),
|
}) : id = Value(id),
|
||||||
attachments = Value(attachments),
|
attachments = Value(attachments),
|
||||||
mentionedUsers = Value(mentionedUsers);
|
mentionedUsers = Value(mentionedUsers),
|
||||||
|
channelCid = Value(channelCid);
|
||||||
static Insertable<MessageEntity> custom({
|
static Insertable<MessageEntity> custom({
|
||||||
Expression<String>? id,
|
Expression<String>? id,
|
||||||
Expression<String?>? messageText,
|
Expression<String?>? messageText,
|
||||||
@@ -1150,7 +1149,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
|||||||
Expression<DateTime?>? pinnedAt,
|
Expression<DateTime?>? pinnedAt,
|
||||||
Expression<DateTime?>? pinExpires,
|
Expression<DateTime?>? pinExpires,
|
||||||
Expression<String?>? pinnedByUserId,
|
Expression<String?>? pinnedByUserId,
|
||||||
Expression<String?>? channelCid,
|
Expression<String>? channelCid,
|
||||||
Expression<Map<String, String>?>? i18n,
|
Expression<Map<String, String>?>? i18n,
|
||||||
Expression<Map<String, Object?>?>? extraData,
|
Expression<Map<String, Object?>?>? extraData,
|
||||||
}) {
|
}) {
|
||||||
@@ -1206,7 +1205,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
|||||||
Value<DateTime?>? pinnedAt,
|
Value<DateTime?>? pinnedAt,
|
||||||
Value<DateTime?>? pinExpires,
|
Value<DateTime?>? pinExpires,
|
||||||
Value<String?>? pinnedByUserId,
|
Value<String?>? pinnedByUserId,
|
||||||
Value<String?>? channelCid,
|
Value<String>? channelCid,
|
||||||
Value<Map<String, String>?>? i18n,
|
Value<Map<String, String>?>? i18n,
|
||||||
Value<Map<String, Object?>?>? extraData}) {
|
Value<Map<String, Object?>?>? extraData}) {
|
||||||
return MessagesCompanion(
|
return MessagesCompanion(
|
||||||
@@ -1317,7 +1316,7 @@ class MessagesCompanion extends UpdateCompanion<MessageEntity> {
|
|||||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId.value);
|
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId.value);
|
||||||
}
|
}
|
||||||
if (channelCid.present) {
|
if (channelCid.present) {
|
||||||
map['channel_cid'] = Variable<String?>(channelCid.value);
|
map['channel_cid'] = Variable<String>(channelCid.value);
|
||||||
}
|
}
|
||||||
if (i18n.present) {
|
if (i18n.present) {
|
||||||
final converter = $MessagesTable.$converter5;
|
final converter = $MessagesTable.$converter5;
|
||||||
@@ -1491,11 +1490,10 @@ class $MessagesTable extends Messages
|
|||||||
typeName: 'TEXT', requiredDuringInsert: false);
|
typeName: 'TEXT', requiredDuringInsert: false);
|
||||||
final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid');
|
final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid');
|
||||||
late final GeneratedColumn<String?> channelCid = GeneratedColumn<String?>(
|
late final GeneratedColumn<String?> channelCid = GeneratedColumn<String?>(
|
||||||
'channel_cid', aliasedName, true,
|
'channel_cid', aliasedName, false,
|
||||||
typeName: 'TEXT',
|
typeName: 'TEXT',
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: true,
|
||||||
$customConstraints:
|
$customConstraints: 'REFERENCES channels(cid) ON DELETE CASCADE');
|
||||||
'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE');
|
|
||||||
final VerificationMeta _i18nMeta = const VerificationMeta('i18n');
|
final VerificationMeta _i18nMeta = const VerificationMeta('i18n');
|
||||||
late final GeneratedColumnWithTypeConverter<Map<String, String>, String?>
|
late final GeneratedColumnWithTypeConverter<Map<String, String>, String?>
|
||||||
i18n = GeneratedColumn<String?>('i18n', aliasedName, true,
|
i18n = GeneratedColumn<String?>('i18n', aliasedName, true,
|
||||||
@@ -1634,6 +1632,8 @@ class $MessagesTable extends Messages
|
|||||||
_channelCidMeta,
|
_channelCidMeta,
|
||||||
channelCid.isAcceptableOrUnknown(
|
channelCid.isAcceptableOrUnknown(
|
||||||
data['channel_cid']!, _channelCidMeta));
|
data['channel_cid']!, _channelCidMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_channelCidMeta);
|
||||||
}
|
}
|
||||||
context.handle(_i18nMeta, const VerificationResult.success());
|
context.handle(_i18nMeta, const VerificationResult.success());
|
||||||
context.handle(_extraDataMeta, const VerificationResult.success());
|
context.handle(_extraDataMeta, const VerificationResult.success());
|
||||||
@@ -1739,7 +1739,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
final String? pinnedByUserId;
|
final String? pinnedByUserId;
|
||||||
|
|
||||||
/// The channel cid of which this message is part of
|
/// The channel cid of which this message is part of
|
||||||
final String? channelCid;
|
final String channelCid;
|
||||||
|
|
||||||
/// A Map of [messageText] translations.
|
/// A Map of [messageText] translations.
|
||||||
final Map<String, String>? i18n;
|
final Map<String, String>? i18n;
|
||||||
@@ -1769,7 +1769,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
this.pinnedAt,
|
this.pinnedAt,
|
||||||
this.pinExpires,
|
this.pinExpires,
|
||||||
this.pinnedByUserId,
|
this.pinnedByUserId,
|
||||||
this.channelCid,
|
required this.channelCid,
|
||||||
this.i18n,
|
this.i18n,
|
||||||
this.extraData});
|
this.extraData});
|
||||||
factory PinnedMessageEntity.fromData(
|
factory PinnedMessageEntity.fromData(
|
||||||
@@ -1825,7 +1825,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
pinnedByUserId: const StringType()
|
pinnedByUserId: const StringType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}pinned_by_user_id']),
|
.mapFromDatabaseResponse(data['${effectivePrefix}pinned_by_user_id']),
|
||||||
channelCid: const StringType()
|
channelCid: const StringType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid']),
|
.mapFromDatabaseResponse(data['${effectivePrefix}channel_cid'])!,
|
||||||
i18n: $PinnedMessagesTable.$converter5.mapToDart(const StringType()
|
i18n: $PinnedMessagesTable.$converter5.mapToDart(const StringType()
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}i18n'])),
|
.mapFromDatabaseResponse(data['${effectivePrefix}i18n'])),
|
||||||
extraData: $PinnedMessagesTable.$converter6.mapToDart(const StringType()
|
extraData: $PinnedMessagesTable.$converter6.mapToDart(const StringType()
|
||||||
@@ -1897,9 +1897,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
if (!nullToAbsent || pinnedByUserId != null) {
|
if (!nullToAbsent || pinnedByUserId != null) {
|
||||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId);
|
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) {
|
if (!nullToAbsent || i18n != null) {
|
||||||
final converter = $PinnedMessagesTable.$converter5;
|
final converter = $PinnedMessagesTable.$converter5;
|
||||||
map['i18n'] = Variable<String?>(converter.mapToSql(i18n));
|
map['i18n'] = Variable<String?>(converter.mapToSql(i18n));
|
||||||
@@ -1939,7 +1937,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
pinnedAt: serializer.fromJson<DateTime?>(json['pinnedAt']),
|
pinnedAt: serializer.fromJson<DateTime?>(json['pinnedAt']),
|
||||||
pinExpires: serializer.fromJson<DateTime?>(json['pinExpires']),
|
pinExpires: serializer.fromJson<DateTime?>(json['pinExpires']),
|
||||||
pinnedByUserId: serializer.fromJson<String?>(json['pinnedByUserId']),
|
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']),
|
i18n: serializer.fromJson<Map<String, String>?>(json['i18n']),
|
||||||
extraData: serializer.fromJson<Map<String, Object?>?>(json['extraData']),
|
extraData: serializer.fromJson<Map<String, Object?>?>(json['extraData']),
|
||||||
);
|
);
|
||||||
@@ -1970,7 +1968,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
'pinnedAt': serializer.toJson<DateTime?>(pinnedAt),
|
'pinnedAt': serializer.toJson<DateTime?>(pinnedAt),
|
||||||
'pinExpires': serializer.toJson<DateTime?>(pinExpires),
|
'pinExpires': serializer.toJson<DateTime?>(pinExpires),
|
||||||
'pinnedByUserId': serializer.toJson<String?>(pinnedByUserId),
|
'pinnedByUserId': serializer.toJson<String?>(pinnedByUserId),
|
||||||
'channelCid': serializer.toJson<String?>(channelCid),
|
'channelCid': serializer.toJson<String>(channelCid),
|
||||||
'i18n': serializer.toJson<Map<String, String>?>(i18n),
|
'i18n': serializer.toJson<Map<String, String>?>(i18n),
|
||||||
'extraData': serializer.toJson<Map<String, Object?>?>(extraData),
|
'extraData': serializer.toJson<Map<String, Object?>?>(extraData),
|
||||||
};
|
};
|
||||||
@@ -1999,7 +1997,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
Value<DateTime?> pinnedAt = const Value.absent(),
|
Value<DateTime?> pinnedAt = const Value.absent(),
|
||||||
Value<DateTime?> pinExpires = const Value.absent(),
|
Value<DateTime?> pinExpires = const Value.absent(),
|
||||||
Value<String?> pinnedByUserId = 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, String>?> i18n = const Value.absent(),
|
||||||
Value<Map<String, Object?>?> extraData = const Value.absent()}) =>
|
Value<Map<String, Object?>?> extraData = const Value.absent()}) =>
|
||||||
PinnedMessageEntity(
|
PinnedMessageEntity(
|
||||||
@@ -2031,7 +2029,7 @@ class PinnedMessageEntity extends DataClass
|
|||||||
pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires,
|
pinExpires: pinExpires.present ? pinExpires.value : this.pinExpires,
|
||||||
pinnedByUserId:
|
pinnedByUserId:
|
||||||
pinnedByUserId.present ? pinnedByUserId.value : this.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,
|
i18n: i18n.present ? i18n.value : this.i18n,
|
||||||
extraData: extraData.present ? extraData.value : this.extraData,
|
extraData: extraData.present ? extraData.value : this.extraData,
|
||||||
);
|
);
|
||||||
@@ -2165,7 +2163,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
|||||||
final Value<DateTime?> pinnedAt;
|
final Value<DateTime?> pinnedAt;
|
||||||
final Value<DateTime?> pinExpires;
|
final Value<DateTime?> pinExpires;
|
||||||
final Value<String?> pinnedByUserId;
|
final Value<String?> pinnedByUserId;
|
||||||
final Value<String?> channelCid;
|
final Value<String> channelCid;
|
||||||
final Value<Map<String, String>?> i18n;
|
final Value<Map<String, String>?> i18n;
|
||||||
final Value<Map<String, Object?>?> extraData;
|
final Value<Map<String, Object?>?> extraData;
|
||||||
const PinnedMessagesCompanion({
|
const PinnedMessagesCompanion({
|
||||||
@@ -2218,12 +2216,13 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
|||||||
this.pinnedAt = const Value.absent(),
|
this.pinnedAt = const Value.absent(),
|
||||||
this.pinExpires = const Value.absent(),
|
this.pinExpires = const Value.absent(),
|
||||||
this.pinnedByUserId = const Value.absent(),
|
this.pinnedByUserId = const Value.absent(),
|
||||||
this.channelCid = const Value.absent(),
|
required String channelCid,
|
||||||
this.i18n = const Value.absent(),
|
this.i18n = const Value.absent(),
|
||||||
this.extraData = const Value.absent(),
|
this.extraData = const Value.absent(),
|
||||||
}) : id = Value(id),
|
}) : id = Value(id),
|
||||||
attachments = Value(attachments),
|
attachments = Value(attachments),
|
||||||
mentionedUsers = Value(mentionedUsers);
|
mentionedUsers = Value(mentionedUsers),
|
||||||
|
channelCid = Value(channelCid);
|
||||||
static Insertable<PinnedMessageEntity> custom({
|
static Insertable<PinnedMessageEntity> custom({
|
||||||
Expression<String>? id,
|
Expression<String>? id,
|
||||||
Expression<String?>? messageText,
|
Expression<String?>? messageText,
|
||||||
@@ -2247,7 +2246,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
|||||||
Expression<DateTime?>? pinnedAt,
|
Expression<DateTime?>? pinnedAt,
|
||||||
Expression<DateTime?>? pinExpires,
|
Expression<DateTime?>? pinExpires,
|
||||||
Expression<String?>? pinnedByUserId,
|
Expression<String?>? pinnedByUserId,
|
||||||
Expression<String?>? channelCid,
|
Expression<String>? channelCid,
|
||||||
Expression<Map<String, String>?>? i18n,
|
Expression<Map<String, String>?>? i18n,
|
||||||
Expression<Map<String, Object?>?>? extraData,
|
Expression<Map<String, Object?>?>? extraData,
|
||||||
}) {
|
}) {
|
||||||
@@ -2303,7 +2302,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
|||||||
Value<DateTime?>? pinnedAt,
|
Value<DateTime?>? pinnedAt,
|
||||||
Value<DateTime?>? pinExpires,
|
Value<DateTime?>? pinExpires,
|
||||||
Value<String?>? pinnedByUserId,
|
Value<String?>? pinnedByUserId,
|
||||||
Value<String?>? channelCid,
|
Value<String>? channelCid,
|
||||||
Value<Map<String, String>?>? i18n,
|
Value<Map<String, String>?>? i18n,
|
||||||
Value<Map<String, Object?>?>? extraData}) {
|
Value<Map<String, Object?>?>? extraData}) {
|
||||||
return PinnedMessagesCompanion(
|
return PinnedMessagesCompanion(
|
||||||
@@ -2414,7 +2413,7 @@ class PinnedMessagesCompanion extends UpdateCompanion<PinnedMessageEntity> {
|
|||||||
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId.value);
|
map['pinned_by_user_id'] = Variable<String?>(pinnedByUserId.value);
|
||||||
}
|
}
|
||||||
if (channelCid.present) {
|
if (channelCid.present) {
|
||||||
map['channel_cid'] = Variable<String?>(channelCid.value);
|
map['channel_cid'] = Variable<String>(channelCid.value);
|
||||||
}
|
}
|
||||||
if (i18n.present) {
|
if (i18n.present) {
|
||||||
final converter = $PinnedMessagesTable.$converter5;
|
final converter = $PinnedMessagesTable.$converter5;
|
||||||
@@ -2589,11 +2588,10 @@ class $PinnedMessagesTable extends PinnedMessages
|
|||||||
typeName: 'TEXT', requiredDuringInsert: false);
|
typeName: 'TEXT', requiredDuringInsert: false);
|
||||||
final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid');
|
final VerificationMeta _channelCidMeta = const VerificationMeta('channelCid');
|
||||||
late final GeneratedColumn<String?> channelCid = GeneratedColumn<String?>(
|
late final GeneratedColumn<String?> channelCid = GeneratedColumn<String?>(
|
||||||
'channel_cid', aliasedName, true,
|
'channel_cid', aliasedName, false,
|
||||||
typeName: 'TEXT',
|
typeName: 'TEXT',
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: true,
|
||||||
$customConstraints:
|
$customConstraints: 'REFERENCES channels(cid) ON DELETE CASCADE');
|
||||||
'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE');
|
|
||||||
final VerificationMeta _i18nMeta = const VerificationMeta('i18n');
|
final VerificationMeta _i18nMeta = const VerificationMeta('i18n');
|
||||||
late final GeneratedColumnWithTypeConverter<Map<String, String>, String?>
|
late final GeneratedColumnWithTypeConverter<Map<String, String>, String?>
|
||||||
i18n = GeneratedColumn<String?>('i18n', aliasedName, true,
|
i18n = GeneratedColumn<String?>('i18n', aliasedName, true,
|
||||||
@@ -2734,6 +2732,8 @@ class $PinnedMessagesTable extends PinnedMessages
|
|||||||
_channelCidMeta,
|
_channelCidMeta,
|
||||||
channelCid.isAcceptableOrUnknown(
|
channelCid.isAcceptableOrUnknown(
|
||||||
data['channel_cid']!, _channelCidMeta));
|
data['channel_cid']!, _channelCidMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_channelCidMeta);
|
||||||
}
|
}
|
||||||
context.handle(_i18nMeta, const VerificationResult.success());
|
context.handle(_i18nMeta, const VerificationResult.success());
|
||||||
context.handle(_extraDataMeta, const VerificationResult.success());
|
context.handle(_extraDataMeta, const VerificationResult.success());
|
||||||
@@ -2769,6 +2769,340 @@ class $PinnedMessagesTable extends PinnedMessages
|
|||||||
MapConverter<Object?>();
|
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> {
|
class ReactionEntity extends DataClass implements Insertable<ReactionEntity> {
|
||||||
/// The id of the user that sent the reaction
|
/// The id of the user that sent the reaction
|
||||||
final String userId;
|
final String userId;
|
||||||
@@ -4897,6 +5231,8 @@ abstract class _$MoorChatDatabase extends GeneratedDatabase {
|
|||||||
late final $ChannelsTable channels = $ChannelsTable(this);
|
late final $ChannelsTable channels = $ChannelsTable(this);
|
||||||
late final $MessagesTable messages = $MessagesTable(this);
|
late final $MessagesTable messages = $MessagesTable(this);
|
||||||
late final $PinnedMessagesTable pinnedMessages = $PinnedMessagesTable(this);
|
late final $PinnedMessagesTable pinnedMessages = $PinnedMessagesTable(this);
|
||||||
|
late final $PinnedMessageReactionsTable pinnedMessageReactions =
|
||||||
|
$PinnedMessageReactionsTable(this);
|
||||||
late final $ReactionsTable reactions = $ReactionsTable(this);
|
late final $ReactionsTable reactions = $ReactionsTable(this);
|
||||||
late final $UsersTable users = $UsersTable(this);
|
late final $UsersTable users = $UsersTable(this);
|
||||||
late final $MembersTable members = $MembersTable(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 MessageDao messageDao = MessageDao(this as MoorChatDatabase);
|
||||||
late final PinnedMessageDao pinnedMessageDao =
|
late final PinnedMessageDao pinnedMessageDao =
|
||||||
PinnedMessageDao(this as MoorChatDatabase);
|
PinnedMessageDao(this as MoorChatDatabase);
|
||||||
|
late final PinnedMessageReactionDao pinnedMessageReactionDao =
|
||||||
|
PinnedMessageReactionDao(this as MoorChatDatabase);
|
||||||
late final MemberDao memberDao = MemberDao(this as MoorChatDatabase);
|
late final MemberDao memberDao = MemberDao(this as MoorChatDatabase);
|
||||||
late final ReactionDao reactionDao = ReactionDao(this as MoorChatDatabase);
|
late final ReactionDao reactionDao = ReactionDao(this as MoorChatDatabase);
|
||||||
late final ReadDao readDao = ReadDao(this as MoorChatDatabase);
|
late final ReadDao readDao = ReadDao(this as MoorChatDatabase);
|
||||||
@@ -4923,6 +5261,7 @@ abstract class _$MoorChatDatabase extends GeneratedDatabase {
|
|||||||
channels,
|
channels,
|
||||||
messages,
|
messages,
|
||||||
pinnedMessages,
|
pinnedMessages,
|
||||||
|
pinnedMessageReactions,
|
||||||
reactions,
|
reactions,
|
||||||
users,
|
users,
|
||||||
members,
|
members,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export 'channels.dart';
|
|||||||
export 'connection_events.dart';
|
export 'connection_events.dart';
|
||||||
export 'members.dart';
|
export 'members.dart';
|
||||||
export 'messages.dart';
|
export 'messages.dart';
|
||||||
|
export 'pinned_message_reactions.dart';
|
||||||
export 'pinned_messages.dart';
|
export 'pinned_messages.dart';
|
||||||
export 'reactions.dart';
|
export 'reactions.dart';
|
||||||
export 'reads.dart';
|
export 'reads.dart';
|
||||||
|
|||||||
@@ -39,8 +39,5 @@ class Members extends Table {
|
|||||||
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
|
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column> get primaryKey => {
|
Set<Column> get primaryKey => {userId, channelCid};
|
||||||
userId,
|
|
||||||
channelCid,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ class Messages extends Table {
|
|||||||
TextColumn get pinnedByUserId => text().nullable()();
|
TextColumn get pinnedByUserId => text().nullable()();
|
||||||
|
|
||||||
/// The channel cid of which this message is part of
|
/// The channel cid of which this message is part of
|
||||||
TextColumn get channelCid => text().nullable().customConstraint(
|
TextColumn get channelCid =>
|
||||||
'NULLABLE REFERENCES channels(cid) ON DELETE CASCADE')();
|
text().customConstraint('REFERENCES channels(cid) ON DELETE CASCADE')();
|
||||||
|
|
||||||
/// A Map of [messageText] translations.
|
/// A Map of [messageText] translations.
|
||||||
TextColumn get i18n => text().nullable().map(MapConverter<String>())();
|
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 'member_mapper.dart';
|
||||||
export 'message_mapper.dart';
|
export 'message_mapper.dart';
|
||||||
export 'pinned_message_mapper.dart';
|
export 'pinned_message_mapper.dart';
|
||||||
|
export 'pinned_message_reaction_mapper.dart';
|
||||||
export 'reaction_mapper.dart';
|
export 'reaction_mapper.dart';
|
||||||
export 'read_mapper.dart';
|
export 'read_mapper.dart';
|
||||||
export 'user_mapper.dart';
|
export 'user_mapper.dart';
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ extension MessageEntityX on MessageEntity {
|
|||||||
/// Useful mapping functions for [Message]
|
/// Useful mapping functions for [Message]
|
||||||
extension MessageX on Message {
|
extension MessageX on Message {
|
||||||
/// Maps a [Message] into [MessageEntity]
|
/// Maps a [Message] into [MessageEntity]
|
||||||
MessageEntity toEntity({String? cid}) => MessageEntity(
|
MessageEntity toEntity({required String cid}) => MessageEntity(
|
||||||
id: id,
|
id: id,
|
||||||
attachments: attachments.map((it) => jsonEncode(it.toData())).toList(),
|
attachments: attachments.map((it) => jsonEncode(it.toData())).toList(),
|
||||||
channelCid: cid,
|
channelCid: cid,
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ extension PinnedMessageEntityX on PinnedMessageEntity {
|
|||||||
/// Useful mapping functions for [Message]
|
/// Useful mapping functions for [Message]
|
||||||
extension PMessageX on Message {
|
extension PMessageX on Message {
|
||||||
/// Maps a [Message] into [PinnedMessageEntity]
|
/// Maps a [Message] into [PinnedMessageEntity]
|
||||||
PinnedMessageEntity toPinnedEntity({String? cid}) => PinnedMessageEntity(
|
PinnedMessageEntity toPinnedEntity({required String cid}) =>
|
||||||
|
PinnedMessageEntity(
|
||||||
id: id,
|
id: id,
|
||||||
attachments: attachments.map((it) => jsonEncode(it.toData())).toList(),
|
attachments: attachments.map((it) => jsonEncode(it.toData())).toList(),
|
||||||
channelCid: cid,
|
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
|
@override
|
||||||
Future<void> updateMembers(String cid, List<Member> members) {
|
Future<void> bulkUpdateMembers(Map<String, List<Member>> members) {
|
||||||
assert(_debugIsConnected, '');
|
assert(_debugIsConnected, '');
|
||||||
_logger.info('updateMembers');
|
_logger.info('bulkUpdateMembers');
|
||||||
return _readProtected(() => db!.memberDao.updateMembers(cid, members));
|
return _readProtected(() => db!.memberDao.bulkUpdateMembers(members));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updateMessages(String cid, List<Message> messages) {
|
Future<void> bulkUpdateMessages(Map<String, List<Message>> messages) {
|
||||||
assert(_debugIsConnected, '');
|
assert(_debugIsConnected, '');
|
||||||
_logger.info('updateMessages');
|
_logger.info('bulkUpdateMessages');
|
||||||
return _readProtected(() => db!.messageDao.updateMessages(cid, messages));
|
return _readProtected(() => db!.messageDao.bulkUpdateMessages(messages));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updatePinnedMessages(String cid, List<Message> messages) {
|
Future<void> bulkUpdatePinnedMessages(Map<String, List<Message>> messages) {
|
||||||
assert(_debugIsConnected, '');
|
assert(_debugIsConnected, '');
|
||||||
_logger.info('updatePinnedMessages');
|
_logger.info('bulkUpdatePinnedMessages');
|
||||||
return _readProtected(
|
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
|
@override
|
||||||
Future<void> updateReads(String cid, List<Read> reads) {
|
Future<void> bulkUpdateReads(Map<String, List<Read>> reads) {
|
||||||
assert(_debugIsConnected, '');
|
assert(_debugIsConnected, '');
|
||||||
_logger.info('updateReads');
|
_logger.info('bulkUpdateReads');
|
||||||
return _readProtected(() => db!.readDao.updateReads(cid, reads));
|
return _readProtected(() => db!.readDao.bulkUpdateReads(reads));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -339,6 +348,18 @@ class StreamChatPersistenceClient extends ChatPersistenceClient {
|
|||||||
return _readProtected(() => db!.userDao.updateUsers(users));
|
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
|
@override
|
||||||
Future<void> deleteReactionsByMessageId(List<String> messageIds) {
|
Future<void> deleteReactionsByMessageId(List<String> messageIds) {
|
||||||
assert(_debugIsConnected, '');
|
assert(_debugIsConnected, '');
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ class MockChatDatabase extends Mock implements MoorChatDatabase {
|
|||||||
@override
|
@override
|
||||||
ReactionDao get reactionDao => _reactionDao ??= MockReactionDao();
|
ReactionDao get reactionDao => _reactionDao ??= MockReactionDao();
|
||||||
|
|
||||||
|
PinnedMessageReactionDao? _pinnedMessageReactionDao;
|
||||||
|
|
||||||
|
@override
|
||||||
|
PinnedMessageReactionDao get pinnedMessageReactionDao =>
|
||||||
|
_pinnedMessageReactionDao ??= MockPinnedMessageReactionDao();
|
||||||
|
|
||||||
ReadDao? _readDao;
|
ReadDao? _readDao;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -70,6 +76,9 @@ class MockMemberDao extends Mock implements MemberDao {}
|
|||||||
|
|
||||||
class MockReactionDao extends Mock implements ReactionDao {}
|
class MockReactionDao extends Mock implements ReactionDao {}
|
||||||
|
|
||||||
|
class MockPinnedMessageReactionDao extends Mock
|
||||||
|
implements PinnedMessageReactionDao {}
|
||||||
|
|
||||||
class MockReadDao extends Mock implements ReadDao {}
|
class MockReadDao extends Mock implements ReadDao {}
|
||||||
|
|
||||||
class MockChannelQueryDao extends Mock implements ChannelQueryDao {}
|
class MockChannelQueryDao extends Mock implements ChannelQueryDao {}
|
||||||
|
|||||||
@@ -61,12 +61,73 @@ void main() {
|
|||||||
expect(updatedChannel.cid, cid);
|
expect(updatedChannel.cid, cid);
|
||||||
expect(updatedChannel.type, type);
|
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
|
// Deleting the dummyChannel using cid
|
||||||
await channelDao.deleteChannelByCids([cid]);
|
await channelDao.deleteChannelByCids([cid]);
|
||||||
|
|
||||||
// Fetched channel Should be null
|
// Fetched channel Should be null
|
||||||
final channel = await channelDao.getChannelByCid(cid);
|
final channel = await channelDao.getChannelByCid(cid);
|
||||||
expect(channel, isNull);
|
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 {
|
test('cids', () async {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Future<List<Member>> _prepareTestData(String cid) async {
|
Future<List<Member>> _prepareTestData(String cid) async {
|
||||||
|
final channels = [ChannelModel(cid: cid)];
|
||||||
final users = List.generate(3, (index) => User(id: 'testUserId$index'));
|
final users = List.generate(3, (index) => User(id: 'testUserId$index'));
|
||||||
final memberList = List.generate(
|
final memberList = List.generate(
|
||||||
3,
|
3,
|
||||||
@@ -34,12 +35,13 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
await database.userDao.updateUsers(users);
|
await database.userDao.updateUsers(users);
|
||||||
|
await database.channelDao.updateChannels(channels);
|
||||||
await memberDao.updateMembers(cid, memberList);
|
await memberDao.updateMembers(cid, memberList);
|
||||||
return memberList;
|
return memberList;
|
||||||
}
|
}
|
||||||
|
|
||||||
test('getMembersByCid', () async {
|
test('getMembersByCid', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Should be empty initially
|
// Should be empty initially
|
||||||
final members = await memberDao.getMembersByCid(cid);
|
final members = await memberDao.getMembersByCid(cid);
|
||||||
@@ -70,7 +72,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('updateMembers', () async {
|
test('updateMembers', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Preparing test data
|
// Preparing test data
|
||||||
final memberList = await _prepareTestData(cid);
|
final memberList = await _prepareTestData(cid);
|
||||||
@@ -132,7 +134,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('deleteMemberByCids', () async {
|
test('deleteMemberByCids', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Preparing test data
|
// Preparing test data
|
||||||
final members = await _prepareTestData(cid);
|
final members = await _prepareTestData(cid);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ void main() {
|
|||||||
bool mapAllThreadToFirstMessage = false,
|
bool mapAllThreadToFirstMessage = false,
|
||||||
int count = 3,
|
int count = 3,
|
||||||
}) async {
|
}) async {
|
||||||
|
final channels = [ChannelModel(cid: cid)];
|
||||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||||
final messages = List.generate(
|
final messages = List.generate(
|
||||||
count,
|
count,
|
||||||
@@ -98,13 +99,20 @@ void main() {
|
|||||||
if (quoted) ...quotedMessages,
|
if (quoted) ...quotedMessages,
|
||||||
if (threads) ...threadMessages
|
if (threads) ...threadMessages
|
||||||
];
|
];
|
||||||
|
final reaction = Reaction(
|
||||||
|
type: 'type',
|
||||||
|
messageId: allMessages.first.id,
|
||||||
|
user: users.first,
|
||||||
|
);
|
||||||
await database.userDao.updateUsers(users);
|
await database.userDao.updateUsers(users);
|
||||||
|
await database.channelDao.updateChannels(channels);
|
||||||
await messageDao.updateMessages(cid, allMessages);
|
await messageDao.updateMessages(cid, allMessages);
|
||||||
|
await database.reactionDao.updateReactions([reaction]);
|
||||||
return allMessages;
|
return allMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
test('deleteMessageByIds', () async {
|
test('deleteMessageByIds', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Preparing test data
|
// Preparing test data
|
||||||
final insertedMessages = await _prepareTestData(cid);
|
final insertedMessages = await _prepareTestData(cid);
|
||||||
@@ -113,66 +121,112 @@ void main() {
|
|||||||
final messages = await messageDao.getMessagesByCid(cid);
|
final messages = await messageDao.getMessagesByCid(cid);
|
||||||
expect(messages.length, insertedMessages.length);
|
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
|
// Deleting 2 messages from DB
|
||||||
await messageDao.deleteMessageByIds(
|
await messageDao.deleteMessageByIds(
|
||||||
['testMessageId${cid}0', 'testMessageId${cid}1'],
|
[firstMessageId, 'testMessageId${cid}1'],
|
||||||
);
|
);
|
||||||
|
|
||||||
// New fetched messages length should 2 less than the
|
// New fetched messages length should 2 less than the
|
||||||
// previous fetched messages
|
// previous fetched messages
|
||||||
final newMessages = await messageDao.getMessagesByCid(cid);
|
final newMessages = await messageDao.getMessagesByCid(cid);
|
||||||
expect(newMessages.length, messages.length - 2);
|
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', () {
|
group('deleteMessageByCids', () {
|
||||||
const cid1 = 'testCid1';
|
const cid1 = 'test:Cid1';
|
||||||
const cid2 = 'testCid2';
|
const cid2 = 'test:Cid2';
|
||||||
|
|
||||||
test('should delete all the messages of first channel', () async {
|
test(
|
||||||
// Preparing test data
|
'should delete all the messages and reactions of first channel',
|
||||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
() async {
|
||||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
// Preparing test data
|
||||||
|
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||||
|
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||||
|
|
||||||
// Fetched message list should match the test message list length
|
// Fetched message list should match the test message list length
|
||||||
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
||||||
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
||||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||||
|
|
||||||
// Deleting all the messages of cid1
|
// Fetched reactions list should have one reaction for given message id
|
||||||
await messageDao.deleteMessageByCids([cid1]);
|
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
|
// Deleting all the messages of cid1
|
||||||
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
|
await messageDao.deleteMessageByCids([cid1]);
|
||||||
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
|
|
||||||
expect(cid1FetchedMessages, isEmpty);
|
|
||||||
expect(cid2FetchedMessages, isNotEmpty);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should delete all the messages of both channel', () async {
|
// Fetched messages length of only cid1 should be empty
|
||||||
// Preparing test data
|
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
|
||||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
|
||||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
expect(cid1FetchedMessages, isEmpty);
|
||||||
|
expect(cid2FetchedMessages, isNotEmpty);
|
||||||
|
|
||||||
// Fetched message list should match the test message list length
|
// Reaction for the first message should be deleted too
|
||||||
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
final cid1FetchedReactions =
|
||||||
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
await database.reactionDao.getReactions(cid1firstMessageId);
|
||||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
expect(cid1FetchedReactions, isEmpty);
|
||||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Deleting all the messages of cid1
|
test(
|
||||||
await messageDao.deleteMessageByCids([cid1, cid2]);
|
'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
|
// Fetched message list should match the test message list length
|
||||||
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
|
final cid1Messages = await messageDao.getMessagesByCid(cid1);
|
||||||
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
|
final cid2Messages = await messageDao.getMessagesByCid(cid2);
|
||||||
expect(cid1FetchedMessages, isEmpty);
|
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||||
expect(cid2FetchedMessages, isEmpty);
|
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 {
|
test('getMessageById', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const id = 'testMessageId${cid}0';
|
const id = 'testMessageId${cid}0';
|
||||||
|
|
||||||
// Should be null initially
|
// Should be null initially
|
||||||
@@ -190,7 +244,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getThreadMessages', () async {
|
test('getThreadMessages', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Messages should be empty initially
|
// Messages should be empty initially
|
||||||
final messages = await messageDao.getThreadMessages(cid);
|
final messages = await messageDao.getThreadMessages(cid);
|
||||||
@@ -209,7 +263,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getThreadMessagesByParentId', () async {
|
test('getThreadMessagesByParentId', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const parentId = 'testMessageId${cid}0';
|
const parentId = 'testMessageId${cid}0';
|
||||||
|
|
||||||
// Messages should be empty initially
|
// Messages should be empty initially
|
||||||
@@ -228,7 +282,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getThreadMessagesByParentId along with pagination', () async {
|
test('getThreadMessagesByParentId along with pagination', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const parentId = 'testMessageId${cid}0';
|
const parentId = 'testMessageId${cid}0';
|
||||||
const options = PaginationParams(
|
const options = PaginationParams(
|
||||||
limit: 15,
|
limit: 15,
|
||||||
@@ -262,7 +316,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getMessagesByCid', () async {
|
test('getMessagesByCid', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Should be empty initially
|
// Should be empty initially
|
||||||
final messages = await messageDao.getMessagesByCid(cid);
|
final messages = await messageDao.getMessagesByCid(cid);
|
||||||
@@ -283,7 +337,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getMessagesByCid along with quotedMessage', () async {
|
test('getMessagesByCid along with quotedMessage', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Should be empty initially
|
// Should be empty initially
|
||||||
final messages = await messageDao.getMessagesByCid(cid);
|
final messages = await messageDao.getMessagesByCid(cid);
|
||||||
@@ -301,7 +355,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getMessagesByCid along with pagination', () async {
|
test('getMessagesByCid along with pagination', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const limit = 15;
|
const limit = 15;
|
||||||
const lessThan = 'testMessageId${cid}25';
|
const lessThan = 'testMessageId${cid}25';
|
||||||
const greaterThanOrEqual = 'testMessageId${cid}5';
|
const greaterThanOrEqual = 'testMessageId${cid}5';
|
||||||
@@ -333,7 +387,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('updateMessages', () async {
|
test('updateMessages', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Preparing test data
|
// Preparing test data
|
||||||
final insertedMessages = await _prepareTestData(cid);
|
final insertedMessages = await _prepareTestData(cid);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ void main() {
|
|||||||
bool mapAllThreadToFirstMessage = false,
|
bool mapAllThreadToFirstMessage = false,
|
||||||
int count = 3,
|
int count = 3,
|
||||||
}) async {
|
}) async {
|
||||||
|
final channels = [ChannelModel(cid: cid)];
|
||||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||||
final messages = List.generate(
|
final messages = List.generate(
|
||||||
count,
|
count,
|
||||||
@@ -83,13 +84,20 @@ void main() {
|
|||||||
if (quoted) ...quotedMessages,
|
if (quoted) ...quotedMessages,
|
||||||
if (threads) ...threadMessages
|
if (threads) ...threadMessages
|
||||||
];
|
];
|
||||||
|
final reaction = Reaction(
|
||||||
|
type: 'type',
|
||||||
|
messageId: allMessages.first.id,
|
||||||
|
user: users.first,
|
||||||
|
);
|
||||||
await database.userDao.updateUsers(users);
|
await database.userDao.updateUsers(users);
|
||||||
|
await database.channelDao.updateChannels(channels);
|
||||||
await pinnedMessageDao.updateMessages(cid, allMessages);
|
await pinnedMessageDao.updateMessages(cid, allMessages);
|
||||||
|
await database.pinnedMessageReactionDao.updateReactions([reaction]);
|
||||||
return allMessages;
|
return allMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
test('deleteMessageByIds', () async {
|
test('deleteMessageByIds', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Preparing test data
|
// Preparing test data
|
||||||
final insertedMessages = await _prepareTestData(cid);
|
final insertedMessages = await _prepareTestData(cid);
|
||||||
@@ -98,66 +106,117 @@ void main() {
|
|||||||
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||||
expect(messages.length, insertedMessages.length);
|
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
|
// Deleting 2 messages from DB
|
||||||
await pinnedMessageDao.deleteMessageByIds(
|
await pinnedMessageDao.deleteMessageByIds(
|
||||||
['testMessageId${cid}0', 'testMessageId${cid}1'],
|
[firstMessageId, 'testMessageId${cid}1'],
|
||||||
);
|
);
|
||||||
|
|
||||||
// New fetched messages length should 2 less than the
|
// New fetched messages length should 2 less than the
|
||||||
// previous fetched messages
|
// previous fetched messages
|
||||||
final newMessages = await pinnedMessageDao.getMessagesByCid(cid);
|
final newMessages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||||
expect(newMessages.length, messages.length - 2);
|
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', () {
|
group('deleteMessageByCids', () {
|
||||||
const cid1 = 'testCid1';
|
const cid1 = 'test:Cid1';
|
||||||
const cid2 = 'testCid2';
|
const cid2 = 'test:Cid2';
|
||||||
|
|
||||||
test('should delete all the messages of first channel', () async {
|
test(
|
||||||
// Preparing test data
|
'should delete all the messages and reactions of first channel',
|
||||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
() async {
|
||||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
// Preparing test data
|
||||||
|
final cid1InsertedMessages = await _prepareTestData(cid1);
|
||||||
|
final cid2InsertedMessages = await _prepareTestData(cid2);
|
||||||
|
|
||||||
// Fetched message list should match the test message list length
|
// Fetched message list should match the test message list length
|
||||||
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||||
|
|
||||||
// Deleting all the messages of cid1
|
// Fetched reactions list should have one reaction for given message id
|
||||||
await pinnedMessageDao.deleteMessageByCids([cid1]);
|
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
|
// Deleting all the messages of cid1
|
||||||
final cid1FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid1);
|
await pinnedMessageDao.deleteMessageByCids([cid1]);
|
||||||
final cid2FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid2);
|
|
||||||
expect(cid1FetchedMessages, isEmpty);
|
|
||||||
expect(cid2FetchedMessages, isNotEmpty);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should delete all the messages of both channel', () async {
|
// Fetched messages length of only cid1 should be empty
|
||||||
// Preparing test data
|
final cid1FetchedMessages =
|
||||||
final cid1InsertedMessages = await _prepareTestData(cid1);
|
await pinnedMessageDao.getMessagesByCid(cid1);
|
||||||
final cid2InsertedMessages = await _prepareTestData(cid2);
|
final cid2FetchedMessages =
|
||||||
|
await pinnedMessageDao.getMessagesByCid(cid2);
|
||||||
|
expect(cid1FetchedMessages, isEmpty);
|
||||||
|
expect(cid2FetchedMessages, isNotEmpty);
|
||||||
|
|
||||||
// Fetched message list should match the test message list length
|
// Reaction for the first message should be deleted too
|
||||||
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
final cid1FetchedReactions = await database.pinnedMessageReactionDao
|
||||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
.getReactions(cid1firstMessageId);
|
||||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
expect(cid1FetchedReactions, isEmpty);
|
||||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Deleting all the messages of cid1
|
test(
|
||||||
await pinnedMessageDao.deleteMessageByCids([cid1, cid2]);
|
'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
|
// Fetched message list should match the test message list length
|
||||||
final cid1FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid1);
|
final cid1Messages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||||
final cid2FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid2);
|
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||||
expect(cid1FetchedMessages, isEmpty);
|
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||||
expect(cid2FetchedMessages, isEmpty);
|
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 {
|
test('getMessageById', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const id = 'testMessageId${cid}0';
|
const id = 'testMessageId${cid}0';
|
||||||
|
|
||||||
// Should be null initially
|
// Should be null initially
|
||||||
@@ -175,7 +234,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getThreadMessages', () async {
|
test('getThreadMessages', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Messages should be empty initially
|
// Messages should be empty initially
|
||||||
final messages = await pinnedMessageDao.getThreadMessages(cid);
|
final messages = await pinnedMessageDao.getThreadMessages(cid);
|
||||||
@@ -194,7 +253,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getThreadMessagesByParentId', () async {
|
test('getThreadMessagesByParentId', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const parentId = 'testMessageId${cid}0';
|
const parentId = 'testMessageId${cid}0';
|
||||||
|
|
||||||
// Messages should be empty initially
|
// Messages should be empty initially
|
||||||
@@ -214,7 +273,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getThreadMessagesByParentId along with pagination', () async {
|
test('getThreadMessagesByParentId along with pagination', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const parentId = 'testMessageId${cid}0';
|
const parentId = 'testMessageId${cid}0';
|
||||||
const options = PaginationParams(
|
const options = PaginationParams(
|
||||||
limit: 15,
|
limit: 15,
|
||||||
@@ -248,7 +307,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getMessagesByCid', () async {
|
test('getMessagesByCid', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Should be empty initially
|
// Should be empty initially
|
||||||
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||||
@@ -269,7 +328,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getMessagesByCid along with quotedMessage', () async {
|
test('getMessagesByCid along with quotedMessage', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Should be empty initially
|
// Should be empty initially
|
||||||
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||||
@@ -287,7 +346,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('getMessagesByCid along with pagination', () async {
|
test('getMessagesByCid along with pagination', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
const limit = 15;
|
const limit = 15;
|
||||||
const lessThan = 'testMessageId${cid}25';
|
const lessThan = 'testMessageId${cid}25';
|
||||||
const greaterThanOrEqual = 'testMessageId${cid}5';
|
const greaterThanOrEqual = 'testMessageId${cid}5';
|
||||||
@@ -319,7 +378,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('updateMessages', () async {
|
test('updateMessages', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Preparing test data
|
// Preparing test data
|
||||||
final insertedMessages = await _prepareTestData(cid);
|
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,
|
String? userId,
|
||||||
int count = 3,
|
int count = 3,
|
||||||
}) async {
|
}) async {
|
||||||
|
const cid = 'test:Cid';
|
||||||
|
final channels = [ChannelModel(cid: cid)];
|
||||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||||
final message = Message(
|
final message = Message(
|
||||||
id: messageId,
|
id: messageId,
|
||||||
@@ -50,7 +52,8 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await database.userDao.updateUsers(users);
|
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);
|
await reactionDao.updateReactions(reactions);
|
||||||
|
|
||||||
return reactions;
|
return reactions;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Future<List<Read>> _prepareReadData(String cid, {int count = 3}) async {
|
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 users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||||
final reads = List.generate(
|
final reads = List.generate(
|
||||||
count,
|
count,
|
||||||
@@ -27,12 +28,13 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await database.userDao.updateUsers(users);
|
await database.userDao.updateUsers(users);
|
||||||
|
await database.channelDao.updateChannels(channels);
|
||||||
await readDao.updateReads(cid, reads);
|
await readDao.updateReads(cid, reads);
|
||||||
return reads;
|
return reads;
|
||||||
}
|
}
|
||||||
|
|
||||||
test('getReadsByCid', () async {
|
test('getReadsByCid', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Should be empty initially
|
// Should be empty initially
|
||||||
final reads = await readDao.getReadsByCid(cid);
|
final reads = await readDao.getReadsByCid(cid);
|
||||||
@@ -55,7 +57,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('updateReads', () async {
|
test('updateReads', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'test:Cid';
|
||||||
|
|
||||||
// Preparing test data
|
// Preparing test data
|
||||||
final insertedReads = await _prepareReadData(cid);
|
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 {
|
test('updateMessages', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'testCid';
|
||||||
final messages = List.generate(3, (index) => Message());
|
final messages = List.generate(3, (index) => Message());
|
||||||
when(() => mockDatabase.messageDao.updateMessages(cid, messages))
|
|
||||||
|
when(() => mockDatabase.messageDao.bulkUpdateMessages({cid: messages}))
|
||||||
.thenAnswer((_) => Future.value());
|
.thenAnswer((_) => Future.value());
|
||||||
|
|
||||||
await client.updateMessages(cid, messages);
|
await client.updateMessages(cid, messages);
|
||||||
verify(() => mockDatabase.messageDao.updateMessages(cid, messages))
|
verify(() => mockDatabase.messageDao.bulkUpdateMessages({cid: messages}))
|
||||||
.called(1);
|
.called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('updatePinnedMessages', () async {
|
test('updatePinnedMessages', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'testCid';
|
||||||
final messages = List.generate(3, (index) => Message());
|
final messages = List.generate(3, (index) => Message());
|
||||||
when(() => mockDatabase.pinnedMessageDao.updateMessages(cid, messages))
|
when(
|
||||||
.thenAnswer((_) => Future.value());
|
() => mockDatabase.pinnedMessageDao.bulkUpdateMessages({cid: messages}),
|
||||||
|
).thenAnswer((_) => Future.value());
|
||||||
|
|
||||||
await client.updatePinnedMessages(cid, messages);
|
await client.updatePinnedMessages(cid, messages);
|
||||||
verify(() => mockDatabase.pinnedMessageDao.updateMessages(cid, messages))
|
verify(
|
||||||
.called(1);
|
() => mockDatabase.pinnedMessageDao.bulkUpdateMessages({cid: messages}),
|
||||||
|
).called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getChannelThreads', () async {
|
test('getChannelThreads', () async {
|
||||||
@@ -456,11 +459,11 @@ void main() {
|
|||||||
test('updateMembers', () async {
|
test('updateMembers', () async {
|
||||||
const cid = 'testCid';
|
const cid = 'testCid';
|
||||||
final members = List.generate(3, (index) => Member());
|
final members = List.generate(3, (index) => Member());
|
||||||
when(() => mockDatabase.memberDao.updateMembers(cid, members))
|
when(() => mockDatabase.memberDao.bulkUpdateMembers({cid: members}))
|
||||||
.thenAnswer((_) => Future.value());
|
.thenAnswer((_) => Future.value());
|
||||||
|
|
||||||
await client.updateMembers(cid, members);
|
await client.updateMembers(cid, members);
|
||||||
verify(() => mockDatabase.memberDao.updateMembers(cid, members))
|
verify(() => mockDatabase.memberDao.bulkUpdateMembers({cid: members}))
|
||||||
.called(1);
|
.called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -473,11 +476,12 @@ void main() {
|
|||||||
lastRead: DateTime.now(),
|
lastRead: DateTime.now(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
when(() => mockDatabase.readDao.updateReads(cid, reads))
|
when(() => mockDatabase.readDao.bulkUpdateReads({cid: reads}))
|
||||||
.thenAnswer((_) => Future.value());
|
.thenAnswer((_) => Future.value());
|
||||||
|
|
||||||
await client.updateReads(cid, reads);
|
await client.updateReads(cid, reads);
|
||||||
verify(() => mockDatabase.readDao.updateReads(cid, reads)).called(1);
|
verify(() => mockDatabase.readDao.bulkUpdateReads({cid: reads}))
|
||||||
|
.called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('updateUsers', () async {
|
test('updateUsers', () async {
|
||||||
@@ -502,6 +506,21 @@ void main() {
|
|||||||
.called(1);
|
.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 {
|
test('deleteReactionsByMessageId', () async {
|
||||||
final messageIds = <String>[];
|
final messageIds = <String>[];
|
||||||
when(() =>
|
when(() =>
|
||||||
@@ -514,6 +533,17 @@ void main() {
|
|||||||
.called(1);
|
.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 {
|
test('deleteMembersByCids', () async {
|
||||||
final cids = <String>[];
|
final cids = <String>[];
|
||||||
when(() => mockDatabase.memberDao.deleteMemberByCids(cids))
|
when(() => mockDatabase.memberDao.deleteMemberByCids(cids))
|
||||||
|
|||||||
Reference in New Issue
Block a user