@@ -27,7 +27,7 @@ class Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a channel client instance from a [ChannelState] object
|
/// Create a channel client instance from a [ChannelState] object
|
||||||
Channel.fromState(this._client, ChannelState channelState) {
|
Channel.fromState(this._client, ChannelState channelState) : _extraData = {} {
|
||||||
_cid = channelState.channel!.cid;
|
_cid = channelState.channel!.cid;
|
||||||
_id = channelState.channel!.id;
|
_id = channelState.channel!.id;
|
||||||
type = channelState.channel!.type;
|
type = channelState.channel!.type;
|
||||||
@@ -45,9 +45,9 @@ class Channel {
|
|||||||
|
|
||||||
String? _id;
|
String? _id;
|
||||||
String? _cid;
|
String? _cid;
|
||||||
Map<String, dynamic>? _extraData;
|
Map<String, dynamic> _extraData;
|
||||||
|
|
||||||
set extraData(Map<String, dynamic>? extraData) {
|
set extraData(Map<String, dynamic> extraData) {
|
||||||
if (_initializedCompleter.isCompleted) {
|
if (_initializedCompleter.isCompleted) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Once the channel is initialized you should use channel.update '
|
'Once the channel is initialized you should use channel.update '
|
||||||
@@ -81,7 +81,7 @@ class Channel {
|
|||||||
/// Channel configuration as a stream
|
/// Channel configuration as a stream
|
||||||
Stream<ChannelConfig?>? get configStream {
|
Stream<ChannelConfig?>? get configStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.config);
|
return state?.channelStateStream.map((cs) => cs.channel?.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel user creator
|
/// Channel user creator
|
||||||
@@ -93,7 +93,7 @@ class Channel {
|
|||||||
/// Channel user creator as a stream
|
/// Channel user creator as a stream
|
||||||
Stream<User?>? get createdByStream {
|
Stream<User?>? get createdByStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.createdBy);
|
return state?.channelStateStream.map((cs) => cs.channel?.createdBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel frozen status
|
/// Channel frozen status
|
||||||
@@ -105,7 +105,7 @@ class Channel {
|
|||||||
/// Channel frozen status as a stream
|
/// Channel frozen status as a stream
|
||||||
Stream<bool?>? get frozenStream {
|
Stream<bool?>? get frozenStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.frozen);
|
return state?.channelStateStream.map((cs) => cs.channel?.frozen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel creation date
|
/// Channel creation date
|
||||||
@@ -117,7 +117,7 @@ class Channel {
|
|||||||
/// Channel creation date as a stream
|
/// Channel creation date as a stream
|
||||||
Stream<DateTime?>? get createdAtStream {
|
Stream<DateTime?>? get createdAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.createdAt);
|
return state?.channelStateStream.map((cs) => cs.channel?.createdAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel last message date
|
/// Channel last message date
|
||||||
@@ -131,7 +131,7 @@ class Channel {
|
|||||||
Stream<DateTime?>? get lastMessageAtStream {
|
Stream<DateTime?>? get lastMessageAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.lastMessageAt);
|
return state?.channelStateStream.map((cs) => cs.channel?.lastMessageAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel updated date
|
/// Channel updated date
|
||||||
@@ -145,7 +145,7 @@ class Channel {
|
|||||||
Stream<DateTime?>? get updatedAtStream {
|
Stream<DateTime?>? get updatedAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.updatedAt);
|
return state?.channelStateStream.map((cs) => cs.channel?.updatedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel deletion date
|
/// Channel deletion date
|
||||||
@@ -159,7 +159,7 @@ class Channel {
|
|||||||
Stream<DateTime?>? get deletedAtStream {
|
Stream<DateTime?>? get deletedAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.deletedAt);
|
return state?.channelStateStream.map((cs) => cs.channel?.deletedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel member count
|
/// Channel member count
|
||||||
@@ -173,7 +173,7 @@ class Channel {
|
|||||||
Stream<int?>? get memberCountStream {
|
Stream<int?>? get memberCountStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.memberCount);
|
return state?.channelStateStream.map((cs) => cs.channel?.memberCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel id
|
/// Channel id
|
||||||
@@ -189,13 +189,13 @@ class Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Channel extra data
|
/// Channel extra data
|
||||||
Map<String, dynamic>? get extraData =>
|
Map<String, dynamic> get extraData =>
|
||||||
state?._channelState.channel?.extraData ?? _extraData;
|
state?._channelState.channel?.extraData ?? _extraData;
|
||||||
|
|
||||||
/// Channel extra data as a stream
|
/// Channel extra data as a stream
|
||||||
Stream<Map<String, dynamic>?>? get extraDataStream {
|
Stream<Map<String, dynamic>?>? get extraDataStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs!.channel?.extraData);
|
return state?.channelStateStream.map((cs) => cs.channel?.extraData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The main Stream chat client
|
/// The main Stream chat client
|
||||||
@@ -842,7 +842,7 @@ class Channel {
|
|||||||
messages: state?.messages?..remove(oldMessage),
|
messages: state?.messages?..remove(oldMessage),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
oldMessage = state!.threads!.values
|
oldMessage = state!.threads.values
|
||||||
.expand((messages) => messages)
|
.expand((messages) => messages)
|
||||||
.firstWhereOrNull((m) => m.id == messageId);
|
.firstWhereOrNull((m) => m.id == messageId);
|
||||||
if (oldMessage?.parentId != null) {
|
if (oldMessage?.parentId != null) {
|
||||||
@@ -853,8 +853,8 @@ class Channel {
|
|||||||
state!.addMessage(parentMessage.copyWith(
|
state!.addMessage(parentMessage.copyWith(
|
||||||
replyCount: parentMessage.replyCount! - 1));
|
replyCount: parentMessage.replyCount! - 1));
|
||||||
}
|
}
|
||||||
state!.updateThreadInfo(oldMessage!.parentId,
|
state!.updateThreadInfo(oldMessage!.parentId!,
|
||||||
state!.threads![oldMessage.parentId!]!..remove(oldMessage));
|
state!.threads[oldMessage.parentId!]!..remove(oldMessage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,7 +1028,7 @@ class Channel {
|
|||||||
})
|
})
|
||||||
..addAll(options);
|
..addAll(options);
|
||||||
|
|
||||||
if (_extraData != null) {
|
if (_extraData.isNotEmpty) {
|
||||||
payload['data'] = _extraData;
|
payload['data'] = _extraData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1333,7 +1333,7 @@ class ChannelClientState {
|
|||||||
final _subscriptions = <StreamSubscription>[];
|
final _subscriptions = <StreamSubscription>[];
|
||||||
|
|
||||||
void _computeInitialUnread() {
|
void _computeInitialUnread() {
|
||||||
final userRead = channelState?.read.firstWhereOrNull(
|
final userRead = channelState.read.firstWhereOrNull(
|
||||||
(r) => r.user.id == _channel._client.state.user?.id,
|
(r) => r.user.id == _channel._client.state.user?.id,
|
||||||
);
|
);
|
||||||
if (userRead != null) {
|
if (userRead != null) {
|
||||||
@@ -1372,9 +1372,9 @@ class ChannelClientState {
|
|||||||
void _listenMemberAdded() {
|
void _listenMemberAdded() {
|
||||||
_subscriptions.add(_channel.on(EventType.memberAdded).listen((Event e) {
|
_subscriptions.add(_channel.on(EventType.memberAdded).listen((Event e) {
|
||||||
final member = e.member;
|
final member = e.member;
|
||||||
updateChannelState(channelState!.copyWith(
|
updateChannelState(channelState.copyWith(
|
||||||
members: [
|
members: [
|
||||||
...channelState!.members,
|
...channelState.members,
|
||||||
member!,
|
member!,
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
@@ -1384,9 +1384,9 @@ class ChannelClientState {
|
|||||||
void _listenMemberRemoved() {
|
void _listenMemberRemoved() {
|
||||||
_subscriptions.add(_channel.on(EventType.memberRemoved).listen((Event e) {
|
_subscriptions.add(_channel.on(EventType.memberRemoved).listen((Event e) {
|
||||||
final user = e.user;
|
final user = e.user;
|
||||||
updateChannelState(channelState!.copyWith(
|
updateChannelState(channelState.copyWith(
|
||||||
members: List.from(
|
members: List.from(
|
||||||
channelState!.members..removeWhere((m) => m.userId == user!.id)),
|
channelState.members..removeWhere((m) => m.userId == user!.id)),
|
||||||
));
|
));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -1394,7 +1394,7 @@ class ChannelClientState {
|
|||||||
void _listenChannelUpdated() {
|
void _listenChannelUpdated() {
|
||||||
_subscriptions.add(_channel.on(EventType.channelUpdated).listen((Event e) {
|
_subscriptions.add(_channel.on(EventType.channelUpdated).listen((Event e) {
|
||||||
final channel = e.channel!;
|
final channel = e.channel!;
|
||||||
updateChannelState(channelState!.copyWith(
|
updateChannelState(channelState.copyWith(
|
||||||
channel: channel,
|
channel: channel,
|
||||||
members: channel.members,
|
members: channel.members,
|
||||||
));
|
));
|
||||||
@@ -1416,14 +1416,14 @@ class ChannelClientState {
|
|||||||
/// This flag should be managed by UI sdks.
|
/// This flag should be managed by UI sdks.
|
||||||
/// When false, any new message (received by WebSocket event
|
/// When false, any new message (received by WebSocket event
|
||||||
/// - [EventType.messageNew]) will not be pushed on to message list.
|
/// - [EventType.messageNew]) will not be pushed on to message list.
|
||||||
bool get isUpToDate => _isUpToDateController.value!;
|
bool get isUpToDate => _isUpToDateController.value ?? true;
|
||||||
|
|
||||||
set isUpToDate(bool isUpToDate) => _isUpToDateController.add(isUpToDate);
|
set isUpToDate(bool isUpToDate) => _isUpToDateController.add(isUpToDate);
|
||||||
|
|
||||||
/// [isUpToDate] flag count as a stream
|
/// [isUpToDate] flag count as a stream
|
||||||
Stream<bool?> get isUpToDateStream => _isUpToDateController.stream;
|
Stream<bool> get isUpToDateStream => _isUpToDateController.stream;
|
||||||
|
|
||||||
final BehaviorSubject<bool?> _isUpToDateController =
|
final BehaviorSubject<bool> _isUpToDateController =
|
||||||
BehaviorSubject.seeded(true);
|
BehaviorSubject.seeded(true);
|
||||||
|
|
||||||
/// The retry queue associated to this channel
|
/// The retry queue associated to this channel
|
||||||
@@ -1432,7 +1432,7 @@ class ChannelClientState {
|
|||||||
/// Retry failed message
|
/// Retry failed message
|
||||||
Future<void> retryFailedMessages() async {
|
Future<void> retryFailedMessages() async {
|
||||||
final failedMessages =
|
final failedMessages =
|
||||||
<Message>[...messages, ...threads!.values.expand((v) => v)]
|
<Message>[...messages, ...threads.values.expand((v) => v)]
|
||||||
.where(
|
.where(
|
||||||
(message) =>
|
(message) =>
|
||||||
message.status != MessageSendingStatus.sent &&
|
message.status != MessageSendingStatus.sent &&
|
||||||
@@ -1549,7 +1549,7 @@ class ChannelClientState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (message.parentId != null) {
|
if (message.parentId != null) {
|
||||||
updateThreadInfo(message.parentId, [message]);
|
updateThreadInfo(message.parentId!, [message]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1592,14 +1592,14 @@ class ChannelClientState {
|
|||||||
|
|
||||||
/// Channel message list as a stream
|
/// Channel message list as a stream
|
||||||
Stream<List<Message>?> get messagesStream =>
|
Stream<List<Message>?> get messagesStream =>
|
||||||
channelStateStream.map((cs) => cs!.messages);
|
channelStateStream.map((cs) => cs.messages);
|
||||||
|
|
||||||
/// Channel pinned message list
|
/// Channel pinned message list
|
||||||
List<Message>? get pinnedMessages => _channelState.pinnedMessages.toList();
|
List<Message>? get pinnedMessages => _channelState.pinnedMessages.toList();
|
||||||
|
|
||||||
/// Channel pinned message list as a stream
|
/// Channel pinned message list as a stream
|
||||||
Stream<List<Message>?> get pinnedMessagesStream =>
|
Stream<List<Message>?> get pinnedMessagesStream =>
|
||||||
channelStateStream.map((cs) => cs!.pinnedMessages.toList());
|
channelStateStream.map((cs) => cs.pinnedMessages.toList());
|
||||||
|
|
||||||
/// Get channel last message
|
/// Get channel last message
|
||||||
Message? get lastMessage => _channelState.messages.isNotEmpty == true
|
Message? get lastMessage => _channelState.messages.isNotEmpty == true
|
||||||
@@ -1618,7 +1618,7 @@ class ChannelClientState {
|
|||||||
/// Channel members list as a stream
|
/// Channel members list as a stream
|
||||||
Stream<List<Member>> get membersStream => CombineLatestStream.combine2<
|
Stream<List<Member>> get membersStream => CombineLatestStream.combine2<
|
||||||
List<Member?>?, Map<String?, User?>, List<Member>>(
|
List<Member?>?, Map<String?, User?>, List<Member>>(
|
||||||
channelStateStream.map((cs) => cs!.members),
|
channelStateStream.map((cs) => cs.members),
|
||||||
_channel.client.state.usersStream,
|
_channel.client.state.usersStream,
|
||||||
(members, users) =>
|
(members, users) =>
|
||||||
members!.map((e) => e!.copyWith(user: users[e.user!.id])).toList(),
|
members!.map((e) => e!.copyWith(user: users[e.user!.id])).toList(),
|
||||||
@@ -1629,7 +1629,7 @@ class ChannelClientState {
|
|||||||
|
|
||||||
/// Channel watcher count as a stream
|
/// Channel watcher count as a stream
|
||||||
Stream<int?> get watcherCountStream =>
|
Stream<int?> get watcherCountStream =>
|
||||||
channelStateStream.map((cs) => cs!.watcherCount);
|
channelStateStream.map((cs) => cs.watcherCount);
|
||||||
|
|
||||||
/// Channel watchers list
|
/// Channel watchers list
|
||||||
List<User> get watchers => _channelState.watchers
|
List<User> get watchers => _channelState.watchers
|
||||||
@@ -1639,7 +1639,7 @@ class ChannelClientState {
|
|||||||
/// Channel watchers list as a stream
|
/// Channel watchers list as a stream
|
||||||
Stream<List<User>> get watchersStream => CombineLatestStream.combine2<
|
Stream<List<User>> get watchersStream => CombineLatestStream.combine2<
|
||||||
List<User>?, Map<String?, User?>, List<User>>(
|
List<User>?, Map<String?, User?>, List<User>>(
|
||||||
channelStateStream.map((cs) => cs!.watchers),
|
channelStateStream.map((cs) => cs.watchers),
|
||||||
_channel.client.state.usersStream,
|
_channel.client.state.usersStream,
|
||||||
(watchers, users) => watchers!.map((e) => users[e.id] ?? e).toList(),
|
(watchers, users) => watchers!.map((e) => users[e.id] ?? e).toList(),
|
||||||
);
|
);
|
||||||
@@ -1648,8 +1648,7 @@ class ChannelClientState {
|
|||||||
List<Read>? get read => _channelState.read;
|
List<Read>? get read => _channelState.read;
|
||||||
|
|
||||||
/// Channel read list as a stream
|
/// Channel read list as a stream
|
||||||
Stream<List<Read>?> get readStream =>
|
Stream<List<Read>?> get readStream => channelStateStream.map((cs) => cs.read);
|
||||||
channelStateStream.map((cs) => cs!.read);
|
|
||||||
|
|
||||||
final BehaviorSubject<int> _unreadCountController = BehaviorSubject.seeded(0);
|
final BehaviorSubject<int> _unreadCountController = BehaviorSubject.seeded(0);
|
||||||
|
|
||||||
@@ -1672,21 +1671,20 @@ class ChannelClientState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update threads with updated information about messages
|
/// Update threads with updated information about messages
|
||||||
void updateThreadInfo(String? parentId, List<Message>? messages) {
|
void updateThreadInfo(String parentId, List<Message> messages) {
|
||||||
final newThreads = Map<String?, List<Message>?>.from(threads!);
|
final newThreads = Map<String, List<Message>>.from(threads);
|
||||||
|
|
||||||
if (newThreads.containsKey(parentId)) {
|
if (newThreads.containsKey(parentId)) {
|
||||||
newThreads[parentId] = [
|
newThreads[parentId] = [
|
||||||
...newThreads[parentId]
|
...newThreads[parentId]
|
||||||
?.where((newMessage) =>
|
?.where(
|
||||||
!messages!.any((m) => m.id == newMessage.id))
|
(newMessage) => !messages.any((m) => m.id == newMessage.id))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[],
|
[],
|
||||||
...messages!,
|
...messages,
|
||||||
];
|
];
|
||||||
|
|
||||||
newThreads[parentId]!
|
newThreads[parentId]!.sort(_sortByCreatedAt);
|
||||||
.sort(_sortByCreatedAt as int Function(Message, Message)?);
|
|
||||||
} else {
|
} else {
|
||||||
newThreads[parentId] = messages;
|
newThreads[parentId] = messages;
|
||||||
}
|
}
|
||||||
@@ -1713,7 +1711,7 @@ class ChannelClientState {
|
|||||||
.any((newMessage) => newMessage.id == m.id) !=
|
.any((newMessage) => newMessage.id == m.id) !=
|
||||||
true)
|
true)
|
||||||
.toList(),
|
.toList(),
|
||||||
]..sort(_sortByCreatedAt as int Function(Message, Message)?);
|
]..sort(_sortByCreatedAt);
|
||||||
|
|
||||||
final newWatchers = <User>[
|
final newWatchers = <User>[
|
||||||
...updatedState.watchers,
|
...updatedState.watchers,
|
||||||
@@ -1752,27 +1750,17 @@ class ChannelClientState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int? _sortByCreatedAt(a, b) {
|
int _sortByCreatedAt(Message a, Message b) =>
|
||||||
if (a.createdAt == null) {
|
a.createdAt.compareTo(b.createdAt);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b.createdAt == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.createdAt.compareTo(b.createdAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The channel state related to this client
|
/// The channel state related to this client
|
||||||
ChannelState get _channelState => _channelStateController.value!;
|
ChannelState get _channelState => _channelStateController.value!;
|
||||||
|
|
||||||
/// The channel state related to this client as a stream
|
/// The channel state related to this client as a stream
|
||||||
Stream<ChannelState?> get channelStateStream =>
|
Stream<ChannelState> get channelStateStream => _channelStateController.stream;
|
||||||
_channelStateController.stream;
|
|
||||||
|
|
||||||
/// The channel state related to this client
|
/// The channel state related to this client
|
||||||
ChannelState? get channelState => _channelStateController.value;
|
ChannelState get channelState => _channelStateController.value!;
|
||||||
late BehaviorSubject<ChannelState> _channelStateController;
|
late BehaviorSubject<ChannelState> _channelStateController;
|
||||||
|
|
||||||
final Debounce _debouncedUpdatePersistenceChannelState;
|
final Debounce _debouncedUpdatePersistenceChannelState;
|
||||||
@@ -1783,33 +1771,33 @@ class ChannelClientState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The channel threads related to this channel
|
/// The channel threads related to this channel
|
||||||
Map<String, List<Message>>? get threads => _threadsController.value
|
Map<String, List<Message>> get threads =>
|
||||||
?.map((key, value) => MapEntry(key ?? '', value ?? []));
|
_threadsController.value!.map((key, value) => MapEntry(key, value));
|
||||||
|
|
||||||
/// The channel threads related to this channel as a stream
|
/// The channel threads related to this channel as a stream
|
||||||
Stream<Map<String?, List<Message>?>> get threadsStream =>
|
Stream<Map<String, List<Message>>> get threadsStream =>
|
||||||
_threadsController.stream;
|
_threadsController.stream;
|
||||||
final BehaviorSubject<Map<String?, List<Message>?>> _threadsController =
|
final BehaviorSubject<Map<String, List<Message>>> _threadsController =
|
||||||
BehaviorSubject.seeded({});
|
BehaviorSubject.seeded({});
|
||||||
|
|
||||||
set _threads(Map<String?, List<Message>?> v) {
|
set _threads(Map<String, List<Message>> v) {
|
||||||
_channel._client.chatPersistenceClient?.updateMessages(
|
_channel._client.chatPersistenceClient?.updateMessages(
|
||||||
_channel.cid!,
|
_channel.cid!,
|
||||||
v.values.expand((v) => v!).toList(),
|
v.values.expand((v) => v).toList(),
|
||||||
);
|
);
|
||||||
_threadsController.add(v);
|
_threadsController.add(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel related typing users last value
|
/// Channel related typing users last value
|
||||||
List<User>? get typingEvents => _typingEventsController.value as List<User>?;
|
List<User> get typingEvents => _typingEventsController.value!;
|
||||||
|
|
||||||
/// Channel related typing users stream
|
/// Channel related typing users stream
|
||||||
Stream<List<User?>> get typingEventsStream => _typingEventsController.stream;
|
Stream<List<User>> get typingEventsStream => _typingEventsController.stream;
|
||||||
final BehaviorSubject<List<User?>> _typingEventsController =
|
final BehaviorSubject<List<User>> _typingEventsController =
|
||||||
BehaviorSubject.seeded([]);
|
BehaviorSubject.seeded([]);
|
||||||
|
|
||||||
final Channel _channel;
|
final Channel _channel;
|
||||||
final Map<User?, DateTime> _typings = {};
|
final Map<User, DateTime> _typings = {};
|
||||||
|
|
||||||
void _listenTypingEvents() {
|
void _listenTypingEvents() {
|
||||||
if (_channelState.channel?.config.typingEvents == false) {
|
if (_channelState.channel?.config.typingEvents == false) {
|
||||||
@@ -1820,9 +1808,12 @@ class ChannelClientState {
|
|||||||
..add(
|
..add(
|
||||||
_channel.on(EventType.typingStart).listen(
|
_channel.on(EventType.typingStart).listen(
|
||||||
(event) {
|
(event) {
|
||||||
if (event.user!.id != _channel.client.state.user!.id) {
|
if (event.user != null) {
|
||||||
_typings[event.user] = DateTime.now();
|
final user = event.user!;
|
||||||
_typingEventsController.add(_typings.keys.toList());
|
if (user.id != _channel.client.state.user?.id) {
|
||||||
|
_typings[user] = DateTime.now();
|
||||||
|
_typingEventsController.add(_typings.keys.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -1830,9 +1821,12 @@ class ChannelClientState {
|
|||||||
..add(
|
..add(
|
||||||
_channel.on(EventType.typingStop).listen(
|
_channel.on(EventType.typingStop).listen(
|
||||||
(event) {
|
(event) {
|
||||||
if (event.user!.id != _channel.client.state.user!.id) {
|
if (event.user != null) {
|
||||||
_typings.remove(event.user);
|
final user = event.user!;
|
||||||
_typingEventsController.add(_typings.keys.toList());
|
if (user.id != _channel.client.state.user?.id) {
|
||||||
|
_typings.remove(event.user);
|
||||||
|
_typingEventsController.add(_typings.keys.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -1888,7 +1882,7 @@ class ChannelClientState {
|
|||||||
void _startCleaningPinnedMessages() {
|
void _startCleaningPinnedMessages() {
|
||||||
_pinnedMessagesTimer = Timer.periodic(const Duration(seconds: 30), (_) {
|
_pinnedMessagesTimer = Timer.periodic(const Duration(seconds: 30), (_) {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
var expiredMessages = channelState!.pinnedMessages
|
var expiredMessages = channelState.pinnedMessages
|
||||||
.where((m) => m.pinExpires?.isBefore(now) == true)
|
.where((m) => m.pinExpires?.isBefore(now) == true)
|
||||||
.toList();
|
.toList();
|
||||||
if (expiredMessages.isNotEmpty) {
|
if (expiredMessages.isNotEmpty) {
|
||||||
|
|||||||
@@ -780,10 +780,11 @@ class StreamChatClient {
|
|||||||
PaginationParams paginationParams = const PaginationParams(),
|
PaginationParams paginationParams = const PaginationParams(),
|
||||||
}) async {
|
}) async {
|
||||||
final offlineChannels = (await _chatPersistenceClient?.getChannelStates(
|
final offlineChannels = (await _chatPersistenceClient?.getChannelStates(
|
||||||
filter: filter,
|
filter: filter,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
paginationParams: paginationParams,
|
paginationParams: paginationParams,
|
||||||
))!;
|
)) ??
|
||||||
|
[];
|
||||||
final updatedData = _mapChannelStateToChannel(offlineChannels);
|
final updatedData = _mapChannelStateToChannel(offlineChannels);
|
||||||
state.channels = updatedData.key;
|
state.channels = updatedData.key;
|
||||||
return updatedData.value;
|
return updatedData.value;
|
||||||
@@ -1193,7 +1194,7 @@ class StreamChatClient {
|
|||||||
Channel channel(
|
Channel channel(
|
||||||
String type, {
|
String type, {
|
||||||
String? id,
|
String? id,
|
||||||
Map<String, dynamic>? extraData,
|
Map<String, dynamic> extraData = const {},
|
||||||
}) {
|
}) {
|
||||||
if (id != null && state.channels?.containsKey('$type:$id') == true) {
|
if (id != null && state.channels?.containsKey('$type:$id') == true) {
|
||||||
if (state.channels!['$type:$id'] != null) {
|
if (state.channels!['$type:$id'] != null) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class ChannelModel {
|
|||||||
createdAt = createdAt ?? DateTime.now(),
|
createdAt = createdAt ?? DateTime.now(),
|
||||||
updatedAt = updatedAt ?? DateTime.now(),
|
updatedAt = updatedAt ?? DateTime.now(),
|
||||||
assert(
|
assert(
|
||||||
cid != null || (id != null && type != null),
|
(cid != null && cid.contains(':')) || (id != null && type != null),
|
||||||
'provide either a cid or an id and type',
|
'provide either a cid or an id and type',
|
||||||
),
|
),
|
||||||
id = id ?? cid!.split(':')[1],
|
id = id ?? cid!.split(':')[1],
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ class OwnUser extends User {
|
|||||||
this.totalUnreadCount = 0,
|
this.totalUnreadCount = 0,
|
||||||
this.unreadChannels,
|
this.unreadChannels,
|
||||||
this.channelMutes = const [],
|
this.channelMutes = const [],
|
||||||
String id = '',
|
required String id,
|
||||||
String role = '',
|
String? role,
|
||||||
DateTime? createdAt,
|
DateTime? createdAt,
|
||||||
DateTime? updatedAt,
|
DateTime? updatedAt,
|
||||||
DateTime? lastActive,
|
DateTime? lastActive,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ OwnUser _$OwnUserFromJson(Map<String, dynamic> json) {
|
|||||||
.toList() ??
|
.toList() ??
|
||||||
[],
|
[],
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
role: json['role'] as String,
|
role: json['role'] as String?,
|
||||||
createdAt: json['created_at'] == null
|
createdAt: json['created_at'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['created_at'] as String),
|
: DateTime.parse(json['created_at'] as String),
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class User {
|
|||||||
int get hashCode => id.hashCode;
|
int get hashCode => id.hashCode;
|
||||||
|
|
||||||
/// Shortcut for user name
|
/// Shortcut for user name
|
||||||
String? get name =>
|
String get name =>
|
||||||
(extraData.containsKey('name') == true && extraData['name'] != '')
|
(extraData.containsKey('name') == true && extraData['name'] != '')
|
||||||
? extraData['name']
|
? extraData['name']
|
||||||
: id;
|
: id;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ library stream_chat;
|
|||||||
export 'package:async/async.dart';
|
export 'package:async/async.dart';
|
||||||
export 'package:dio/src/dio_error.dart';
|
export 'package:dio/src/dio_error.dart';
|
||||||
export 'package:dio/src/multipart_file.dart';
|
export 'package:dio/src/multipart_file.dart';
|
||||||
|
export 'package:dio/src/options.dart';
|
||||||
export 'package:dio/src/options.dart' show ProgressCallback;
|
export 'package:dio/src/options.dart' show ProgressCallback;
|
||||||
export 'package:logging/logging.dart' show Logger, Level;
|
export 'package:logging/logging.dart' show Logger, Level;
|
||||||
|
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
await channelClient.watch();
|
await channelClient.watch();
|
||||||
|
|
||||||
final event = Event(type: EventType.any);
|
final event = const Event(type: EventType.any);
|
||||||
|
|
||||||
when(
|
when(
|
||||||
() => mockDio.post<String>(
|
() => mockDio.post<String>(
|
||||||
@@ -564,7 +564,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
await channelClient.watch();
|
await channelClient.watch();
|
||||||
|
|
||||||
final event = Event(type: EventType.typingStart);
|
final event = const Event(type: EventType.typingStart);
|
||||||
|
|
||||||
when(
|
when(
|
||||||
() => mockDio.post<String>(
|
() => mockDio.post<String>(
|
||||||
@@ -610,7 +610,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
await channelClient.watch();
|
await channelClient.watch();
|
||||||
|
|
||||||
final event = Event(type: EventType.typingStop);
|
final event = const Event(type: EventType.typingStop);
|
||||||
|
|
||||||
when(
|
when(
|
||||||
() => mockDio.post<String>(
|
() => mockDio.post<String>(
|
||||||
@@ -901,8 +901,10 @@ void main() {
|
|||||||
'presence': true,
|
'presence': true,
|
||||||
};
|
};
|
||||||
|
|
||||||
when(() => mockDio.post<String>('/channels/messaging/query',
|
when(() => mockDio.post<String>(
|
||||||
data: options)).thenAnswer(
|
'/channels/messaging/query',
|
||||||
|
data: options,
|
||||||
|
)).thenAnswer(
|
||||||
(_) async => Response(
|
(_) async => Response(
|
||||||
data: r'''
|
data: r'''
|
||||||
{
|
{
|
||||||
@@ -1198,8 +1200,10 @@ void main() {
|
|||||||
|
|
||||||
final response = await channelClient.query(options: options);
|
final response = await channelClient.query(options: options);
|
||||||
|
|
||||||
verify(() => mockDio.post<String>('/channels/messaging/query',
|
verify(() => mockDio.post<String>(
|
||||||
data: options)).called(1);
|
'/channels/messaging/query',
|
||||||
|
data: options,
|
||||||
|
)).called(1);
|
||||||
expect(channelClient.id, response.channel?.id);
|
expect(channelClient.id, response.channel?.id);
|
||||||
expect(channelClient.cid, response.channel?.cid);
|
expect(channelClient.cid, response.channel?.cid);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ class StreamExample extends StatelessWidget {
|
|||||||
/// If you'd prefer using pre-made UI widgets for your app, please see our other
|
/// If you'd prefer using pre-made UI widgets for your app, please see our other
|
||||||
/// package, `stream_chat_flutter`.
|
/// package, `stream_chat_flutter`.
|
||||||
const StreamExample({
|
const StreamExample({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.client,
|
required this.client,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Instance of Stream Client.
|
/// Instance of Stream Client.
|
||||||
@@ -55,7 +55,7 @@ class StreamExample extends StatelessWidget {
|
|||||||
home: HomeScreen(),
|
home: HomeScreen(),
|
||||||
builder: (context, child) => StreamChatCore(
|
builder: (context, child) => StreamChatCore(
|
||||||
client: client,
|
client: client,
|
||||||
child: child,
|
child: child!,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ class HomeScreen extends StatelessWidget {
|
|||||||
'type': 'messaging',
|
'type': 'messaging',
|
||||||
'members': {
|
'members': {
|
||||||
r'$in': [
|
r'$in': [
|
||||||
StreamChatCore.of(context).user.id,
|
StreamChatCore.of(context).user!.id,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -100,10 +100,13 @@ class HomeScreen extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
errorBuilder: (BuildContext context, dynamic error) {
|
errorBuilder: (
|
||||||
|
BuildContext context,
|
||||||
|
dynamic error,
|
||||||
|
) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Oh no, something went wrong. Please check your config.'),
|
'Oh no, something went wrong. Please check your config. ${error}'),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
listBuilder: (
|
listBuilder: (
|
||||||
@@ -112,20 +115,20 @@ class HomeScreen extends StatelessWidget {
|
|||||||
) =>
|
) =>
|
||||||
LazyLoadScrollView(
|
LazyLoadScrollView(
|
||||||
onEndOfPage: () async {
|
onEndOfPage: () async {
|
||||||
channelListController.paginateData();
|
channelListController.paginateData!();
|
||||||
},
|
},
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: channels.length,
|
itemCount: channels.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
final _item = channels[index];
|
final _item = channels[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_item.name),
|
title: Text(_item.name!),
|
||||||
subtitle: StreamBuilder<Message>(
|
subtitle: StreamBuilder<Message?>(
|
||||||
stream: _item.state.lastMessageStream,
|
stream: _item.state!.lastMessageStream,
|
||||||
initialData: _item.state.lastMessage,
|
initialData: _item.state!.lastMessage,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
return Text(snapshot.data.text);
|
return Text(snapshot.data!.text!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SizedBox();
|
return SizedBox();
|
||||||
@@ -169,8 +172,8 @@ class MessageScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MessageScreenState extends State<MessageScreen> {
|
class _MessageScreenState extends State<MessageScreen> {
|
||||||
TextEditingController _controller;
|
late final TextEditingController _controller;
|
||||||
ScrollController _scrollController;
|
late final ScrollController _scrollController;
|
||||||
final messageListController = MessageListController();
|
final messageListController = MessageListController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -203,11 +206,11 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: StreamBuilder<List<User>>(
|
title: StreamBuilder<List<User>>(
|
||||||
initialData: channel.state.typingEvents,
|
initialData: channel.state?.typingEvents,
|
||||||
stream: channel.state.typingEventsStream,
|
stream: channel.state?.typingEventsStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data.isNotEmpty) {
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
return Text('${snapshot.data.first.name} is typing...');
|
return Text('${snapshot.data!.first.name} is typing...');
|
||||||
}
|
}
|
||||||
return SizedBox();
|
return SizedBox();
|
||||||
},
|
},
|
||||||
@@ -219,9 +222,10 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: LazyLoadScrollView(
|
child: LazyLoadScrollView(
|
||||||
onEndOfPage: () async {
|
onEndOfPage: () async {
|
||||||
messageListController.paginateData();
|
messageListController.paginateData!();
|
||||||
},
|
},
|
||||||
child: MessageListCore(
|
child: MessageListCore(
|
||||||
|
messageListController: messageListController,
|
||||||
emptyBuilder: (BuildContext context) {
|
emptyBuilder: (BuildContext context) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text('Nothing here yet'),
|
child: Text('Nothing here yet'),
|
||||||
@@ -247,12 +251,12 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
final item = messages[index];
|
final item = messages[index];
|
||||||
final client = StreamChatCore.of(context).client;
|
final client = StreamChatCore.of(context).client;
|
||||||
if (item.user.id == client.uid) {
|
if (item.user!.id == client.uid) {
|
||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(item.text),
|
child: Text(item.text!),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -260,7 +264,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(item.text),
|
child: Text(item.text!),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -268,7 +272,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
errorWidgetBuilder: (BuildContext context, error) {
|
errorWidgetBuilder: (BuildContext context, error) {
|
||||||
print(error?.toString());
|
print(error.toString());
|
||||||
return Center(
|
return Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 100.0,
|
height: 100.0,
|
||||||
@@ -282,7 +286,7 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -303,12 +307,14 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
await channel.sendMessage(
|
await channel.sendMessage(
|
||||||
Message(text: _controller.value.text),
|
Message(text: _controller.value.text),
|
||||||
);
|
);
|
||||||
_controller.clear();
|
if (mounted) {
|
||||||
_updateList();
|
_controller.clear();
|
||||||
|
_updateList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.send,
|
Icons.send,
|
||||||
@@ -332,12 +338,12 @@ class _MessageScreenState extends State<MessageScreen> {
|
|||||||
/// below, we add two simple extensions to the [StreamChatClient] and [Channel].
|
/// below, we add two simple extensions to the [StreamChatClient] and [Channel].
|
||||||
extension on StreamChatClient {
|
extension on StreamChatClient {
|
||||||
/// Fetches the current user id.
|
/// Fetches the current user id.
|
||||||
String get uid => state.user.id;
|
String get uid => state.user!.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on Channel {
|
extension on Channel {
|
||||||
/// Fetches the name of the channel by accessing [extraData] or [cid].
|
/// Fetches the name of the channel by accessing [extraData] or [cid].
|
||||||
String get name {
|
String? get name {
|
||||||
final _channelName = extraData['name'];
|
final _channelName = extraData['name'];
|
||||||
if (_channelName != null) {
|
if (_channelName != null) {
|
||||||
return _channelName;
|
return _channelName;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
version: 1.0.0+1
|
version: 1.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ import 'package:stream_chat_flutter_core/src/typedef.dart';
|
|||||||
class ChannelListCore extends StatefulWidget {
|
class ChannelListCore extends StatefulWidget {
|
||||||
/// Instantiate a new ChannelListView
|
/// Instantiate a new ChannelListView
|
||||||
const ChannelListCore({
|
const ChannelListCore({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.errorBuilder,
|
required this.errorBuilder,
|
||||||
@required this.emptyBuilder,
|
required this.emptyBuilder,
|
||||||
@required this.loadingBuilder,
|
required this.loadingBuilder,
|
||||||
@required this.listBuilder,
|
required this.listBuilder,
|
||||||
this.filter,
|
this.filter,
|
||||||
this.options,
|
this.options,
|
||||||
this.sort,
|
this.sort,
|
||||||
@@ -69,29 +69,13 @@ class ChannelListCore extends StatefulWidget {
|
|||||||
limit: 25,
|
limit: 25,
|
||||||
),
|
),
|
||||||
this.channelListController,
|
this.channelListController,
|
||||||
}) : assert(
|
}) : super(key: key);
|
||||||
errorBuilder != null,
|
|
||||||
'Parameter errorBuilder should not be null',
|
|
||||||
),
|
|
||||||
assert(
|
|
||||||
emptyBuilder != null,
|
|
||||||
'Parameter emptyBuilder should not be null',
|
|
||||||
),
|
|
||||||
assert(
|
|
||||||
loadingBuilder != null,
|
|
||||||
'Parameter loadingBuilder should not be null',
|
|
||||||
),
|
|
||||||
assert(
|
|
||||||
listBuilder != null,
|
|
||||||
'Parameter listBuilder should not be null',
|
|
||||||
),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// A [ChannelListController] allows reloading and pagination.
|
/// A [ChannelListController] allows reloading and pagination.
|
||||||
/// Use [ChannelListController.loadData] and
|
/// Use [ChannelListController.loadData] and
|
||||||
/// [ChannelListController.paginateData] respectively for reloading and
|
/// [ChannelListController.paginateData] respectively for reloading and
|
||||||
/// pagination.
|
/// pagination.
|
||||||
final ChannelListController channelListController;
|
final ChannelListController? channelListController;
|
||||||
|
|
||||||
/// The builder that will be used in case of error
|
/// The builder that will be used in case of error
|
||||||
final ErrorBuilder errorBuilder;
|
final ErrorBuilder errorBuilder;
|
||||||
@@ -108,20 +92,20 @@ class ChannelListCore extends StatefulWidget {
|
|||||||
/// The query filters to use.
|
/// The query filters to use.
|
||||||
/// You can query on any of the custom fields you've defined on the [Channel].
|
/// You can query on any of the custom fields you've defined on the [Channel].
|
||||||
/// You can also filter other built-in channel fields.
|
/// You can also filter other built-in channel fields.
|
||||||
final Map<String, dynamic> filter;
|
final Map<String, dynamic>? filter;
|
||||||
|
|
||||||
/// Query channels options.
|
/// Query channels options.
|
||||||
///
|
///
|
||||||
/// state: if true returns the Channel state
|
/// state: if true returns the Channel state
|
||||||
/// watch: if true listen to changes to this Channel in real time.
|
/// watch: if true listen to changes to this Channel in real time.
|
||||||
final Map<String, dynamic> options;
|
final Map<String, dynamic>? options;
|
||||||
|
|
||||||
/// The sorting used for the channels matching the filters.
|
/// The sorting used for the channels matching the filters.
|
||||||
/// Sorting is based on field and direction, multiple sorting options can be
|
/// Sorting is based on field and direction, multiple sorting options can be
|
||||||
/// provided.
|
/// provided.
|
||||||
/// You can sort based on last_updated, last_message_at, updated_at, created
|
/// You can sort based on last_updated, last_message_at, updated_at, created
|
||||||
/// _at or member_count. Direction can be ascending or descending.
|
/// _at or member_count. Direction can be ascending or descending.
|
||||||
final List<SortOption<ChannelModel>> sort;
|
final List<SortOption<ChannelModel>>? sort;
|
||||||
|
|
||||||
/// Pagination parameters
|
/// Pagination parameters
|
||||||
/// limit: the number of channels to return (max is 30)
|
/// limit: the number of channels to return (max is 30)
|
||||||
@@ -149,12 +133,12 @@ class ChannelListCoreState extends State<ChannelListCore> {
|
|||||||
stream: channelsBlocState.channelsStream,
|
stream: channelsBlocState.channelsStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return widget.errorBuilder(context, snapshot.error);
|
return widget.errorBuilder(context, snapshot.error!);
|
||||||
}
|
}
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return widget.loadingBuilder(context);
|
return widget.loadingBuilder(context);
|
||||||
}
|
}
|
||||||
final channels = snapshot.data;
|
final channels = snapshot.data!;
|
||||||
if (channels.isEmpty) {
|
if (channels.isEmpty) {
|
||||||
return widget.emptyBuilder(context);
|
return widget.emptyBuilder(context);
|
||||||
}
|
}
|
||||||
@@ -186,7 +170,7 @@ class ChannelListCoreState extends State<ChannelListCore> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamSubscription<Event> _subscription;
|
late StreamSubscription<Event> _subscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -203,8 +187,8 @@ class ChannelListCoreState extends State<ChannelListCore> {
|
|||||||
.listen((event) => loadData());
|
.listen((event) => loadData());
|
||||||
|
|
||||||
if (widget.channelListController != null) {
|
if (widget.channelListController != null) {
|
||||||
widget.channelListController.loadData = loadData;
|
widget.channelListController!.loadData = loadData;
|
||||||
widget.channelListController.paginateData = paginateData;
|
widget.channelListController!.paginateData = paginateData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,8 +199,8 @@ class ChannelListCoreState extends State<ChannelListCore> {
|
|||||||
if (widget.filter?.toString() != oldWidget.filter?.toString() ||
|
if (widget.filter?.toString() != oldWidget.filter?.toString() ||
|
||||||
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
|
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
|
||||||
widget.options?.toString() != oldWidget.options?.toString() ||
|
widget.options?.toString() != oldWidget.options?.toString() ||
|
||||||
widget.pagination?.toJson()?.toString() !=
|
widget.pagination.toJson().toString() !=
|
||||||
oldWidget.pagination?.toJson()?.toString()) {
|
oldWidget.pagination.toJson().toString()) {
|
||||||
loadData();
|
loadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,10 +217,10 @@ class ChannelListCoreState extends State<ChannelListCore> {
|
|||||||
class ChannelListController {
|
class ChannelListController {
|
||||||
/// This function calls Stream's servers to load a list of channels.
|
/// This function calls Stream's servers to load a list of channels.
|
||||||
/// If there is existing data, calling this function causes a reload.
|
/// If there is existing data, calling this function causes a reload.
|
||||||
AsyncCallback loadData;
|
AsyncCallback? loadData;
|
||||||
|
|
||||||
/// This function is used to load another page of data. Note, [loadData]
|
/// This function is used to load another page of data. Note, [loadData]
|
||||||
/// should be used to populate the initial page of data. Calling
|
/// should be used to populate the initial page of data. Calling
|
||||||
/// [paginateData] performs a query to load subsequent pages.
|
/// [paginateData] performs a query to load subsequent pages.
|
||||||
AsyncCallback paginateData;
|
AsyncCallback? paginateData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,12 @@ class ChannelsBloc extends StatefulWidget {
|
|||||||
/// Creates a new [ChannelsBloc]. The parameter [child] must be supplied and
|
/// Creates a new [ChannelsBloc]. The parameter [child] must be supplied and
|
||||||
/// not null.
|
/// not null.
|
||||||
const ChannelsBloc({
|
const ChannelsBloc({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.child,
|
required this.child,
|
||||||
this.lockChannelsOrder = false,
|
this.lockChannelsOrder = false,
|
||||||
this.channelsComparator,
|
this.channelsComparator,
|
||||||
this.shouldAddChannel,
|
this.shouldAddChannel,
|
||||||
}) : assert(child != null, 'Parameter child should not be null.'),
|
}) : super(key: key);
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// The widget child
|
/// The widget child
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@@ -36,18 +35,18 @@ class ChannelsBloc extends StatefulWidget {
|
|||||||
final bool lockChannelsOrder;
|
final bool lockChannelsOrder;
|
||||||
|
|
||||||
/// Comparator used to sort the channels when a message.new event is received
|
/// Comparator used to sort the channels when a message.new event is received
|
||||||
final Comparator<Channel> channelsComparator;
|
final Comparator<Channel>? channelsComparator;
|
||||||
|
|
||||||
/// Function used to evaluate if a channel should be added to the list when a
|
/// Function used to evaluate if a channel should be added to the list when a
|
||||||
/// message.new event is received
|
/// message.new event is received
|
||||||
final bool Function(Event) shouldAddChannel;
|
final bool Function(Event)? shouldAddChannel;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ChannelsBlocState createState() => ChannelsBlocState();
|
ChannelsBlocState createState() => ChannelsBlocState();
|
||||||
|
|
||||||
/// Use this method to get the current [ChannelsBlocState] instance
|
/// Use this method to get the current [ChannelsBlocState] instance
|
||||||
static ChannelsBlocState of(BuildContext context) {
|
static ChannelsBlocState of(BuildContext context) {
|
||||||
ChannelsBlocState streamChatState;
|
ChannelsBlocState? streamChatState;
|
||||||
|
|
||||||
streamChatState = context.findAncestorStateOfType<ChannelsBlocState>();
|
streamChatState = context.findAncestorStateOfType<ChannelsBlocState>();
|
||||||
|
|
||||||
@@ -69,14 +68,15 @@ class ChannelsBlocState extends State<ChannelsBloc>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The current channel list
|
/// The current channel list
|
||||||
List<Channel> get channels => _channelsController.value;
|
List<Channel>? get channels => _channelsController.value;
|
||||||
|
|
||||||
/// The current channel list as a stream
|
/// The current channel list as a stream
|
||||||
Stream<List<Channel>> get channelsStream => _channelsController.stream;
|
Stream<List<Channel>> get channelsStream => _channelsController.stream;
|
||||||
|
|
||||||
final _queryChannelsLoadingController = BehaviorSubject.seeded(false);
|
final _queryChannelsLoadingController = BehaviorSubject.seeded(false);
|
||||||
|
|
||||||
final _channelsController = BehaviorSubject<List<Channel>>();
|
final BehaviorSubject<List<Channel>> _channelsController =
|
||||||
|
BehaviorSubject<List<Channel>>();
|
||||||
|
|
||||||
/// The stream notifying the state of queryChannel call
|
/// The stream notifying the state of queryChannel call
|
||||||
Stream<bool> get queryChannelsLoading =>
|
Stream<bool> get queryChannelsLoading =>
|
||||||
@@ -88,10 +88,10 @@ class ChannelsBlocState extends State<ChannelsBloc>
|
|||||||
|
|
||||||
/// Calls [client.queryChannels] updating [queryChannelsLoading] stream
|
/// Calls [client.queryChannels] updating [queryChannelsLoading] stream
|
||||||
Future<void> queryChannels({
|
Future<void> queryChannels({
|
||||||
Map<String, dynamic> filter,
|
Map<String, dynamic>? filter,
|
||||||
List<SortOption<ChannelModel>> sortOptions,
|
List<SortOption<ChannelModel>>? sortOptions,
|
||||||
PaginationParams paginationParams,
|
PaginationParams paginationParams = const PaginationParams(limit: 30),
|
||||||
Map<String, dynamic> options,
|
Map<String, dynamic>? options,
|
||||||
}) async {
|
}) async {
|
||||||
final client = StreamChatCore.of(context).client;
|
final client = StreamChatCore.of(context).client;
|
||||||
|
|
||||||
@@ -104,9 +104,7 @@ class ChannelsBlocState extends State<ChannelsBloc>
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final clear = paginationParams == null ||
|
final clear = paginationParams.offset == 0;
|
||||||
paginationParams.offset == null ||
|
|
||||||
paginationParams.offset == 0;
|
|
||||||
final oldChannels = List<Channel>.from(channels ?? []);
|
final oldChannels = List<Channel>.from(channels ?? []);
|
||||||
var newChannels = <Channel>[];
|
var newChannels = <Channel>[];
|
||||||
await for (final channels in client.queryChannels(
|
await for (final channels in client.queryChannels(
|
||||||
@@ -123,7 +121,7 @@ class ChannelsBlocState extends State<ChannelsBloc>
|
|||||||
_channelsController.add(temp);
|
_channelsController.add(temp);
|
||||||
}
|
}
|
||||||
if (_channelsController.hasValue &&
|
if (_channelsController.hasValue &&
|
||||||
_queryChannelsLoadingController.value) {
|
_queryChannelsLoadingController.value!) {
|
||||||
_queryChannelsLoadingController.sink.add(false);
|
_queryChannelsLoadingController.sink.add(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,9 +160,9 @@ class ChannelsBlocState extends State<ChannelsBloc>
|
|||||||
newChannels.insert(0, _hiddenChannels[hiddenIndex]);
|
newChannels.insert(0, _hiddenChannels[hiddenIndex]);
|
||||||
_hiddenChannels.removeAt(hiddenIndex);
|
_hiddenChannels.removeAt(hiddenIndex);
|
||||||
} else {
|
} else {
|
||||||
if (client.state?.channels != null &&
|
if (client.state.channels != null &&
|
||||||
client.state?.channels[e.cid] != null) {
|
client.state.channels?[e.cid] != null) {
|
||||||
newChannels.insert(0, client.state.channels[e.cid]);
|
newChannels.insert(0, client.state.channels![e.cid]!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +193,7 @@ class ChannelsBlocState extends State<ChannelsBloc>
|
|||||||
// ignore: cascade_invocations
|
// ignore: cascade_invocations
|
||||||
final channel = e.channel;
|
final channel = e.channel;
|
||||||
_channelsController.add(List.from(
|
_channelsController.add(List.from(
|
||||||
(channels ?? [])..removeWhere((c) => c.cid == channel.cid)));
|
(channels ?? [])..removeWhere((c) => c.cid == channel?.cid)));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,34 +9,33 @@ class LazyLoadScrollView extends StatefulWidget {
|
|||||||
/// Creates a new instance of [LazyLoadScrollView]. The parameter [child]
|
/// Creates a new instance of [LazyLoadScrollView]. The parameter [child]
|
||||||
/// must be supplied and not null.
|
/// must be supplied and not null.
|
||||||
const LazyLoadScrollView({
|
const LazyLoadScrollView({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.child,
|
required this.child,
|
||||||
this.onStartOfPage,
|
this.onStartOfPage,
|
||||||
this.onEndOfPage,
|
this.onEndOfPage,
|
||||||
this.onPageScrollStart,
|
this.onPageScrollStart,
|
||||||
this.onPageScrollEnd,
|
this.onPageScrollEnd,
|
||||||
this.onInBetweenOfPage,
|
this.onInBetweenOfPage,
|
||||||
this.scrollOffset = 100,
|
this.scrollOffset = 100,
|
||||||
}) : assert(child != null, 'Parameter child should not be null'),
|
}) : super(key: key);
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// The [Widget] that this widget watches for changes on
|
/// The [Widget] that this widget watches for changes on
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
/// Called when the [child] reaches the start of the list
|
/// Called when the [child] reaches the start of the list
|
||||||
final AsyncCallback onStartOfPage;
|
final AsyncCallback? onStartOfPage;
|
||||||
|
|
||||||
/// Called when the [child] reaches the end of the list
|
/// Called when the [child] reaches the end of the list
|
||||||
final AsyncCallback onEndOfPage;
|
final AsyncCallback? onEndOfPage;
|
||||||
|
|
||||||
/// Called when the list scrolling starts
|
/// Called when the list scrolling starts
|
||||||
final VoidCallback onPageScrollStart;
|
final VoidCallback? onPageScrollStart;
|
||||||
|
|
||||||
/// Called when the list scrolling ends
|
/// Called when the list scrolling ends
|
||||||
final VoidCallback onPageScrollEnd;
|
final VoidCallback? onPageScrollEnd;
|
||||||
|
|
||||||
/// Called every time the [child] is in-between the list
|
/// Called every time the [child] is in-between the list
|
||||||
final VoidCallback onInBetweenOfPage;
|
final VoidCallback? onInBetweenOfPage;
|
||||||
|
|
||||||
/// The offset to take into account when triggering [onEndOfPage]/[onStartOfPage] in pixels
|
/// The offset to take into account when triggering [onEndOfPage]/[onStartOfPage] in pixels
|
||||||
final double scrollOffset;
|
final double scrollOffset;
|
||||||
@@ -46,7 +45,7 @@ class LazyLoadScrollView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
|
class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
|
||||||
_LoadingStatus _loadMoreStatus = _LoadingStatus.stable;
|
var _loadMoreStatus = _LoadingStatus.stable;
|
||||||
double _scrollPosition = 0;
|
double _scrollPosition = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -59,13 +58,13 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
|
|||||||
bool _onNotification(ScrollNotification notification) {
|
bool _onNotification(ScrollNotification notification) {
|
||||||
if (notification is ScrollStartNotification) {
|
if (notification is ScrollStartNotification) {
|
||||||
if (widget.onPageScrollStart != null) {
|
if (widget.onPageScrollStart != null) {
|
||||||
widget.onPageScrollStart();
|
widget.onPageScrollStart!();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notification is ScrollEndNotification) {
|
if (notification is ScrollEndNotification) {
|
||||||
if (widget.onPageScrollEnd != null) {
|
if (widget.onPageScrollEnd != null) {
|
||||||
widget.onPageScrollEnd();
|
widget.onPageScrollEnd!();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,12 +72,12 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
|
|||||||
final pixels = notification.metrics.pixels;
|
final pixels = notification.metrics.pixels;
|
||||||
final maxScrollExtent = notification.metrics.maxScrollExtent;
|
final maxScrollExtent = notification.metrics.maxScrollExtent;
|
||||||
final minScrollExtent = notification.metrics.minScrollExtent;
|
final minScrollExtent = notification.metrics.minScrollExtent;
|
||||||
final scrollOffset = widget.scrollOffset ?? 0;
|
final scrollOffset = widget.scrollOffset;
|
||||||
|
|
||||||
if (pixels > (minScrollExtent + scrollOffset) &&
|
if (pixels > (minScrollExtent + scrollOffset) &&
|
||||||
pixels < (maxScrollExtent - scrollOffset)) {
|
pixels < (maxScrollExtent - scrollOffset)) {
|
||||||
if (widget.onInBetweenOfPage != null) {
|
if (widget.onInBetweenOfPage != null) {
|
||||||
widget.onInBetweenOfPage();
|
widget.onInBetweenOfPage!();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,10 +113,10 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onEndOfPage() {
|
void _onEndOfPage() {
|
||||||
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) {
|
if (_loadMoreStatus == _LoadingStatus.stable) {
|
||||||
if (widget.onEndOfPage != null) {
|
if (widget.onEndOfPage != null) {
|
||||||
_loadMoreStatus = _LoadingStatus.loading;
|
_loadMoreStatus = _LoadingStatus.loading;
|
||||||
widget.onEndOfPage().whenComplete(() {
|
widget.onEndOfPage!().whenComplete(() {
|
||||||
_loadMoreStatus = _LoadingStatus.stable;
|
_loadMoreStatus = _LoadingStatus.stable;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -125,10 +124,10 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onStartOfPage() {
|
void _onStartOfPage() {
|
||||||
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) {
|
if (_loadMoreStatus == _LoadingStatus.stable) {
|
||||||
if (widget.onStartOfPage != null) {
|
if (widget.onStartOfPage != null) {
|
||||||
_loadMoreStatus = _LoadingStatus.loading;
|
_loadMoreStatus = _LoadingStatus.loading;
|
||||||
widget.onStartOfPage().whenComplete(() {
|
widget.onStartOfPage!().whenComplete(() {
|
||||||
_loadMoreStatus = _LoadingStatus.stable;
|
_loadMoreStatus = _LoadingStatus.stable;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,30 +61,20 @@ import 'package:stream_chat_flutter_core/src/typedef.dart';
|
|||||||
class MessageListCore extends StatefulWidget {
|
class MessageListCore extends StatefulWidget {
|
||||||
/// Instantiate a new [MessageListView].
|
/// Instantiate a new [MessageListView].
|
||||||
const MessageListCore({
|
const MessageListCore({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.loadingBuilder,
|
required this.loadingBuilder,
|
||||||
@required this.emptyBuilder,
|
required this.emptyBuilder,
|
||||||
@required this.messageListBuilder,
|
required this.messageListBuilder,
|
||||||
@required this.errorWidgetBuilder,
|
required this.errorWidgetBuilder,
|
||||||
this.showScrollToBottom = true,
|
this.showScrollToBottom = true,
|
||||||
this.parentMessage,
|
this.parentMessage,
|
||||||
this.messageListController,
|
this.messageListController,
|
||||||
this.messageFilter,
|
this.messageFilter,
|
||||||
}) : assert(loadingBuilder != null, 'loadingBuilder should not be null'),
|
}) : super(key: key);
|
||||||
assert(emptyBuilder != null, 'emptyBuilder should not be null'),
|
|
||||||
assert(
|
|
||||||
messageListBuilder != null,
|
|
||||||
'messageListBuilder should not be null',
|
|
||||||
),
|
|
||||||
assert(
|
|
||||||
errorWidgetBuilder != null,
|
|
||||||
'errorWidgetBuilder should not be null',
|
|
||||||
),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// A [MessageListController] allows pagination.
|
/// A [MessageListController] allows pagination.
|
||||||
/// Use [ChannelListController.paginateData] pagination.
|
/// Use [ChannelListController.paginateData] pagination.
|
||||||
final MessageListController messageListController;
|
final MessageListController? messageListController;
|
||||||
|
|
||||||
/// Function called when messages are fetched
|
/// Function called when messages are fetched
|
||||||
final Widget Function(BuildContext, List<Message>) messageListBuilder;
|
final Widget Function(BuildContext, List<Message>) messageListBuilder;
|
||||||
@@ -108,10 +98,10 @@ class MessageListCore extends StatefulWidget {
|
|||||||
|
|
||||||
/// If the current message belongs to a `thread`, this property represents the
|
/// If the current message belongs to a `thread`, this property represents the
|
||||||
/// first message or the parent of the conversation.
|
/// first message or the parent of the conversation.
|
||||||
final Message parentMessage;
|
final Message? parentMessage;
|
||||||
|
|
||||||
/// Predicate used to filter messages
|
/// Predicate used to filter messages
|
||||||
final bool Function(Message) messageFilter;
|
final bool Function(Message)? messageFilter;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MessageListCoreState createState() => MessageListCoreState();
|
MessageListCoreState createState() => MessageListCoreState();
|
||||||
@@ -119,41 +109,44 @@ class MessageListCore extends StatefulWidget {
|
|||||||
|
|
||||||
/// The current state of the [MessageListCore].
|
/// The current state of the [MessageListCore].
|
||||||
class MessageListCoreState extends State<MessageListCore> {
|
class MessageListCoreState extends State<MessageListCore> {
|
||||||
StreamChannelState _streamChannel;
|
late StreamChannelState _streamChannel;
|
||||||
|
|
||||||
bool get _upToDate => _streamChannel.channel.state.isUpToDate;
|
bool get _upToDate => _streamChannel.channel.state?.isUpToDate ?? true;
|
||||||
|
|
||||||
bool get _isThreadConversation => widget.parentMessage != null;
|
bool get _isThreadConversation => widget.parentMessage != null;
|
||||||
|
|
||||||
OwnUser get _currentUser => _streamChannel.channel.client.state.user;
|
OwnUser? get _currentUser => _streamChannel.channel.client.state.user;
|
||||||
|
|
||||||
var _messages = <Message>[];
|
var _messages = <Message>[];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final messagesStream = _isThreadConversation
|
final messagesStream = _isThreadConversation
|
||||||
? _streamChannel.channel.state.threadsStream
|
? _streamChannel.channel.state?.threadsStream
|
||||||
.where((threads) => threads.containsKey(widget.parentMessage.id))
|
.where((threads) => threads.containsKey(widget.parentMessage!.id))
|
||||||
.map((threads) => threads[widget.parentMessage.id])
|
.map((threads) => threads[widget.parentMessage!.id])
|
||||||
: _streamChannel.channel.state?.messagesStream;
|
: _streamChannel.channel.state?.messagesStream;
|
||||||
|
|
||||||
bool defaultFilter(Message m) {
|
bool defaultFilter(Message m) {
|
||||||
final isMyMessage = m.user.id == _currentUser.id;
|
final isMyMessage = m.user?.id == _currentUser?.id;
|
||||||
final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true;
|
final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true;
|
||||||
if (isDeletedOrShadowed && !isMyMessage) return false;
|
if (isDeletedOrShadowed && !isMyMessage) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return StreamBuilder<List<Message>>(
|
return StreamBuilder<List<Message>?>(
|
||||||
stream: messagesStream?.map((messages) =>
|
stream: messagesStream?.map((messages) =>
|
||||||
messages?.where(widget.messageFilter ?? defaultFilter)?.toList()),
|
messages?.where(widget.messageFilter ?? defaultFilter).toList(
|
||||||
|
growable: false,
|
||||||
|
)),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return widget.errorWidgetBuilder(context, snapshot.error);
|
return widget.errorWidgetBuilder(context, snapshot.error!);
|
||||||
} else if (!snapshot.hasData) {
|
} else if (!snapshot.hasData) {
|
||||||
return widget.loadingBuilder(context);
|
return widget.loadingBuilder(context);
|
||||||
} else {
|
} else {
|
||||||
final messageList = snapshot.data?.reversed?.toList() ?? [];
|
final messageList =
|
||||||
|
snapshot.data?.reversed.toList(growable: false) ?? [];
|
||||||
if (messageList.isEmpty && !_isThreadConversation) {
|
if (messageList.isEmpty && !_isThreadConversation) {
|
||||||
if (_upToDate) {
|
if (_upToDate) {
|
||||||
return widget.emptyBuilder(context);
|
return widget.emptyBuilder(context);
|
||||||
@@ -169,13 +162,14 @@ class MessageListCoreState extends State<MessageListCore> {
|
|||||||
|
|
||||||
/// Fetches more messages with updated pagination and updates the widget.
|
/// Fetches more messages with updated pagination and updates the widget.
|
||||||
///
|
///
|
||||||
/// Optionally pass the fetch direction, defaults to [QueryDirection.bottom]
|
/// Optionally pass the fetch direction, defaults to [QueryDirection.top]
|
||||||
Future<void> paginateData(
|
Future<void> paginateData({
|
||||||
{QueryDirection direction = QueryDirection.bottom}) {
|
QueryDirection direction = QueryDirection.top,
|
||||||
|
}) {
|
||||||
if (!_isThreadConversation) {
|
if (!_isThreadConversation) {
|
||||||
return _streamChannel.queryMessages(direction: direction);
|
return _streamChannel.queryMessages(direction: direction);
|
||||||
} else {
|
} else {
|
||||||
return _streamChannel.getReplies(widget.parentMessage.id);
|
return _streamChannel.getReplies(widget.parentMessage!.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,11 +178,11 @@ class MessageListCoreState extends State<MessageListCore> {
|
|||||||
_streamChannel = StreamChannel.of(context);
|
_streamChannel = StreamChannel.of(context);
|
||||||
|
|
||||||
if (_isThreadConversation) {
|
if (_isThreadConversation) {
|
||||||
_streamChannel.getReplies(widget.parentMessage.id);
|
_streamChannel.getReplies(widget.parentMessage!.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.messageListController != null) {
|
if (widget.messageListController != null) {
|
||||||
widget.messageListController.paginateData = paginateData;
|
widget.messageListController!.paginateData = paginateData;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -206,5 +200,5 @@ class MessageListCoreState extends State<MessageListCore> {
|
|||||||
/// Controller used for paginating data in [ChannelListView]
|
/// Controller used for paginating data in [ChannelListView]
|
||||||
class MessageListController {
|
class MessageListController {
|
||||||
/// Call this function to load further data
|
/// Call this function to load further data
|
||||||
Future<void> Function({QueryDirection direction}) paginateData;
|
Future<void> Function({QueryDirection direction})? paginateData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ import 'package:stream_chat_flutter_core/src/stream_chat_core.dart';
|
|||||||
class MessageSearchBloc extends StatefulWidget {
|
class MessageSearchBloc extends StatefulWidget {
|
||||||
/// Instantiate a new MessageSearchBloc
|
/// Instantiate a new MessageSearchBloc
|
||||||
const MessageSearchBloc({
|
const MessageSearchBloc({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.child,
|
required this.child,
|
||||||
}) : assert(child != null, 'Parameter child should not be null.'),
|
}) : super(key: key);
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// The widget child
|
/// The widget child
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@@ -26,7 +25,7 @@ class MessageSearchBloc extends StatefulWidget {
|
|||||||
|
|
||||||
/// Use this method to get the current [MessageSearchBlocState] instance
|
/// Use this method to get the current [MessageSearchBlocState] instance
|
||||||
static MessageSearchBlocState of(BuildContext context) {
|
static MessageSearchBlocState of(BuildContext context) {
|
||||||
MessageSearchBlocState state;
|
MessageSearchBlocState? state;
|
||||||
|
|
||||||
state = context.findAncestorStateOfType<MessageSearchBlocState>();
|
state = context.findAncestorStateOfType<MessageSearchBlocState>();
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ class MessageSearchBloc extends StatefulWidget {
|
|||||||
class MessageSearchBlocState extends State<MessageSearchBloc>
|
class MessageSearchBlocState extends State<MessageSearchBloc>
|
||||||
with AutomaticKeepAliveClientMixin {
|
with AutomaticKeepAliveClientMixin {
|
||||||
/// The current messages list
|
/// The current messages list
|
||||||
List<GetMessageResponse> get messageResponses => _messageResponses.value;
|
List<GetMessageResponse>? get messageResponses => _messageResponses.value;
|
||||||
|
|
||||||
/// The current messages list as a stream
|
/// The current messages list as a stream
|
||||||
Stream<List<GetMessageResponse>> get messagesStream =>
|
Stream<List<GetMessageResponse>> get messagesStream =>
|
||||||
@@ -59,11 +58,11 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
|
|||||||
/// Calls [StreamChatClient.search] updating
|
/// Calls [StreamChatClient.search] updating
|
||||||
/// [messagesStream] and [queryMessagesLoading] stream
|
/// [messagesStream] and [queryMessagesLoading] stream
|
||||||
Future<void> search({
|
Future<void> search({
|
||||||
Map<String, dynamic> filter,
|
required Map<String, dynamic> filter,
|
||||||
Map<String, dynamic> messageFilter,
|
Map<String, dynamic>? messageFilter,
|
||||||
List<SortOption> sort,
|
List<SortOption>? sort,
|
||||||
String query,
|
String? query,
|
||||||
PaginationParams pagination,
|
PaginationParams? pagination,
|
||||||
}) async {
|
}) async {
|
||||||
final client = StreamChatCore.of(context).client;
|
final client = StreamChatCore.of(context).client;
|
||||||
|
|
||||||
@@ -73,9 +72,7 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
|
|||||||
_queryMessagesLoadingController.add(true);
|
_queryMessagesLoadingController.add(true);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final clear = pagination == null ||
|
final clear = pagination == null || pagination.offset == 0;
|
||||||
pagination.offset == null ||
|
|
||||||
pagination.offset == 0;
|
|
||||||
|
|
||||||
final oldMessages = List<GetMessageResponse>.from(messageResponses ?? []);
|
final oldMessages = List<GetMessageResponse>.from(messageResponses ?? []);
|
||||||
|
|
||||||
@@ -93,7 +90,8 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
|
|||||||
final temp = oldMessages + messages.results;
|
final temp = oldMessages + messages.results;
|
||||||
_messageResponses.add(temp);
|
_messageResponses.add(temp);
|
||||||
}
|
}
|
||||||
if (_messageResponses.hasValue && _queryMessagesLoadingController.value) {
|
if (_messageResponses.hasValue &&
|
||||||
|
_queryMessagesLoadingController.value!) {
|
||||||
_queryMessagesLoadingController.add(false);
|
_queryMessagesLoadingController.add(false);
|
||||||
}
|
}
|
||||||
} catch (e, stk) {
|
} catch (e, stk) {
|
||||||
|
|||||||
@@ -42,31 +42,27 @@ class MessageSearchListCore extends StatefulWidget {
|
|||||||
/// * [loadingBuilder]
|
/// * [loadingBuilder]
|
||||||
/// * [childBuilder]
|
/// * [childBuilder]
|
||||||
const MessageSearchListCore({
|
const MessageSearchListCore({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.emptyBuilder,
|
required this.emptyBuilder,
|
||||||
@required this.errorBuilder,
|
required this.errorBuilder,
|
||||||
@required this.loadingBuilder,
|
required this.loadingBuilder,
|
||||||
@required this.childBuilder,
|
required this.childBuilder,
|
||||||
|
required this.filters,
|
||||||
this.messageQuery,
|
this.messageQuery,
|
||||||
this.filters,
|
|
||||||
this.sortOptions,
|
this.sortOptions,
|
||||||
this.paginationParams,
|
this.paginationParams,
|
||||||
this.messageFilters,
|
this.messageFilters,
|
||||||
this.messageSearchListController,
|
this.messageSearchListController,
|
||||||
}) : assert(emptyBuilder != null, 'emptyBuilder should not be null'),
|
}) : super(key: key);
|
||||||
assert(errorBuilder != null, 'errorBuilder should not be null'),
|
|
||||||
assert(loadingBuilder != null, 'loadingBuilder should not be null'),
|
|
||||||
assert(childBuilder != null, 'childBuilder should not be null'),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// A [MessageSearchListController] allows reloading and pagination.
|
/// A [MessageSearchListController] allows reloading and pagination.
|
||||||
/// Use [MessageSearchListController.loadData] and
|
/// Use [MessageSearchListController.loadData] and
|
||||||
/// [MessageSearchListController.paginateData] respectively for reloading and
|
/// [MessageSearchListController.paginateData] respectively for reloading and
|
||||||
/// pagination.
|
/// pagination.
|
||||||
final MessageSearchListController messageSearchListController;
|
final MessageSearchListController? messageSearchListController;
|
||||||
|
|
||||||
/// Message String to search on
|
/// Message String to search on
|
||||||
final String messageQuery;
|
final String? messageQuery;
|
||||||
|
|
||||||
/// The query filters to use.
|
/// The query filters to use.
|
||||||
/// You can query on any of the custom fields you've defined on the [Channel].
|
/// You can query on any of the custom fields you've defined on the [Channel].
|
||||||
@@ -78,18 +74,18 @@ class MessageSearchListCore extends StatefulWidget {
|
|||||||
/// provided.
|
/// provided.
|
||||||
/// You can sort based on last_updated, last_message_at, updated_at, created_
|
/// You can sort based on last_updated, last_message_at, updated_at, created_
|
||||||
/// at or member_count. Direction can be ascending or descending.
|
/// at or member_count. Direction can be ascending or descending.
|
||||||
final List<SortOption> sortOptions;
|
final List<SortOption>? sortOptions;
|
||||||
|
|
||||||
/// Pagination parameters
|
/// Pagination parameters
|
||||||
/// limit: the number of users to return (max is 30)
|
/// limit: the number of users to return (max is 30)
|
||||||
/// offset: the offset (max is 1000)
|
/// offset: the offset (max is 1000)
|
||||||
/// message_limit: how many messages should be included to each channel
|
/// message_limit: how many messages should be included to each channel
|
||||||
final PaginationParams paginationParams;
|
final PaginationParams? paginationParams;
|
||||||
|
|
||||||
/// The message query filters to use.
|
/// The message query filters to use.
|
||||||
/// You can query on any of the custom fields you've defined on the [Channel].
|
/// You can query on any of the custom fields you've defined on the [Channel].
|
||||||
/// You can also filter other built-in channel fields.
|
/// You can also filter other built-in channel fields.
|
||||||
final Map<String, dynamic> messageFilters;
|
final Map<String, dynamic>? messageFilters;
|
||||||
|
|
||||||
/// The builder that is used when the search messages are fetched
|
/// The builder that is used when the search messages are fetched
|
||||||
final Widget Function(List<GetMessageResponse>) childBuilder;
|
final Widget Function(List<GetMessageResponse>) childBuilder;
|
||||||
@@ -114,8 +110,8 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
|
|||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
loadData();
|
loadData();
|
||||||
if (widget.messageSearchListController != null) {
|
if (widget.messageSearchListController != null) {
|
||||||
widget.messageSearchListController.loadData = loadData;
|
widget.messageSearchListController!.loadData = loadData;
|
||||||
widget.messageSearchListController.paginateData = paginateData;
|
widget.messageSearchListController!.paginateData = paginateData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,16 +126,16 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
|
|||||||
stream: messageSearchBloc.messagesStream,
|
stream: messageSearchBloc.messagesStream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return widget.errorBuilder(context, snapshot.error);
|
return widget.errorBuilder(context, snapshot.error!);
|
||||||
}
|
}
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return widget.loadingBuilder(context);
|
return widget.loadingBuilder(context);
|
||||||
}
|
}
|
||||||
final items = snapshot.data;
|
final items = snapshot.data!;
|
||||||
if (items.isEmpty) {
|
if (items.isEmpty) {
|
||||||
return widget.emptyBuilder(context);
|
return widget.emptyBuilder(context);
|
||||||
}
|
}
|
||||||
return widget.childBuilder(snapshot.data);
|
return widget.childBuilder(items);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -161,7 +157,7 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
|
|||||||
return messageSearchBloc.search(
|
return messageSearchBloc.search(
|
||||||
filter: widget.filters,
|
filter: widget.filters,
|
||||||
sort: widget.sortOptions,
|
sort: widget.sortOptions,
|
||||||
pagination: widget.paginationParams.copyWith(
|
pagination: widget.paginationParams!.copyWith(
|
||||||
offset: messageSearchBloc.messageResponses?.length ?? 0,
|
offset: messageSearchBloc.messageResponses?.length ?? 0,
|
||||||
),
|
),
|
||||||
query: widget.messageQuery,
|
query: widget.messageQuery,
|
||||||
@@ -172,13 +168,13 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(MessageSearchListCore oldWidget) {
|
void didUpdateWidget(MessageSearchListCore oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.filters?.toString() != oldWidget.filters?.toString() ||
|
if (widget.filters.toString() != oldWidget.filters.toString() ||
|
||||||
jsonEncode(widget.sortOptions) != jsonEncode(oldWidget.sortOptions) ||
|
jsonEncode(widget.sortOptions) != jsonEncode(oldWidget.sortOptions) ||
|
||||||
widget.messageQuery?.toString() != oldWidget.messageQuery?.toString() ||
|
widget.messageQuery?.toString() != oldWidget.messageQuery?.toString() ||
|
||||||
widget.messageFilters?.toString() !=
|
widget.messageFilters?.toString() !=
|
||||||
oldWidget.messageFilters?.toString() ||
|
oldWidget.messageFilters?.toString() ||
|
||||||
widget.paginationParams?.toJson()?.toString() !=
|
widget.paginationParams?.toJson().toString() !=
|
||||||
oldWidget.paginationParams?.toJson()?.toString()) {
|
oldWidget.paginationParams?.toJson().toString()) {
|
||||||
loadData();
|
loadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,8 +183,8 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
|
|||||||
/// Controller used for paginating data in [ChannelListView]
|
/// Controller used for paginating data in [ChannelListView]
|
||||||
class MessageSearchListController {
|
class MessageSearchListController {
|
||||||
/// Call this function to reload data
|
/// Call this function to reload data
|
||||||
AsyncCallback loadData;
|
AsyncCallback? loadData;
|
||||||
|
|
||||||
/// Call this function to load further data
|
/// Call this function to load further data
|
||||||
AsyncCallback paginateData;
|
AsyncCallback? paginateData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
@@ -21,16 +22,14 @@ class StreamChannel extends StatefulWidget {
|
|||||||
/// Creates a new instance of [StreamChannel]. Both [child] and [client] must
|
/// Creates a new instance of [StreamChannel]. Both [child] and [client] must
|
||||||
/// be supplied and not null.
|
/// be supplied and not null.
|
||||||
const StreamChannel({
|
const StreamChannel({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.child,
|
required this.child,
|
||||||
@required this.channel,
|
required this.channel,
|
||||||
this.showLoading = true,
|
this.showLoading = true,
|
||||||
this.initialMessageId,
|
this.initialMessageId,
|
||||||
}) : assert(child != null, 'Child should not be null'),
|
}) : super(key: key);
|
||||||
assert(channel != null, 'Channel should not be null'),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
// ignore: public_member_api_docs
|
/// The child of the widget
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
/// [channel] specifies the channel with which child should be wrapped
|
/// [channel] specifies the channel with which child should be wrapped
|
||||||
@@ -40,11 +39,11 @@ class StreamChannel extends StatefulWidget {
|
|||||||
final bool showLoading;
|
final bool showLoading;
|
||||||
|
|
||||||
/// If passed the channel will load from this particular message.
|
/// If passed the channel will load from this particular message.
|
||||||
final String initialMessageId;
|
final String? initialMessageId;
|
||||||
|
|
||||||
/// Use this method to get the current [StreamChannelState] instance
|
/// Use this method to get the current [StreamChannelState] instance
|
||||||
static StreamChannelState of(BuildContext context) {
|
static StreamChannelState of(BuildContext context) {
|
||||||
StreamChannelState streamChannelState;
|
StreamChannelState? streamChannelState;
|
||||||
|
|
||||||
streamChannelState = context.findAncestorStateOfType<StreamChannelState>();
|
streamChannelState = context.findAncestorStateOfType<StreamChannelState>();
|
||||||
|
|
||||||
@@ -67,11 +66,11 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
Channel get channel => widget.channel;
|
Channel get channel => widget.channel;
|
||||||
|
|
||||||
/// InitialMessageId
|
/// InitialMessageId
|
||||||
String get initialMessageId => widget.initialMessageId;
|
String? get initialMessageId => widget.initialMessageId;
|
||||||
|
|
||||||
/// Current channel state stream
|
/// Current channel state stream
|
||||||
Stream<ChannelState> get channelStateStream =>
|
Stream<ChannelState>? get channelStateStream =>
|
||||||
widget.channel.state.channelStateStream;
|
widget.channel.state?.channelStateStream;
|
||||||
|
|
||||||
final _queryTopMessagesController = BehaviorSubject.seeded(false);
|
final _queryTopMessagesController = BehaviorSubject.seeded(false);
|
||||||
final _queryBottomMessagesController = BehaviorSubject.seeded(false);
|
final _queryBottomMessagesController = BehaviorSubject.seeded(false);
|
||||||
@@ -89,16 +88,18 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
int limit = 20,
|
int limit = 20,
|
||||||
bool preferOffline = false,
|
bool preferOffline = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (_topPaginationEnded || _queryTopMessagesController?.value == true) {
|
if (_topPaginationEnded ||
|
||||||
|
_queryTopMessagesController.value == true ||
|
||||||
|
channel.state == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_queryTopMessagesController.add(true);
|
_queryTopMessagesController.add(true);
|
||||||
|
|
||||||
if (channel.state.messages.isEmpty) {
|
if (channel.state!.messages.isEmpty) {
|
||||||
return _queryTopMessagesController.add(false);
|
return _queryTopMessagesController.add(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
final oldestMessage = channel.state.messages.first;
|
final oldestMessage = channel.state!.messages.first;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final state = await queryBeforeMessage(
|
final state = await queryBeforeMessage(
|
||||||
@@ -120,15 +121,16 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
bool preferOffline = false,
|
bool preferOffline = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (_bottomPaginationEnded ||
|
if (_bottomPaginationEnded ||
|
||||||
_queryBottomMessagesController?.value == true ||
|
_queryBottomMessagesController.value == true ||
|
||||||
channel?.state?.isUpToDate == true) return;
|
channel.state == null ||
|
||||||
|
channel.state!.isUpToDate == true) return;
|
||||||
_queryBottomMessagesController.add(true);
|
_queryBottomMessagesController.add(true);
|
||||||
|
|
||||||
if (channel.state.messages.isEmpty) {
|
if (channel.state!.messages.isEmpty) {
|
||||||
return _queryBottomMessagesController.add(false);
|
return _queryBottomMessagesController.add(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
final recentMessage = channel.state.messages.last;
|
final recentMessage = channel.state!.messages.last;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final state = await queryAfterMessage(
|
final state = await queryAfterMessage(
|
||||||
@@ -146,7 +148,7 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Calls [channel.query] updating [queryMessage] stream
|
/// Calls [channel.query] updating [queryMessage] stream
|
||||||
Future<void> queryMessages({QueryDirection direction = QueryDirection.top}) {
|
Future<void> queryMessages({QueryDirection? direction = QueryDirection.top}) {
|
||||||
if (direction == QueryDirection.top) return _queryTopMessages();
|
if (direction == QueryDirection.top) return _queryTopMessages();
|
||||||
return _queryBottomMessages();
|
return _queryBottomMessages();
|
||||||
}
|
}
|
||||||
@@ -157,12 +159,14 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
int limit = 50,
|
int limit = 50,
|
||||||
bool preferOffline = false,
|
bool preferOffline = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (_topPaginationEnded || _queryTopMessagesController.value) return;
|
if (_topPaginationEnded ||
|
||||||
|
_queryTopMessagesController.value! ||
|
||||||
|
channel.state == null) return;
|
||||||
_queryTopMessagesController.add(true);
|
_queryTopMessagesController.add(true);
|
||||||
|
|
||||||
Message message;
|
late Message message;
|
||||||
if (channel.state.threads.containsKey(parentId)) {
|
if (channel.state!.threads.containsKey(parentId)) {
|
||||||
final thread = channel.state.threads[parentId];
|
final thread = channel.state!.threads[parentId]!;
|
||||||
if (thread.isNotEmpty) {
|
if (thread.isNotEmpty) {
|
||||||
message = thread.first;
|
message = thread.first;
|
||||||
}
|
}
|
||||||
@@ -172,7 +176,7 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
final response = await channel.getReplies(
|
final response = await channel.getReplies(
|
||||||
parentId,
|
parentId,
|
||||||
PaginationParams(
|
PaginationParams(
|
||||||
lessThan: message?.id,
|
lessThan: message.id,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
),
|
),
|
||||||
preferOffline: preferOffline,
|
preferOffline: preferOffline,
|
||||||
@@ -188,21 +192,26 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
|
|
||||||
/// Query the channel members and watchers
|
/// Query the channel members and watchers
|
||||||
Future<void> queryMembersAndWatchers() async {
|
Future<void> queryMembersAndWatchers() async {
|
||||||
await widget.channel.query(
|
final _members = channel.state?.members;
|
||||||
membersPagination: PaginationParams(
|
if (_members != null) {
|
||||||
offset: channel.state.members?.length,
|
await widget.channel.query(
|
||||||
limit: 100,
|
membersPagination: PaginationParams(
|
||||||
),
|
offset: _members.length,
|
||||||
watchersPagination: PaginationParams(
|
limit: 100,
|
||||||
offset: channel.state.watchers?.length,
|
),
|
||||||
limit: 100,
|
watchersPagination: PaginationParams(
|
||||||
),
|
offset: _members.length,
|
||||||
);
|
limit: 100,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads channel at specific message
|
/// Loads channel at specific message
|
||||||
Future<void> loadChannelAtMessage(
|
Future<void> loadChannelAtMessage(
|
||||||
String messageId, {
|
String? messageId, {
|
||||||
int before = 20,
|
int before = 20,
|
||||||
int after = 20,
|
int after = 20,
|
||||||
bool preferOffline = false,
|
bool preferOffline = false,
|
||||||
@@ -214,15 +223,15 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
preferOffline: preferOffline,
|
preferOffline: preferOffline,
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<void> _queryAtMessage({
|
Future<List<ChannelState>> _queryAtMessage({
|
||||||
String messageId,
|
String? messageId,
|
||||||
int before = 20,
|
int before = 20,
|
||||||
int after = 20,
|
int after = 20,
|
||||||
bool preferOffline = false,
|
bool preferOffline = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (channel.state == null) return;
|
if (channel.state == null) return [];
|
||||||
channel.state.isUpToDate = false;
|
channel.state!.isUpToDate = false;
|
||||||
channel.state.truncate();
|
channel.state!.truncate();
|
||||||
|
|
||||||
if (messageId == null) {
|
if (messageId == null) {
|
||||||
await channel.query(
|
await channel.query(
|
||||||
@@ -231,8 +240,8 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
),
|
),
|
||||||
preferOffline: preferOffline,
|
preferOffline: preferOffline,
|
||||||
);
|
);
|
||||||
channel.state.isUpToDate = true;
|
channel.state!.isUpToDate = true;
|
||||||
return;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return Future.wait([
|
return Future.wait([
|
||||||
@@ -277,16 +286,15 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
preferOffline: preferOffline,
|
preferOffline: preferOffline,
|
||||||
);
|
);
|
||||||
if (state.messages.isEmpty || state.messages.length < limit) {
|
if (state.messages.isEmpty || state.messages.length < limit) {
|
||||||
channel.state.isUpToDate = true;
|
channel.state?.isUpToDate = true;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
Future<Message> getMessage(String messageId) async {
|
Future<Message> getMessage(String messageId) async {
|
||||||
var message = channel.state.messages.firstWhere(
|
var message = channel.state?.messages.firstWhereOrNull(
|
||||||
(it) => it.id == messageId,
|
(it) => it.id == messageId,
|
||||||
orElse: () => null,
|
|
||||||
);
|
);
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
final response = await channel.getMessagesById([messageId]);
|
final response = await channel.getMessagesById([messageId]);
|
||||||
@@ -298,7 +306,7 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
/// Reloads the channel with latest message
|
/// Reloads the channel with latest message
|
||||||
Future<void> reloadChannel() => _queryAtMessage(before: 30);
|
Future<void> reloadChannel() => _queryAtMessage(before: 30);
|
||||||
|
|
||||||
List<Future<bool>> _futures;
|
late List<Future<bool>> _futures;
|
||||||
|
|
||||||
Future<bool> get _loadChannelAtMessage async {
|
Future<bool> get _loadChannelAtMessage async {
|
||||||
try {
|
try {
|
||||||
@@ -358,9 +366,9 @@ class StreamChannelState extends State<StreamChannel> {
|
|||||||
}
|
}
|
||||||
return Center(child: Text(message));
|
return Center(child: Text(message));
|
||||||
}
|
}
|
||||||
final initialized = snapshot.data[0];
|
final initialized = snapshot.data![0];
|
||||||
// ignore: avoid_bool_literals_in_conditional_expressions
|
// ignore: avoid_bool_literals_in_conditional_expressions
|
||||||
final dataLoaded = initialMessageId == null ? true : snapshot.data[1];
|
final dataLoaded = initialMessageId == null ? true : snapshot.data![1];
|
||||||
if (widget.showLoading && (!initialized || !dataLoaded)) {
|
if (widget.showLoading && (!initialized || !dataLoaded)) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
|
|||||||
@@ -38,14 +38,12 @@ class StreamChatCore extends StatefulWidget {
|
|||||||
/// [StreamChatCore] is a stateful widget which reacts to system events and
|
/// [StreamChatCore] is a stateful widget which reacts to system events and
|
||||||
/// updates Stream's connection status accordingly.
|
/// updates Stream's connection status accordingly.
|
||||||
const StreamChatCore({
|
const StreamChatCore({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.client,
|
required this.client,
|
||||||
@required this.child,
|
required this.child,
|
||||||
this.onBackgroundEventReceived,
|
this.onBackgroundEventReceived,
|
||||||
this.backgroundKeepAlive = const Duration(minutes: 1),
|
this.backgroundKeepAlive = const Duration(minutes: 1),
|
||||||
}) : assert(client != null, 'Stream Chat Client should not be null'),
|
}) : super(key: key);
|
||||||
assert(child != null, 'Child should not be null'),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// Instance of Stream Chat Client containing information about the current
|
/// Instance of Stream Chat Client containing information about the current
|
||||||
/// application.
|
/// application.
|
||||||
@@ -61,14 +59,14 @@ class StreamChatCore extends StatefulWidget {
|
|||||||
/// Handler called whenever the [client] receives a new [Event] while the app
|
/// Handler called whenever the [client] receives a new [Event] while the app
|
||||||
/// is in background. Can be used to display various notifications depending
|
/// is in background. Can be used to display various notifications depending
|
||||||
/// upon the [Event.type]
|
/// upon the [Event.type]
|
||||||
final EventHandler onBackgroundEventReceived;
|
final EventHandler? onBackgroundEventReceived;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
StreamChatCoreState createState() => StreamChatCoreState();
|
StreamChatCoreState createState() => StreamChatCoreState();
|
||||||
|
|
||||||
/// Use this method to get the current [StreamChatCoreState] instance
|
/// Use this method to get the current [StreamChatCoreState] instance
|
||||||
static StreamChatCoreState of(BuildContext context) {
|
static StreamChatCoreState of(BuildContext context) {
|
||||||
StreamChatCoreState streamChatState;
|
StreamChatCoreState? streamChatState;
|
||||||
|
|
||||||
streamChatState = context.findAncestorStateOfType<StreamChatCoreState>();
|
streamChatState = context.findAncestorStateOfType<StreamChatCoreState>();
|
||||||
|
|
||||||
@@ -87,24 +85,24 @@ class StreamChatCoreState extends State<StreamChatCore>
|
|||||||
/// Initialized client used throughout the application.
|
/// Initialized client used throughout the application.
|
||||||
StreamChatClient get client => widget.client;
|
StreamChatClient get client => widget.client;
|
||||||
|
|
||||||
Timer _disconnectTimer;
|
Timer? _disconnectTimer;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => widget.child;
|
Widget build(BuildContext context) => widget.child;
|
||||||
|
|
||||||
/// The current user
|
/// The current user
|
||||||
User get user => client.state?.user;
|
User? get user => client.state.user;
|
||||||
|
|
||||||
/// The current user as a stream
|
/// The current user as a stream
|
||||||
Stream<User> get userStream => client.state?.userStream;
|
Stream<User?> get userStream => client.state.userStream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance?.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamSubscription _eventSubscription;
|
StreamSubscription? _eventSubscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
@@ -119,15 +117,15 @@ class StreamChatCoreState extends State<StreamChatCore>
|
|||||||
);
|
);
|
||||||
|
|
||||||
void onTimerComplete() {
|
void onTimerComplete() {
|
||||||
_eventSubscription.cancel();
|
_eventSubscription?.cancel();
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
_disconnectTimer = Timer(widget.backgroundKeepAlive, onTimerComplete);
|
_disconnectTimer = Timer(widget.backgroundKeepAlive, onTimerComplete);
|
||||||
} else if (state == AppLifecycleState.resumed) {
|
} else if (state == AppLifecycleState.resumed) {
|
||||||
if (_disconnectTimer?.isActive == true) {
|
if (_disconnectTimer?.isActive == true) {
|
||||||
_eventSubscription.cancel();
|
_eventSubscription?.cancel();
|
||||||
_disconnectTimer.cancel();
|
_disconnectTimer?.cancel();
|
||||||
} else {
|
} else {
|
||||||
if (client.wsConnectionStatus == ConnectionStatus.disconnected) {
|
if (client.wsConnectionStatus == ConnectionStatus.disconnected) {
|
||||||
client.connect();
|
client.connect();
|
||||||
@@ -139,7 +137,7 @@ class StreamChatCoreState extends State<StreamChatCore>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance?.removeObserver(this);
|
||||||
_eventSubscription?.cancel();
|
_eventSubscription?.cancel();
|
||||||
_disconnectTimer?.cancel();
|
_disconnectTimer?.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|||||||
@@ -57,27 +57,23 @@ import 'package:stream_chat_flutter_core/src/users_bloc.dart';
|
|||||||
class UserListCore extends StatefulWidget {
|
class UserListCore extends StatefulWidget {
|
||||||
/// Instantiate a new [UserListCore]
|
/// Instantiate a new [UserListCore]
|
||||||
const UserListCore({
|
const UserListCore({
|
||||||
@required this.errorBuilder,
|
required this.errorBuilder,
|
||||||
@required this.emptyBuilder,
|
required this.emptyBuilder,
|
||||||
@required this.loadingBuilder,
|
required this.loadingBuilder,
|
||||||
@required this.listBuilder,
|
required this.listBuilder,
|
||||||
Key key,
|
Key? key,
|
||||||
this.filter,
|
this.filter,
|
||||||
this.options,
|
this.options,
|
||||||
this.sort,
|
this.sort,
|
||||||
this.pagination,
|
this.pagination,
|
||||||
this.groupAlphabetically = false,
|
this.groupAlphabetically = false,
|
||||||
this.userListController,
|
this.userListController,
|
||||||
}) : assert(errorBuilder != null, ''),
|
}) : super(key: key);
|
||||||
assert(emptyBuilder != null, ''),
|
|
||||||
assert(loadingBuilder != null, ''),
|
|
||||||
assert(listBuilder != null, ''),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// A [UserListController] allows reloading and pagination.
|
/// A [UserListController] allows reloading and pagination.
|
||||||
/// Use [UserListController.loadData] and [UserListController.paginateData]
|
/// Use [UserListController.loadData] and [UserListController.paginateData]
|
||||||
/// respectively for reloading and pagination.
|
/// respectively for reloading and pagination.
|
||||||
final UserListController userListController;
|
final UserListController? userListController;
|
||||||
|
|
||||||
/// The builder that will be used in case of error
|
/// The builder that will be used in case of error
|
||||||
final Widget Function(Object error) errorBuilder;
|
final Widget Function(Object error) errorBuilder;
|
||||||
@@ -94,25 +90,25 @@ class UserListCore extends StatefulWidget {
|
|||||||
/// The query filters to use.
|
/// The query filters to use.
|
||||||
/// You can query on any of the custom fields you've defined on the [Channel].
|
/// You can query on any of the custom fields you've defined on the [Channel].
|
||||||
/// You can also filter other built-in channel fields.
|
/// You can also filter other built-in channel fields.
|
||||||
final Map<String, dynamic> filter;
|
final Map<String, dynamic>? filter;
|
||||||
|
|
||||||
/// Query channels options.
|
/// Query channels options.
|
||||||
///
|
///
|
||||||
/// state: if true returns the Channel state
|
/// state: if true returns the Channel state
|
||||||
/// watch: if true listen to changes to this Channel in real time.
|
/// watch: if true listen to changes to this Channel in real time.
|
||||||
final Map<String, dynamic> options;
|
final Map<String, dynamic>? options;
|
||||||
|
|
||||||
/// The sorting used for the channels matching the filters.
|
/// The sorting used for the channels matching the filters.
|
||||||
/// Sorting is based on field and direction, multiple sorting options can be
|
/// Sorting is based on field and direction, multiple sorting options can be
|
||||||
/// provided. You can sort based on last_updated, last_message_at, updated_at,
|
/// provided. You can sort based on last_updated, last_message_at, updated_at,
|
||||||
/// created_at or member_count. Direction can be ascending or descending.
|
/// created_at or member_count. Direction can be ascending or descending.
|
||||||
final List<SortOption> sort;
|
final List<SortOption>? sort;
|
||||||
|
|
||||||
/// Pagination parameters
|
/// Pagination parameters
|
||||||
/// limit: the number of users to return (max is 30)
|
/// limit: the number of users to return (max is 30)
|
||||||
/// offset: the offset (max is 1000)
|
/// offset: the offset (max is 1000)
|
||||||
/// message_limit: how many messages should be included to each channel
|
/// message_limit: how many messages should be included to each channel
|
||||||
final PaginationParams pagination;
|
final PaginationParams? pagination;
|
||||||
|
|
||||||
/// Set it to true to group users by their first character
|
/// Set it to true to group users by their first character
|
||||||
///
|
///
|
||||||
@@ -131,8 +127,8 @@ class UserListCoreState extends State<UserListCore>
|
|||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
loadData();
|
loadData();
|
||||||
if (widget.userListController != null) {
|
if (widget.userListController != null) {
|
||||||
widget.userListController.loadData = loadData;
|
widget.userListController!.loadData = loadData;
|
||||||
widget.userListController.paginateData = paginateData;
|
widget.userListController!.paginateData = paginateData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,14 +154,14 @@ class UserListCoreState extends State<UserListCore>
|
|||||||
}
|
}
|
||||||
final groupedUsers = <String, List<User>>{};
|
final groupedUsers = <String, List<User>>{};
|
||||||
for (final e in temp) {
|
for (final e in temp) {
|
||||||
final alphabet = e.name[0]?.toUpperCase();
|
final alphabet = e.name[0].toUpperCase();
|
||||||
groupedUsers[alphabet] = [...groupedUsers[alphabet] ?? [], e];
|
groupedUsers[alphabet] = [...groupedUsers[alphabet] ?? [], e];
|
||||||
}
|
}
|
||||||
final items = <ListItem>[];
|
final items = <ListItem>[];
|
||||||
for (final key in groupedUsers.keys) {
|
for (final key in groupedUsers.keys) {
|
||||||
items
|
items
|
||||||
..add(ListHeaderItem(key))
|
..add(ListHeaderItem(key))
|
||||||
..addAll(groupedUsers[key].map((e) => ListUserItem(e)));
|
..addAll(groupedUsers[key]!.map((e) => ListUserItem(e)));
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
@@ -180,12 +176,12 @@ class UserListCoreState extends State<UserListCore>
|
|||||||
stream: _buildUserStream(usersBlocState),
|
stream: _buildUserStream(usersBlocState),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return widget.errorBuilder(snapshot.error);
|
return widget.errorBuilder(snapshot.error!);
|
||||||
}
|
}
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return widget.loadingBuilder(context);
|
return widget.loadingBuilder(context);
|
||||||
}
|
}
|
||||||
final items = snapshot.data;
|
final items = snapshot.data!;
|
||||||
if (items.isEmpty) {
|
if (items.isEmpty) {
|
||||||
return widget.emptyBuilder(context);
|
return widget.emptyBuilder(context);
|
||||||
}
|
}
|
||||||
@@ -210,7 +206,7 @@ class UserListCoreState extends State<UserListCore>
|
|||||||
return _usersBloc.queryUsers(
|
return _usersBloc.queryUsers(
|
||||||
filter: widget.filter,
|
filter: widget.filter,
|
||||||
sort: widget.sort,
|
sort: widget.sort,
|
||||||
pagination: widget.pagination.copyWith(
|
pagination: widget.pagination!.copyWith(
|
||||||
offset: _usersBloc.users?.length ?? 0,
|
offset: _usersBloc.users?.length ?? 0,
|
||||||
),
|
),
|
||||||
options: widget.options,
|
options: widget.options,
|
||||||
@@ -223,8 +219,8 @@ class UserListCoreState extends State<UserListCore>
|
|||||||
if (widget.filter?.toString() != oldWidget.filter?.toString() ||
|
if (widget.filter?.toString() != oldWidget.filter?.toString() ||
|
||||||
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
|
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
|
||||||
widget.options?.toString() != oldWidget.options?.toString() ||
|
widget.options?.toString() != oldWidget.options?.toString() ||
|
||||||
widget.pagination?.toJson()?.toString() !=
|
widget.pagination?.toJson().toString() !=
|
||||||
oldWidget.pagination?.toJson()?.toString()) {
|
oldWidget.pagination?.toJson().toString()) {
|
||||||
loadData();
|
loadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,7 +231,7 @@ class UserListCoreState extends State<UserListCore>
|
|||||||
/// with `USER`.
|
/// with `USER`.
|
||||||
abstract class ListItem {
|
abstract class ListItem {
|
||||||
/// Unique key per list item
|
/// Unique key per list item
|
||||||
String get key {
|
String? get key {
|
||||||
if (this is ListHeaderItem) {
|
if (this is ListHeaderItem) {
|
||||||
final header = (this as ListHeaderItem).heading;
|
final header = (this as ListHeaderItem).heading;
|
||||||
return 'HEADER-${header.toLowerCase()}';
|
return 'HEADER-${header.toLowerCase()}';
|
||||||
@@ -250,8 +246,8 @@ abstract class ListItem {
|
|||||||
/// Helper function to build widget based on ListItem type
|
/// Helper function to build widget based on ListItem type
|
||||||
// ignore: missing_return
|
// ignore: missing_return
|
||||||
Widget when({
|
Widget when({
|
||||||
@required Widget Function(String heading) headerItem,
|
required Widget Function(String heading) headerItem,
|
||||||
@required Widget Function(User user) userItem,
|
required Widget Function(User user) userItem,
|
||||||
}) {
|
}) {
|
||||||
if (this is ListHeaderItem) {
|
if (this is ListHeaderItem) {
|
||||||
return headerItem((this as ListHeaderItem).heading);
|
return headerItem((this as ListHeaderItem).heading);
|
||||||
@@ -259,6 +255,7 @@ abstract class ListItem {
|
|||||||
if (this is ListUserItem) {
|
if (this is ListUserItem) {
|
||||||
return userItem((this as ListUserItem).user);
|
return userItem((this as ListUserItem).user);
|
||||||
}
|
}
|
||||||
|
return Container();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,8 +280,8 @@ class ListUserItem extends ListItem {
|
|||||||
/// Controller used for paginating data in [ChannelListView]
|
/// Controller used for paginating data in [ChannelListView]
|
||||||
class UserListController {
|
class UserListController {
|
||||||
/// Call this function to reload data
|
/// Call this function to reload data
|
||||||
AsyncCallback loadData;
|
AsyncCallback? loadData;
|
||||||
|
|
||||||
/// Call this function to load further data
|
/// Call this function to load further data
|
||||||
AsyncCallback paginateData;
|
AsyncCallback? paginateData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,9 @@ class UsersBloc extends StatefulWidget {
|
|||||||
/// Instantiate a new [UsersBloc]. The parameter [child] must be supplied and
|
/// Instantiate a new [UsersBloc]. The parameter [child] must be supplied and
|
||||||
/// not null.
|
/// not null.
|
||||||
const UsersBloc({
|
const UsersBloc({
|
||||||
@required this.child,
|
required this.child,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : assert(
|
}) : super(key: key);
|
||||||
child != null,
|
|
||||||
'When constructing a UsersBloc, the parameter '
|
|
||||||
'child should not be null.'),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// The widget child
|
/// The widget child
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@@ -30,7 +26,7 @@ class UsersBloc extends StatefulWidget {
|
|||||||
|
|
||||||
/// Use this method to get the current [UsersBlocState] instance
|
/// Use this method to get the current [UsersBlocState] instance
|
||||||
static UsersBlocState of(BuildContext context) {
|
static UsersBlocState of(BuildContext context) {
|
||||||
UsersBlocState state;
|
UsersBlocState? state;
|
||||||
|
|
||||||
state = context.findAncestorStateOfType<UsersBlocState>();
|
state = context.findAncestorStateOfType<UsersBlocState>();
|
||||||
|
|
||||||
@@ -46,7 +42,7 @@ class UsersBloc extends StatefulWidget {
|
|||||||
class UsersBlocState extends State<UsersBloc>
|
class UsersBlocState extends State<UsersBloc>
|
||||||
with AutomaticKeepAliveClientMixin {
|
with AutomaticKeepAliveClientMixin {
|
||||||
/// The current users list
|
/// The current users list
|
||||||
List<User> get users => _usersController.value;
|
List<User>? get users => _usersController.value;
|
||||||
|
|
||||||
/// The current users list as a stream
|
/// The current users list as a stream
|
||||||
Stream<List<User>> get usersStream => _usersController.stream;
|
Stream<List<User>> get usersStream => _usersController.stream;
|
||||||
@@ -62,10 +58,10 @@ class UsersBlocState extends State<UsersBloc>
|
|||||||
/// online/offline.
|
/// online/offline.
|
||||||
/// [API Reference](https://getstream.io/chat/docs/flutter-dart/query_users/?language=dart)
|
/// [API Reference](https://getstream.io/chat/docs/flutter-dart/query_users/?language=dart)
|
||||||
Future<void> queryUsers({
|
Future<void> queryUsers({
|
||||||
Map<String, dynamic> filter,
|
Map<String, dynamic>? filter,
|
||||||
List<SortOption> sort,
|
List<SortOption>? sort,
|
||||||
Map<String, dynamic> options,
|
Map<String, dynamic>? options,
|
||||||
PaginationParams pagination,
|
PaginationParams? pagination,
|
||||||
}) async {
|
}) async {
|
||||||
final client = StreamChatCore.of(context).client;
|
final client = StreamChatCore.of(context).client;
|
||||||
|
|
||||||
@@ -76,9 +72,7 @@ class UsersBlocState extends State<UsersBloc>
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final clear = pagination == null ||
|
final clear = pagination == null || pagination.offset == 0;
|
||||||
pagination.offset == null ||
|
|
||||||
pagination.offset == 0;
|
|
||||||
|
|
||||||
final oldUsers = List<User>.from(users ?? []);
|
final oldUsers = List<User>.from(users ?? []);
|
||||||
|
|
||||||
@@ -95,7 +89,7 @@ class UsersBlocState extends State<UsersBloc>
|
|||||||
final temp = oldUsers + usersResponse.users;
|
final temp = oldUsers + usersResponse.users;
|
||||||
_usersController.add(temp);
|
_usersController.add(temp);
|
||||||
}
|
}
|
||||||
if (_usersController.hasValue && _queryUsersLoadingController.value) {
|
if (_usersController.hasValue && _queryUsersLoadingController.value!) {
|
||||||
_queryUsersLoadingController.add(false);
|
_queryUsersLoadingController.add(false);
|
||||||
}
|
}
|
||||||
} catch (e, stk) {
|
} catch (e, stk) {
|
||||||
|
|||||||
@@ -8,23 +8,24 @@ issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
|
|||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
flutter: ">=1.17.0"
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
collection: ^1.15.0-nullsafety.4
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
meta: ^1.2.4
|
meta: ^1.3.0
|
||||||
rxdart: ^0.26.0
|
rxdart: ^0.26.0
|
||||||
stream_chat: ^1.5.0
|
stream_chat: ^1.5.2
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
stream_chat:
|
stream_chat:
|
||||||
path: ../stream_chat
|
path: ../stream_chat
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
fake_async: ^1.1.0
|
fake_async: ^1.2.0
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
mockito: ^4.1.3
|
mocktail: ^0.1.1
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat_flutter_core/src/channel_list_core.dart';
|
import 'package:stream_chat_flutter_core/src/channel_list_core.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
@@ -30,58 +30,6 @@ void main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case listBuilder is null',
|
|
||||||
() {
|
|
||||||
final channelListCore = () => ChannelListCore(
|
|
||||||
listBuilder: null,
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(channelListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case loadingBuilder is null',
|
|
||||||
() {
|
|
||||||
final channelListCore = () => ChannelListCore(
|
|
||||||
listBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: null,
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(channelListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case emptyBuilder is null',
|
|
||||||
() {
|
|
||||||
final channelListCore = () => ChannelListCore(
|
|
||||||
listBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: null,
|
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(channelListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case errorBuilder is null',
|
|
||||||
() {
|
|
||||||
final channelListCore = () => ChannelListCore(
|
|
||||||
listBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: null,
|
|
||||||
);
|
|
||||||
expect(channelListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should throw if ChannelListCore is used where ChannelsBloc is not present '
|
'should throw if ChannelListCore is used where ChannelsBloc is not present '
|
||||||
'in the widget tree',
|
'in the widget tree',
|
||||||
@@ -116,7 +64,8 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -151,7 +100,8 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -185,15 +135,16 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
const error = 'Error! Error! Error!';
|
const error = 'Error! Error! Error!';
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -208,12 +159,12 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(errorWidgetKey), findsOneWidget);
|
expect(find.byKey(errorWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -233,15 +184,16 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
const channels = <Channel>[];
|
const channels = <Channel>[];
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenAnswer((_) => Stream.value(channels));
|
)).thenAnswer((_) => Stream.value(channels));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -256,12 +208,12 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(emptyWidgetKey), findsOneWidget);
|
expect(find.byKey(emptyWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -281,15 +233,16 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenAnswer((_) => Stream.value(channels));
|
)).thenAnswer((_) => Stream.value(channels));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -304,12 +257,12 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(listWidgetKey), findsOneWidget);
|
expect(find.byKey(listWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -337,15 +290,16 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenAnswer((_) => Stream.value(channels));
|
)).thenAnswer((_) => Stream.value(channels));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -364,12 +318,12 @@ void main() {
|
|||||||
expect(find.byKey(listWidgetKey), findsOneWidget);
|
expect(find.byKey(listWidgetKey), findsOneWidget);
|
||||||
expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget);
|
expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final channelListCoreState = tester.state<ChannelListCoreState>(
|
final channelListCoreState = tester.state<ChannelListCoreState>(
|
||||||
find.byKey(channelListCoreKey),
|
find.byKey(channelListCoreKey),
|
||||||
@@ -378,12 +332,12 @@ void main() {
|
|||||||
final offset = channels.length;
|
final offset = channels.length;
|
||||||
final paginatedChannels = _generateChannels(mockClient, offset: offset);
|
final paginatedChannels = _generateChannels(mockClient, offset: offset);
|
||||||
final updatedPagination = pagination.copyWith(offset: offset);
|
final updatedPagination = pagination.copyWith(offset: offset);
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).thenAnswer((_) => Stream.value(paginatedChannels));
|
)).thenAnswer((_) => Stream.value(paginatedChannels));
|
||||||
|
|
||||||
await channelListCoreState.paginateData();
|
await channelListCoreState.paginateData();
|
||||||
|
|
||||||
@@ -398,12 +352,12 @@ void main() {
|
|||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -411,8 +365,8 @@ void main() {
|
|||||||
'should rebuild ChannelListCore with updated widget data '
|
'should rebuild ChannelListCore with updated widget data '
|
||||||
'on calling setState()',
|
'on calling setState()',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
StateSetter _stateSetter;
|
StateSetter? _stateSetter;
|
||||||
int limit = pagination.limit;
|
var limit = pagination.limit;
|
||||||
|
|
||||||
const channelListCoreKey = Key('channelListCore');
|
const channelListCoreKey = Key('channelListCore');
|
||||||
const listWidgetKey = Key('listWidget');
|
const listWidgetKey = Key('listWidget');
|
||||||
@@ -435,15 +389,16 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenAnswer((_) => Stream.value(channels));
|
)).thenAnswer((_) => Stream.value(channels));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -466,24 +421,24 @@ void main() {
|
|||||||
expect(find.byKey(listWidgetKey), findsOneWidget);
|
expect(find.byKey(listWidgetKey), findsOneWidget);
|
||||||
expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget);
|
expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
// Rebuilding ChannelListCore with new pagination limit
|
// Rebuilding ChannelListCore with new pagination limit
|
||||||
_stateSetter(() => limit = 6);
|
_stateSetter?.call(() => limit = 6);
|
||||||
|
|
||||||
final updatedChannels = _generateChannels(mockClient, count: limit);
|
final updatedChannels = _generateChannels(mockClient, count: limit);
|
||||||
final updatedPagination = pagination.copyWith(limit: limit);
|
final updatedPagination = pagination.copyWith(limit: limit);
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).thenAnswer((_) => Stream.value(updatedChannels));
|
)).thenAnswer((_) => Stream.value(updatedChannels));
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
@@ -493,12 +448,12 @@ void main() {
|
|||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
import 'matchers/channel_matcher.dart';
|
import 'matchers/channel_matcher.dart';
|
||||||
import 'mocks.dart';
|
import 'mocks.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
setUpAll(() {
|
||||||
|
registerFallbackValue<PaginationParams>(const PaginationParams());
|
||||||
|
});
|
||||||
|
|
||||||
List<Channel> _generateChannels(
|
List<Channel> _generateChannels(
|
||||||
StreamChatClient client, {
|
StreamChatClient client, {
|
||||||
int count = 3,
|
int count = 3,
|
||||||
@@ -28,18 +32,6 @@ void main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error if child is null',
|
|
||||||
() async {
|
|
||||||
const channelsBlocKey = Key('channelsBloc');
|
|
||||||
final channelsBloc = () => ChannelsBloc(
|
|
||||||
key: channelsBlocKey,
|
|
||||||
child: null,
|
|
||||||
);
|
|
||||||
expect(channelsBloc, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should throw if ChannelsBloc is used where StreamChat is not present in the widget tree',
|
'should throw if ChannelsBloc is used where StreamChat is not present in the widget tree',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
@@ -70,7 +62,8 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -101,7 +94,8 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -117,12 +111,12 @@ void main() {
|
|||||||
final offlineChannels = _generateChannels(mockClient);
|
final offlineChannels = _generateChannels(mockClient);
|
||||||
final onlineChannels = _generateChannels(mockClient, offset: 3);
|
final onlineChannels = _generateChannels(mockClient, offset: 3);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.fromIterable([offlineChannels, onlineChannels]),
|
(_) => Stream.fromIterable([offlineChannels, onlineChannels]),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -136,12 +130,12 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -163,7 +157,8 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -176,14 +171,14 @@ void main() {
|
|||||||
find.byKey(channelsBlocKey),
|
find.byKey(channelsBlocKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
final error = 'Error! Error! Error!';
|
const error = 'Error! Error! Error!';
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
channelsBlocState.queryChannels();
|
channelsBlocState.queryChannels();
|
||||||
|
|
||||||
@@ -192,12 +187,12 @@ void main() {
|
|||||||
emitsError(error),
|
emitsError(error),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -214,7 +209,8 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -229,38 +225,41 @@ void main() {
|
|||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer((_) => Stream.value(channels));
|
)).thenAnswer((_) => Stream.value(channels));
|
||||||
|
|
||||||
channelsBlocState.queryChannels();
|
const pagination = PaginationParams(limit: 3);
|
||||||
|
channelsBlocState.queryChannels(
|
||||||
|
paginationParams: pagination,
|
||||||
|
);
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
channelsBlocState.channelsStream,
|
channelsBlocState.channelsStream,
|
||||||
emits(isSameChannelListAs(channels)),
|
emits(isSameChannelListAs(channels)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final offset = channels.length;
|
final offset = channels.length;
|
||||||
final paginationParams = PaginationParams(offset: offset);
|
final paginationParams = pagination.copyWith(offset: offset);
|
||||||
|
|
||||||
final newChannels = _generateChannels(mockClient, offset: offset);
|
final newChannels = _generateChannels(mockClient, offset: offset);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: paginationParams,
|
paginationParams: paginationParams,
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.value(newChannels),
|
(_) => Stream.value(newChannels),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -277,12 +276,12 @@ void main() {
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: paginationParams,
|
paginationParams: paginationParams,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -299,7 +298,8 @@ void main() {
|
|||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty());
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -313,39 +313,41 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
|
final paginationParams = const PaginationParams(
|
||||||
|
limit: 3,
|
||||||
|
);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: paginationParams,
|
||||||
)).thenAnswer((_) => Stream.value(channels));
|
)).thenAnswer((_) => Stream.value(channels));
|
||||||
|
|
||||||
channelsBlocState.queryChannels();
|
channelsBlocState.queryChannels(
|
||||||
|
paginationParams: paginationParams,
|
||||||
|
);
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
channelsBlocState.channelsStream,
|
channelsBlocState.channelsStream,
|
||||||
emits(isSameChannelListAs(channels)),
|
emits(isSameChannelListAs(channels)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: paginationParams,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final offset = channels.length;
|
|
||||||
final paginationParams = PaginationParams(offset: offset);
|
|
||||||
|
|
||||||
final error = 'Error! Error! Error!';
|
final error = 'Error! Error! Error!';
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: paginationParams,
|
paginationParams: paginationParams,
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
channelsBlocState.queryChannels(paginationParams: paginationParams);
|
channelsBlocState.queryChannels(paginationParams: paginationParams);
|
||||||
|
|
||||||
@@ -354,17 +356,17 @@ void main() {
|
|||||||
emitsError(error),
|
emitsError(error),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: paginationParams,
|
paginationParams: paginationParams,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
group('event controller test', () {
|
group('event controller test', () {
|
||||||
StreamController<Event> eventController;
|
late StreamController<Event> eventController;
|
||||||
setUp(() {
|
setUp(() {
|
||||||
eventController = StreamController<Event>.broadcast();
|
eventController = StreamController<Event>.broadcast();
|
||||||
});
|
});
|
||||||
@@ -379,12 +381,12 @@ void main() {
|
|||||||
child: Offstage(),
|
child: Offstage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any))
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
.thenAnswer((_) => Stream.empty());
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
when(mockClient.on(
|
when(() => mockClient.on(
|
||||||
EventType.channelHidden,
|
EventType.channelHidden,
|
||||||
)).thenAnswer((_) => eventController.stream);
|
)).thenAnswer((_) => eventController.stream);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -399,23 +401,23 @@ void main() {
|
|||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.value(channels),
|
(_) => Stream.value(channels),
|
||||||
);
|
);
|
||||||
|
|
||||||
await channelsBlocState.queryChannels();
|
await channelsBlocState.queryChannels();
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final channelHiddenEvent = Event(
|
final channelHiddenEvent = Event(
|
||||||
type: EventType.channelHidden,
|
type: EventType.channelHidden,
|
||||||
@@ -435,7 +437,7 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.on(EventType.channelHidden)).called(1);
|
verify(() => mockClient.on(EventType.channelHidden)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -450,13 +452,13 @@ void main() {
|
|||||||
child: Offstage(),
|
child: Offstage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any))
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
.thenAnswer((_) => Stream.empty());
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
when(mockClient.on(
|
when(() => mockClient.on(
|
||||||
EventType.channelDeleted,
|
EventType.channelDeleted,
|
||||||
EventType.notificationRemovedFromChannel,
|
EventType.notificationRemovedFromChannel,
|
||||||
)).thenAnswer((_) => eventController.stream);
|
)).thenAnswer((_) => eventController.stream);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -471,31 +473,38 @@ void main() {
|
|||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.value(channels),
|
(_) => Stream.value(channels),
|
||||||
);
|
);
|
||||||
|
|
||||||
await channelsBlocState.queryChannels();
|
await channelsBlocState.queryChannels();
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final channelDeletedOrNotificationRemovedEvent = Event(
|
final channelDeletedOrNotificationRemovedEvent = Event(
|
||||||
channel: EventChannel(cid: channels.first.cid),
|
channel: EventChannel(
|
||||||
|
cid: channels.first.cid!,
|
||||||
|
updatedAt: DateTime.now(),
|
||||||
|
config: ChannelConfig(),
|
||||||
|
createdAt: DateTime.now(),
|
||||||
|
memberCount: 1,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
eventController.add(channelDeletedOrNotificationRemovedEvent);
|
eventController.add(channelDeletedOrNotificationRemovedEvent);
|
||||||
|
|
||||||
final channelCid = channelDeletedOrNotificationRemovedEvent.channel.cid;
|
final channelCid =
|
||||||
|
channelDeletedOrNotificationRemovedEvent.channel?.cid;
|
||||||
final newChannels = [...channels]
|
final newChannels = [...channels]
|
||||||
..removeWhere((it) => it.cid == channelCid);
|
..removeWhere((it) => it.cid == channelCid);
|
||||||
|
|
||||||
@@ -507,10 +516,10 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.on(
|
verify(() => mockClient.on(
|
||||||
EventType.channelDeleted,
|
EventType.channelDeleted,
|
||||||
EventType.notificationRemovedFromChannel,
|
EventType.notificationRemovedFromChannel,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -525,12 +534,12 @@ void main() {
|
|||||||
child: Offstage(),
|
child: Offstage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any))
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
.thenAnswer((_) => Stream.empty());
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
when(mockClient.on(
|
when(() => mockClient.on(
|
||||||
EventType.messageNew,
|
EventType.messageNew,
|
||||||
)).thenAnswer((_) => eventController.stream);
|
)).thenAnswer((_) => eventController.stream);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -545,23 +554,23 @@ void main() {
|
|||||||
|
|
||||||
final channels = _generateChannels(mockClient);
|
final channels = _generateChannels(mockClient);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.value(channels),
|
(_) => Stream.value(channels),
|
||||||
);
|
);
|
||||||
|
|
||||||
await channelsBlocState.queryChannels();
|
await channelsBlocState.queryChannels();
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final messageNewEvent = Event(
|
final messageNewEvent = Event(
|
||||||
type: EventType.messageNew,
|
type: EventType.messageNew,
|
||||||
@@ -585,7 +594,7 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.on(EventType.messageNew)).called(1);
|
verify(() => mockClient.on(EventType.messageNew)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -609,16 +618,16 @@ void main() {
|
|||||||
shouldAddChannel: (e) => channels.map((it) => it.cid).contains(e.cid),
|
shouldAddChannel: (e) => channels.map((it) => it.cid).contains(e.cid),
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any))
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
.thenAnswer((_) => Stream.empty());
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
when(mockClient.on(
|
when(() => mockClient.on(
|
||||||
EventType.channelHidden,
|
EventType.channelHidden,
|
||||||
)).thenAnswer((_) => hiddenChannelEventController.stream);
|
)).thenAnswer((_) => hiddenChannelEventController.stream);
|
||||||
|
|
||||||
when(mockClient.on(
|
when(() => mockClient.on(
|
||||||
EventType.messageNew,
|
EventType.messageNew,
|
||||||
)).thenAnswer((_) => eventController.stream);
|
)).thenAnswer((_) => eventController.stream);
|
||||||
|
|
||||||
final messageNewEvent = Event(
|
final messageNewEvent = Event(
|
||||||
type: EventType.messageNew,
|
type: EventType.messageNew,
|
||||||
@@ -636,23 +645,23 @@ void main() {
|
|||||||
find.byKey(channelsBlocKey),
|
find.byKey(channelsBlocKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.value(channels),
|
(_) => Stream.value(channels),
|
||||||
);
|
);
|
||||||
|
|
||||||
await channelsBlocState.queryChannels();
|
await channelsBlocState.queryChannels();
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final channelHiddenEvent = Event(
|
final channelHiddenEvent = Event(
|
||||||
type: EventType.channelHidden,
|
type: EventType.channelHidden,
|
||||||
@@ -681,8 +690,8 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.on(EventType.channelHidden)).called(1);
|
verify(() => mockClient.on(EventType.channelHidden)).called(1);
|
||||||
verify(mockClient.on(EventType.messageNew)).called(1);
|
verify(() => mockClient.on(EventType.messageNew)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -703,14 +712,14 @@ void main() {
|
|||||||
shouldAddChannel: (_) => true,
|
shouldAddChannel: (_) => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.state.channels).thenReturn(stateChannels);
|
when(() => mockClient.state.channels).thenReturn(stateChannels);
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any))
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
.thenAnswer((_) => Stream.empty());
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
when(mockClient.on(
|
when(() => mockClient.on(
|
||||||
EventType.messageNew,
|
EventType.messageNew,
|
||||||
)).thenAnswer((_) => eventController.stream);
|
)).thenAnswer((_) => eventController.stream);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -723,23 +732,23 @@ void main() {
|
|||||||
find.byKey(channelsBlocKey),
|
find.byKey(channelsBlocKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.value(channels),
|
(_) => Stream.value(channels),
|
||||||
);
|
);
|
||||||
|
|
||||||
await channelsBlocState.queryChannels();
|
await channelsBlocState.queryChannels();
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final messageNewEvent = Event(
|
final messageNewEvent = Event(
|
||||||
type: EventType.messageNew,
|
type: EventType.messageNew,
|
||||||
@@ -749,7 +758,7 @@ void main() {
|
|||||||
eventController.add(messageNewEvent);
|
eventController.add(messageNewEvent);
|
||||||
|
|
||||||
final newChannels = [...channels]
|
final newChannels = [...channels]
|
||||||
..insert(0, stateChannels[stateChannels.keys.first]);
|
..insert(0, stateChannels[stateChannels.keys.first]!);
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
channelsBlocState.channelsStream,
|
channelsBlocState.channelsStream,
|
||||||
@@ -759,7 +768,7 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.on(EventType.messageNew)).called(1);
|
verify(() => mockClient.on(EventType.messageNew)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -783,12 +792,12 @@ void main() {
|
|||||||
channelsComparator: channelComparator,
|
channelsComparator: channelComparator,
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.on(any, any, any, any))
|
when(() => mockClient.on(any(), any(), any(), any()))
|
||||||
.thenAnswer((_) => Stream.empty());
|
.thenAnswer((_) => Stream.empty());
|
||||||
|
|
||||||
when(mockClient.on(
|
when(() => mockClient.on(
|
||||||
EventType.messageNew,
|
EventType.messageNew,
|
||||||
)).thenAnswer((_) => eventController.stream);
|
)).thenAnswer((_) => eventController.stream);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -801,23 +810,23 @@ void main() {
|
|||||||
find.byKey(channelsBlocKey),
|
find.byKey(channelsBlocKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockClient.queryChannels(
|
when(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) => Stream.value(channels),
|
(_) => Stream.value(channels),
|
||||||
);
|
);
|
||||||
|
|
||||||
await channelsBlocState.queryChannels();
|
await channelsBlocState.queryChannels();
|
||||||
|
|
||||||
verify(mockClient.queryChannels(
|
verify(() => mockClient.queryChannels(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final messageNewEvent = Event(
|
final messageNewEvent = Event(
|
||||||
type: EventType.messageNew,
|
type: EventType.messageNew,
|
||||||
@@ -836,7 +845,7 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.on(EventType.messageNew)).called(1);
|
verify(() => mockClient.on(EventType.messageNew)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,6 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:stream_chat_flutter_core/src/lazy_load_scroll_view.dart';
|
import 'package:stream_chat_flutter_core/src/lazy_load_scroll_view.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test(
|
|
||||||
'should throw assertion error if child is null',
|
|
||||||
() async {
|
|
||||||
const lazyLoadScrollViewKey = Key('lazyLoadScrollView');
|
|
||||||
final lazyLoadScrollView = () => LazyLoadScrollView(
|
|
||||||
key: lazyLoadScrollViewKey,
|
|
||||||
child: null,
|
|
||||||
);
|
|
||||||
expect(lazyLoadScrollView, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should render LazyLoadScrollView if child is provided',
|
'should render LazyLoadScrollView if child is provided',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Matcher isSameChannelAs(Channel targetChannel) =>
|
|||||||
|
|
||||||
class _IsSameChannelAs extends Matcher {
|
class _IsSameChannelAs extends Matcher {
|
||||||
const _IsSameChannelAs({
|
const _IsSameChannelAs({
|
||||||
@required this.targetChannel,
|
required this.targetChannel,
|
||||||
}) : assert(targetChannel != null, '');
|
}) : assert(targetChannel != null, '');
|
||||||
|
|
||||||
final Channel targetChannel;
|
final Channel targetChannel;
|
||||||
@@ -26,7 +26,7 @@ Matcher isSameChannelListAs(List<Channel> targetChannelList) =>
|
|||||||
|
|
||||||
class _IsSameChannelListAs extends Matcher {
|
class _IsSameChannelListAs extends Matcher {
|
||||||
const _IsSameChannelListAs({
|
const _IsSameChannelListAs({
|
||||||
@required this.targetChannelList,
|
required this.targetChannelList,
|
||||||
}) : assert(targetChannelList != null, '');
|
}) : assert(targetChannelList != null, '');
|
||||||
|
|
||||||
final List<Channel> targetChannelList;
|
final List<Channel> targetChannelList;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:meta/meta.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
@@ -7,15 +6,15 @@ Matcher isSameMessageResponseAs(GetMessageResponse targetResponse) =>
|
|||||||
|
|
||||||
class _IsSameMessageResponseAs extends Matcher {
|
class _IsSameMessageResponseAs extends Matcher {
|
||||||
const _IsSameMessageResponseAs({
|
const _IsSameMessageResponseAs({
|
||||||
@required this.targetResponse,
|
required this.targetResponse,
|
||||||
}) : assert(targetResponse != null, '');
|
});
|
||||||
|
|
||||||
final GetMessageResponse targetResponse;
|
final GetMessageResponse targetResponse;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool matches(covariant GetMessageResponse response, Map matchState) =>
|
bool matches(covariant GetMessageResponse response, Map matchState) =>
|
||||||
response.message.id == targetResponse.message.id &&
|
response.message.id == targetResponse.message.id &&
|
||||||
response.channel.cid == targetResponse.channel.cid;
|
response.channel?.cid == targetResponse.channel?.cid;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Description describe(Description description) =>
|
Description describe(Description description) =>
|
||||||
@@ -28,15 +27,15 @@ Matcher isSameMessageResponseListAs(
|
|||||||
|
|
||||||
class _IsSameMessageResponseListAs extends Matcher {
|
class _IsSameMessageResponseListAs extends Matcher {
|
||||||
const _IsSameMessageResponseListAs({
|
const _IsSameMessageResponseListAs({
|
||||||
@required this.targetResponseList,
|
required this.targetResponseList,
|
||||||
}) : assert(targetResponseList != null, '');
|
});
|
||||||
|
|
||||||
final List<GetMessageResponse> targetResponseList;
|
final List<GetMessageResponse> targetResponseList;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool matches(
|
bool matches(
|
||||||
covariant List<GetMessageResponse> responseList, Map matchState) {
|
covariant List<GetMessageResponse> responseList, Map matchState) {
|
||||||
bool matches = true;
|
var matches = true;
|
||||||
for (var i = 0; i < responseList.length; i++) {
|
for (var i = 0; i < responseList.length; i++) {
|
||||||
final response = responseList[i];
|
final response = responseList[i];
|
||||||
final targetResponse = targetResponseList[i];
|
final targetResponse = targetResponseList[i];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Matcher isSameMessageAs(Message targetMessage) =>
|
|||||||
|
|
||||||
class _IsSameMessageAs extends Matcher {
|
class _IsSameMessageAs extends Matcher {
|
||||||
const _IsSameMessageAs({
|
const _IsSameMessageAs({
|
||||||
@required this.targetMessage,
|
required this.targetMessage,
|
||||||
}) : assert(targetMessage != null, '');
|
}) : assert(targetMessage != null, '');
|
||||||
|
|
||||||
final Message targetMessage;
|
final Message targetMessage;
|
||||||
@@ -26,7 +26,7 @@ Matcher isSameMessageListAs(List<Message> targetMessageList) =>
|
|||||||
|
|
||||||
class _IsSameMessageListAs extends Matcher {
|
class _IsSameMessageListAs extends Matcher {
|
||||||
const _IsSameMessageListAs({
|
const _IsSameMessageListAs({
|
||||||
@required this.targetMessageList,
|
required this.targetMessageList,
|
||||||
}) : assert(targetMessageList != null, '');
|
}) : assert(targetMessageList != null, '');
|
||||||
|
|
||||||
final List<Message> targetMessageList;
|
final List<Message> targetMessageList;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Matcher isSameUserAs(User targetUser) => _IsSameUserAs(targetUser: targetUser);
|
|||||||
|
|
||||||
class _IsSameUserAs extends Matcher {
|
class _IsSameUserAs extends Matcher {
|
||||||
const _IsSameUserAs({
|
const _IsSameUserAs({
|
||||||
@required this.targetUser,
|
required this.targetUser,
|
||||||
}) : assert(targetUser != null, '');
|
}) : assert(targetUser != null, '');
|
||||||
|
|
||||||
final User targetUser;
|
final User targetUser;
|
||||||
@@ -24,7 +24,7 @@ Matcher isSameUserListAs(List<User> targetUserList) =>
|
|||||||
|
|
||||||
class _IsSameUserListAs extends Matcher {
|
class _IsSameUserListAs extends Matcher {
|
||||||
const _IsSameUserListAs({
|
const _IsSameUserListAs({
|
||||||
@required this.targetUserList,
|
required this.targetUserList,
|
||||||
}) : assert(targetUserList != null, '');
|
}) : assert(targetUserList != null, '');
|
||||||
|
|
||||||
final List<User> targetUserList;
|
final List<User> targetUserList;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat_flutter_core/src/message_list_core.dart';
|
import 'package:stream_chat_flutter_core/src/message_list_core.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
@@ -62,61 +62,6 @@ void main() {
|
|||||||
return threads ? threadMessages : messages;
|
return threads ? threadMessages : messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case messageListBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageListCore = () => MessageListCore(
|
|
||||||
messageListBuilder: null,
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorWidgetBuilder: (BuildContext context, Object error) =>
|
|
||||||
Offstage(),
|
|
||||||
);
|
|
||||||
expect(messageListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case loadingBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageListCore = () => MessageListCore(
|
|
||||||
messageListBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: null,
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorWidgetBuilder: (BuildContext context, Object error) =>
|
|
||||||
Offstage(),
|
|
||||||
);
|
|
||||||
expect(messageListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case emptyBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageListCore = () => MessageListCore(
|
|
||||||
messageListBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: null,
|
|
||||||
errorWidgetBuilder: (BuildContext context, Object error) =>
|
|
||||||
Offstage(),
|
|
||||||
);
|
|
||||||
expect(messageListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case errorWidgetBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageListCore = () => MessageListCore(
|
|
||||||
messageListBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorWidgetBuilder: null,
|
|
||||||
);
|
|
||||||
expect(messageListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should throw if MessageListCore is used where StreamChannel is not present '
|
'should throw if MessageListCore is used where StreamChannel is not present '
|
||||||
'in the widget tree',
|
'in the widget tree',
|
||||||
@@ -150,8 +95,11 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
|
when(() => mockChannel.initialized).thenAnswer((_) => Future.value(true));
|
||||||
|
|
||||||
when(mockChannel.state.isUpToDate).thenReturn(true);
|
when(() => mockChannel.state.isUpToDate).thenReturn(true);
|
||||||
|
when(() => mockChannel.state.messagesStream)
|
||||||
|
.thenAnswer((_) => Stream.value([]));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChannel(
|
StreamChannel(
|
||||||
@@ -182,7 +130,10 @@ void main() {
|
|||||||
|
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
|
|
||||||
when(mockChannel.state.isUpToDate).thenReturn(true);
|
when(() => mockChannel.state.isUpToDate).thenReturn(true);
|
||||||
|
when(() => mockChannel.state.messagesStream)
|
||||||
|
.thenAnswer((_) => Stream.value([]));
|
||||||
|
when(() => mockChannel.initialized).thenAnswer((_) => Future.value(true));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChannel(
|
StreamChannel(
|
||||||
@@ -213,11 +164,11 @@ void main() {
|
|||||||
|
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
|
|
||||||
when(mockChannel.state.isUpToDate).thenReturn(true);
|
when(() => mockChannel.state.isUpToDate).thenReturn(true);
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => true);
|
when(() => mockChannel.initialized).thenAnswer((_) async => true);
|
||||||
|
|
||||||
const error = 'Error! Error! Error!';
|
const error = 'Error! Error! Error!';
|
||||||
when(mockChannel.state.messagesStream)
|
when(() => mockChannel.state.messagesStream)
|
||||||
.thenAnswer((_) => Stream.error(error));
|
.thenAnswer((_) => Stream.error(error));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@@ -252,11 +203,11 @@ void main() {
|
|||||||
|
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
|
|
||||||
when(mockChannel.state.isUpToDate).thenReturn(true);
|
when(() => mockChannel.state.isUpToDate).thenReturn(true);
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => true);
|
when(() => mockChannel.initialized).thenAnswer((_) async => true);
|
||||||
|
|
||||||
const messages = <Message>[];
|
const messages = <Message>[];
|
||||||
when(mockChannel.state.messagesStream)
|
when(() => mockChannel.state.messagesStream)
|
||||||
.thenAnswer((_) => Stream.value(messages));
|
.thenAnswer((_) => Stream.value(messages));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@@ -291,11 +242,18 @@ void main() {
|
|||||||
|
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
|
|
||||||
when(mockChannel.state.isUpToDate).thenReturn(false);
|
when(() => mockChannel.state.isUpToDate).thenReturn(false);
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => true);
|
when(() => mockChannel.initialized).thenAnswer((_) async => true);
|
||||||
|
when(() => mockChannel.query(
|
||||||
|
options: any(named: 'options'),
|
||||||
|
membersPagination: any(named: 'membersPagination'),
|
||||||
|
messagesPagination: any(named: 'messagesPagination'),
|
||||||
|
preferOffline: any(named: 'preferOffline'),
|
||||||
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
|
)).thenAnswer((_) async => ChannelState());
|
||||||
|
|
||||||
const messages = <Message>[];
|
const messages = <Message>[];
|
||||||
when(mockChannel.state.messagesStream)
|
when(() => mockChannel.state.messagesStream)
|
||||||
.thenAnswer((_) => Stream.value(messages));
|
.thenAnswer((_) => Stream.value(messages));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@@ -335,11 +293,11 @@ void main() {
|
|||||||
|
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
|
|
||||||
when(mockChannel.state.isUpToDate).thenReturn(true);
|
when(() => mockChannel.state.isUpToDate).thenReturn(true);
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => true);
|
when(() => mockChannel.initialized).thenAnswer((_) async => true);
|
||||||
|
|
||||||
final messages = _generateMessages();
|
final messages = _generateMessages();
|
||||||
when(mockChannel.state.messagesStream)
|
when(() => mockChannel.state.messagesStream)
|
||||||
.thenAnswer((_) => Stream.value(messages));
|
.thenAnswer((_) => Stream.value(messages));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@@ -382,13 +340,13 @@ void main() {
|
|||||||
|
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
|
|
||||||
when(mockChannel.state.isUpToDate).thenReturn(true);
|
when(() => mockChannel.state.isUpToDate).thenReturn(true);
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => true);
|
when(() => mockChannel.initialized).thenAnswer((_) async => true);
|
||||||
|
|
||||||
final threads = {parentMessage.id: messages};
|
final threads = {parentMessage.id: messages};
|
||||||
|
|
||||||
when(mockChannel.state.threads).thenReturn(threads);
|
when(() => mockChannel.state.threads).thenReturn(threads);
|
||||||
when(mockChannel.state.threadsStream)
|
when(() => mockChannel.state.threadsStream)
|
||||||
.thenAnswer((_) => Stream.value(threads));
|
.thenAnswer((_) => Stream.value(threads));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:stream_chat_flutter_core/src/message_search_bloc.dart';
|
import 'package:stream_chat_flutter_core/src/message_search_bloc.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
@@ -23,24 +23,12 @@ void main() {
|
|||||||
text: 'testTextData$index',
|
text: 'testTextData$index',
|
||||||
)
|
)
|
||||||
..channel = ChannelModel(
|
..channel = ChannelModel(
|
||||||
cid: 'testCid',
|
cid: 'testCid:id',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error if child is null',
|
|
||||||
() async {
|
|
||||||
const messageSearchBlocKey = Key('messageSearchBloc');
|
|
||||||
final messageSearchBloc = () => MessageSearchBloc(
|
|
||||||
key: messageSearchBlocKey,
|
|
||||||
child: null,
|
|
||||||
);
|
|
||||||
expect(messageSearchBloc, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'messageSearchBlocState.search() should throw if used where '
|
'messageSearchBlocState.search() should throw if used where '
|
||||||
'StreamChat is not present in the widget tree',
|
'StreamChat is not present in the widget tree',
|
||||||
@@ -62,7 +50,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await usersBlocState.search();
|
await usersBlocState.search(filter: {});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e, isInstanceOf<Exception>());
|
expect(e, isInstanceOf<Exception>());
|
||||||
}
|
}
|
||||||
@@ -93,30 +81,30 @@ void main() {
|
|||||||
|
|
||||||
final messageResponseList = _generateMessages();
|
final messageResponseList = _generateMessages();
|
||||||
|
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
messageSearchBlocState.search();
|
messageSearchBlocState.search(filter: {});
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
messageSearchBlocState.messagesStream,
|
messageSearchBlocState.messagesStream,
|
||||||
emits(isSameMessageResponseListAs(messageResponseList)),
|
emits(isSameMessageResponseListAs(messageResponseList)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -144,28 +132,28 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const error = 'Error! Error! Error!';
|
const error = 'Error! Error! Error!';
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
messageSearchBlocState.search();
|
messageSearchBlocState.search(filter: {});
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
messageSearchBlocState.messagesStream,
|
messageSearchBlocState.messagesStream,
|
||||||
emitsError(error),
|
emitsError(error),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -196,47 +184,47 @@ void main() {
|
|||||||
|
|
||||||
final messageResponseList = _generateMessages();
|
final messageResponseList = _generateMessages();
|
||||||
|
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
messageSearchBlocState.search();
|
messageSearchBlocState.search(filter: {});
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
messageSearchBlocState.messagesStream,
|
messageSearchBlocState.messagesStream,
|
||||||
emits(isSameMessageResponseListAs(messageResponseList)),
|
emits(isSameMessageResponseListAs(messageResponseList)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final offset = messageResponseList.length;
|
final offset = messageResponseList.length;
|
||||||
final paginatedMessageResponseList = _generateMessages(offset: offset);
|
final paginatedMessageResponseList = _generateMessages(offset: offset);
|
||||||
final pagination = PaginationParams(offset: offset);
|
final pagination = PaginationParams(offset: offset);
|
||||||
|
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async =>
|
(_) async =>
|
||||||
SearchMessagesResponse()..results = paginatedMessageResponseList,
|
SearchMessagesResponse()..results = paginatedMessageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
messageSearchBlocState.search(pagination: pagination);
|
messageSearchBlocState.search(pagination: pagination, filter: {});
|
||||||
|
|
||||||
await Future.wait([
|
await Future.wait([
|
||||||
expectLater(
|
expectLater(
|
||||||
@@ -251,13 +239,13 @@ void main() {
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -288,57 +276,57 @@ void main() {
|
|||||||
|
|
||||||
final messageResponseList = _generateMessages();
|
final messageResponseList = _generateMessages();
|
||||||
|
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
messageSearchBlocState.search();
|
messageSearchBlocState.search(filter: {});
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
messageSearchBlocState.messagesStream,
|
messageSearchBlocState.messagesStream,
|
||||||
emits(isSameMessageResponseListAs(messageResponseList)),
|
emits(isSameMessageResponseListAs(messageResponseList)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final offset = messageResponseList.length;
|
final offset = messageResponseList.length;
|
||||||
final pagination = PaginationParams(offset: offset);
|
final pagination = PaginationParams(offset: offset);
|
||||||
|
|
||||||
const error = 'Error! Error! Error!';
|
const error = 'Error! Error! Error!';
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
messageSearchBlocState.search(pagination: pagination);
|
messageSearchBlocState.search(pagination: pagination, filter: {});
|
||||||
|
|
||||||
await expectLater(
|
await expectLater(
|
||||||
messageSearchBlocState.queryMessagesLoading,
|
messageSearchBlocState.queryMessagesLoading,
|
||||||
emitsError(error),
|
emitsError(error),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
|
||||||
import 'package:stream_chat_flutter_core/src/message_search_list_core.dart';
|
import 'package:stream_chat_flutter_core/src/message_search_list_core.dart';
|
||||||
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
import 'mocks.dart';
|
import 'mocks.dart';
|
||||||
|
|
||||||
@@ -10,74 +10,21 @@ void main() {
|
|||||||
List<GetMessageResponse> _generateMessages({
|
List<GetMessageResponse> _generateMessages({
|
||||||
int count = 3,
|
int count = 3,
|
||||||
int offset = 0,
|
int offset = 0,
|
||||||
}) {
|
}) =>
|
||||||
return List.generate(
|
List.generate(
|
||||||
count,
|
count,
|
||||||
(index) {
|
(index) {
|
||||||
index = index + offset;
|
index = index + offset;
|
||||||
return GetMessageResponse()
|
return GetMessageResponse()
|
||||||
..message = Message(
|
..message = Message(
|
||||||
id: 'testId$index',
|
id: 'testId$index',
|
||||||
text: 'testTextData$index',
|
text: 'testTextData$index',
|
||||||
)
|
)
|
||||||
..channel = ChannelModel(
|
..channel = ChannelModel(
|
||||||
cid: 'testCid',
|
cid: 'test:Cid',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case childBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageSearchListCore = () => MessageSearchListCore(
|
|
||||||
childBuilder: null,
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case loadingBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageSearchListCore = () => MessageSearchListCore(
|
|
||||||
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
|
|
||||||
loadingBuilder: null,
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case emptyBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageSearchListCore = () => MessageSearchListCore(
|
|
||||||
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: null,
|
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case errorBuilder is null',
|
|
||||||
() {
|
|
||||||
final messageSearchListCore = () => MessageSearchListCore(
|
|
||||||
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: null,
|
|
||||||
);
|
|
||||||
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should throw if MessageSearchListCore is used where MessageSearchBloc '
|
'should throw if MessageSearchListCore is used where MessageSearchBloc '
|
||||||
@@ -86,10 +33,11 @@ void main() {
|
|||||||
const messageSearchListCoreKey = Key('messageSearchListCore');
|
const messageSearchListCoreKey = Key('messageSearchListCore');
|
||||||
final messageSearchListCore = MessageSearchListCore(
|
final messageSearchListCore = MessageSearchListCore(
|
||||||
key: messageSearchListCoreKey,
|
key: messageSearchListCoreKey,
|
||||||
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
|
childBuilder: (List<GetMessageResponse>? messages) => const Offstage(),
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
loadingBuilder: (BuildContext context) => const Offstage(),
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
emptyBuilder: (BuildContext context) => const Offstage(),
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
errorBuilder: (BuildContext context, Object? error) => const Offstage(),
|
||||||
|
filters: const {},
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.pumpWidget(messageSearchListCore);
|
await tester.pumpWidget(messageSearchListCore);
|
||||||
@@ -109,7 +57,8 @@ void main() {
|
|||||||
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
|
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
loadingBuilder: (BuildContext context) => Offstage(),
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
emptyBuilder: (BuildContext context) => Offstage(),
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
errorBuilder: (BuildContext context, Object? error) => Offstage(),
|
||||||
|
filters: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
@@ -140,6 +89,7 @@ void main() {
|
|||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
emptyBuilder: (BuildContext context) => Offstage(),
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
||||||
messageSearchListController: controller,
|
messageSearchListController: controller,
|
||||||
|
filters: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(controller.loadData, isNull);
|
expect(controller.loadData, isNull);
|
||||||
@@ -175,18 +125,19 @@ void main() {
|
|||||||
errorBuilder: (BuildContext context, Object error) => Offstage(
|
errorBuilder: (BuildContext context, Object error) => Offstage(
|
||||||
key: errorWidgetKey,
|
key: errorWidgetKey,
|
||||||
),
|
),
|
||||||
|
filters: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
const error = 'Error! Error! Error!';
|
const error = 'Error! Error! Error!';
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -201,13 +152,13 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(errorWidgetKey), findsOneWidget);
|
expect(find.byKey(errorWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -223,18 +174,19 @@ void main() {
|
|||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
loadingBuilder: (BuildContext context) => Offstage(),
|
||||||
emptyBuilder: (BuildContext context) => Offstage(key: emptyWidgetKey),
|
emptyBuilder: (BuildContext context) => Offstage(key: emptyWidgetKey),
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
||||||
|
filters: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final messageResponseList = <GetMessageResponse>[];
|
final messageResponseList = <GetMessageResponse>[];
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -251,13 +203,13 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(emptyWidgetKey), findsOneWidget);
|
expect(find.byKey(emptyWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -274,18 +226,19 @@ void main() {
|
|||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
loadingBuilder: (BuildContext context) => Offstage(),
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
emptyBuilder: (BuildContext context) => Offstage(),
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
||||||
|
filters: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final messageResponseList = _generateMessages();
|
final messageResponseList = _generateMessages();
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -302,13 +255,13 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(childWidgetKey), findsOneWidget);
|
expect(find.byKey(childWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: anyNamed('paginationParams'),
|
paginationParams: any(named: 'paginationParams'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -324,25 +277,26 @@ void main() {
|
|||||||
childBuilder: (List<GetMessageResponse> messages) => Container(
|
childBuilder: (List<GetMessageResponse> messages) => Container(
|
||||||
key: childWidgetKey,
|
key: childWidgetKey,
|
||||||
child: Text(
|
child: Text(
|
||||||
messages.map((e) => '${e.channel.cid}-${e.message.id}').join(','),
|
messages.map((e) => '${e.channel?.cid}-${e.message.id}').join(','),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
loadingBuilder: (BuildContext context) => Offstage(),
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
emptyBuilder: (BuildContext context) => Offstage(),
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
|
filters: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final messageResponseList = _generateMessages();
|
final messageResponseList = _generateMessages();
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -364,19 +318,19 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
find.text(
|
find.text(
|
||||||
messageResponseList
|
messageResponseList
|
||||||
.map((e) => '${e.channel.cid}-${e.message.id}')
|
.map((e) => '${e.channel?.cid}-${e.message.id}')
|
||||||
.join(','),
|
.join(','),
|
||||||
),
|
),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final messageSearchListCoreState =
|
final messageSearchListCoreState =
|
||||||
tester.state<MessageSearchListCoreState>(
|
tester.state<MessageSearchListCoreState>(
|
||||||
@@ -386,13 +340,13 @@ void main() {
|
|||||||
final offset = messageResponseList.length;
|
final offset = messageResponseList.length;
|
||||||
final paginatedMessageResponseList = _generateMessages(offset: offset);
|
final paginatedMessageResponseList = _generateMessages(offset: offset);
|
||||||
final updatedPagination = pagination.copyWith(offset: offset);
|
final updatedPagination = pagination.copyWith(offset: offset);
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async =>
|
(_) async =>
|
||||||
SearchMessagesResponse()..results = paginatedMessageResponseList,
|
SearchMessagesResponse()..results = paginatedMessageResponseList,
|
||||||
);
|
);
|
||||||
@@ -406,17 +360,17 @@ void main() {
|
|||||||
find.text([
|
find.text([
|
||||||
...messageResponseList,
|
...messageResponseList,
|
||||||
...paginatedMessageResponseList,
|
...paginatedMessageResponseList,
|
||||||
].map((e) => '${e.channel.cid}-${e.message.id}').join(',')),
|
].map((e) => '${e.channel?.cid}-${e.message.id}').join(',')),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -426,8 +380,8 @@ void main() {
|
|||||||
(tester) async {
|
(tester) async {
|
||||||
const pagination = PaginationParams();
|
const pagination = PaginationParams();
|
||||||
|
|
||||||
StateSetter _stateSetter;
|
StateSetter? _stateSetter;
|
||||||
int limit = pagination.limit;
|
var limit = pagination.limit;
|
||||||
|
|
||||||
const messageSearchListCoreKey = Key('messageSearchListCore');
|
const messageSearchListCoreKey = Key('messageSearchListCore');
|
||||||
const childWidgetKey = Key('childWidget');
|
const childWidgetKey = Key('childWidget');
|
||||||
@@ -438,7 +392,7 @@ void main() {
|
|||||||
key: childWidgetKey,
|
key: childWidgetKey,
|
||||||
child: Text(
|
child: Text(
|
||||||
messages
|
messages
|
||||||
.map((e) => '${e.channel.cid}-${e.message.id}')
|
.map((e) => '${e.channel?.cid}-${e.message.id}')
|
||||||
.join(','),
|
.join(','),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -446,18 +400,19 @@ void main() {
|
|||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
emptyBuilder: (BuildContext context) => Offstage(),
|
||||||
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
errorBuilder: (BuildContext context, Object error) => Offstage(),
|
||||||
paginationParams: pagination.copyWith(limit: limit),
|
paginationParams: pagination.copyWith(limit: limit),
|
||||||
|
filters: {},
|
||||||
);
|
);
|
||||||
|
|
||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final messageResponseList = _generateMessages();
|
final messageResponseList = _generateMessages();
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
(_) async => SearchMessagesResponse()..results = messageResponseList,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -483,32 +438,32 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
find.text(
|
find.text(
|
||||||
messageResponseList
|
messageResponseList
|
||||||
.map((e) => '${e.channel.cid}-${e.message.id}')
|
.map((e) => '${e.channel?.cid}-${e.message.id}')
|
||||||
.join(','),
|
.join(','),
|
||||||
),
|
),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: pagination,
|
paginationParams: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
// Rebuilding MessageSearchListCore with new pagination limit
|
// Rebuilding MessageSearchListCore with new pagination limit
|
||||||
_stateSetter(() => limit = 6);
|
_stateSetter?.call(() => limit = 6);
|
||||||
|
|
||||||
final updatedMessageResponseList = _generateMessages(count: limit);
|
final updatedMessageResponseList = _generateMessages(count: limit);
|
||||||
final updatedPagination = pagination.copyWith(limit: limit);
|
final updatedPagination = pagination.copyWith(limit: limit);
|
||||||
when(mockClient.search(
|
when(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).thenAnswer(
|
)).thenAnswer(
|
||||||
(_) async =>
|
(_) async =>
|
||||||
SearchMessagesResponse()..results = updatedMessageResponseList,
|
SearchMessagesResponse()..results = updatedMessageResponseList,
|
||||||
);
|
);
|
||||||
@@ -518,18 +473,18 @@ void main() {
|
|||||||
expect(find.byKey(childWidgetKey), findsOneWidget);
|
expect(find.byKey(childWidgetKey), findsOneWidget);
|
||||||
expect(
|
expect(
|
||||||
find.text(updatedMessageResponseList
|
find.text(updatedMessageResponseList
|
||||||
.map((e) => '${e.channel.cid}-${e.message.id}')
|
.map((e) => '${e.channel?.cid}-${e.message.id}')
|
||||||
.join(',')),
|
.join(',')),
|
||||||
findsOneWidget,
|
findsOneWidget,
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.search(
|
verify(() => mockClient.search(
|
||||||
any,
|
any(),
|
||||||
query: anyNamed('query'),
|
query: any(named: 'query'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
messageFilters: anyNamed('messageFilters'),
|
messageFilters: any(named: 'messageFilters'),
|
||||||
paginationParams: updatedPagination,
|
paginationParams: updatedPagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
|
||||||
class MockLogger extends Mock implements Logger {}
|
class MockLogger extends Mock implements Logger {}
|
||||||
|
|
||||||
class MockClient extends Mock implements StreamChatClient {
|
class MockClient extends Mock implements StreamChatClient {
|
||||||
|
@override
|
||||||
final Logger logger = MockLogger();
|
final Logger logger = MockLogger();
|
||||||
|
|
||||||
ClientState _state;
|
ClientState? _state;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ClientState get state => _state ??= MockClientState();
|
ClientState get state => _state ??= MockClientState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockClientState extends Mock implements ClientState {
|
class MockClientState extends Mock implements ClientState {
|
||||||
OwnUser _user;
|
OwnUser? _user;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
OwnUser get user => _user ??= OwnUser(
|
OwnUser get user => _user ??= OwnUser(
|
||||||
@@ -25,12 +26,12 @@ class MockClientState extends Mock implements ClientState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MockChannel extends Mock implements Channel {
|
class MockChannel extends Mock implements Channel {
|
||||||
ChannelClientState _state;
|
ChannelClientState? _state;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ChannelClientState get state => _state ??= MockChannelState();
|
ChannelClientState get state => _state ??= MockChannelState();
|
||||||
|
|
||||||
StreamChatClient _client;
|
StreamChatClient? _client;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
StreamChatClient get client => _client ??= MockClient();
|
StreamChatClient get client => _client ??= MockClient();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'dart:async';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
import 'mocks.dart';
|
import 'mocks.dart';
|
||||||
@@ -62,39 +62,13 @@ void main() {
|
|||||||
return threads ? threadMessages : messages;
|
return threads ? threadMessages : messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error if child is null',
|
|
||||||
() async {
|
|
||||||
final mockChannel = MockChannel();
|
|
||||||
const streamChannelKey = Key('streamChannel');
|
|
||||||
final streamChannel = () => StreamChannel(
|
|
||||||
key: streamChannelKey,
|
|
||||||
channel: mockChannel,
|
|
||||||
child: null,
|
|
||||||
);
|
|
||||||
expect(streamChannel, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error if channel is null',
|
|
||||||
() async {
|
|
||||||
const streamChannelKey = Key('streamChannel');
|
|
||||||
final streamChannel = () => StreamChannel(
|
|
||||||
key: streamChannelKey,
|
|
||||||
child: Offstage(),
|
|
||||||
channel: null,
|
|
||||||
);
|
|
||||||
expect(streamChannel, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should render StreamChannel if both channel and child is provided',
|
'should render StreamChannel if both channel and child is provided',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
final mockChannel = MockChannel();
|
final mockChannel = MockChannel();
|
||||||
const streamChannelKey = Key('streamChannel');
|
const streamChannelKey = Key('streamChannel');
|
||||||
const childKey = Key('childKey');
|
const childKey = Key('childKey');
|
||||||
|
when(() => mockChannel.initialized).thenAnswer((_) => Future.value(true));
|
||||||
final streamChannel = StreamChannel(
|
final streamChannel = StreamChannel(
|
||||||
key: streamChannelKey,
|
key: streamChannelKey,
|
||||||
channel: mockChannel,
|
channel: mockChannel,
|
||||||
@@ -121,8 +95,13 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final errorMessage = 'Error! Error! Error!';
|
final errorMessage = 'Error! Error! Error!';
|
||||||
final error = DioError(type: DioErrorType.response, error: errorMessage);
|
final error = DioError(
|
||||||
when(mockChannel.initialized).thenAnswer((_) => Future.error(error));
|
type: DioErrorType.response,
|
||||||
|
error: errorMessage,
|
||||||
|
requestOptions: RequestOptions(path: ''),
|
||||||
|
);
|
||||||
|
when(() => mockChannel.initialized)
|
||||||
|
.thenAnswer((_) => Future.error(error));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -135,7 +114,7 @@ void main() {
|
|||||||
|
|
||||||
expect(find.text(errorMessage), findsOneWidget);
|
expect(find.text(errorMessage), findsOneWidget);
|
||||||
|
|
||||||
verify(mockChannel.initialized).called(1);
|
verify(() => mockChannel.initialized).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -153,7 +132,7 @@ void main() {
|
|||||||
showLoading: true,
|
showLoading: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => false);
|
when(() => mockChannel.initialized).thenAnswer((_) async => false);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -166,7 +145,7 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
||||||
|
|
||||||
verify(mockChannel.initialized).called(1);
|
verify(() => mockChannel.initialized).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -183,15 +162,15 @@ void main() {
|
|||||||
initialMessageId: 'testInitialMessageId',
|
initialMessageId: 'testInitialMessageId',
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => true);
|
when(() => mockChannel.initialized).thenAnswer((_) async => true);
|
||||||
final messages = _generateMessages();
|
final messages = _generateMessages();
|
||||||
when(mockChannel.query(
|
when(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: anyNamed('messagesPagination'),
|
messagesPagination: any(named: 'messagesPagination'),
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).thenAnswer((_) async => ChannelState(messages: messages));
|
)).thenAnswer((_) async => ChannelState(messages: messages));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -202,14 +181,14 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
verify(mockChannel.initialized).called(1);
|
verify(() => mockChannel.initialized).called(1);
|
||||||
verify(mockChannel.query(
|
verify(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: anyNamed('messagesPagination'),
|
messagesPagination: any(named: 'messagesPagination'),
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).called(
|
)).called(
|
||||||
2, // Fetching After messages + Fetching Before messages,
|
2, // Fetching After messages + Fetching Before messages,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -219,7 +198,7 @@ void main() {
|
|||||||
'should rebuild StreamChannel with updated widget data '
|
'should rebuild StreamChannel with updated widget data '
|
||||||
'on calling setState()',
|
'on calling setState()',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
StateSetter _stateSetter;
|
StateSetter? _stateSetter;
|
||||||
|
|
||||||
var initialMessageId = 'testInitialMessageId';
|
var initialMessageId = 'testInitialMessageId';
|
||||||
|
|
||||||
@@ -244,25 +223,25 @@ void main() {
|
|||||||
limit: 20,
|
limit: 20,
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockChannel.initialized).thenAnswer((_) async => true);
|
when(() => mockChannel.initialized).thenAnswer((_) async => true);
|
||||||
|
|
||||||
final messages = _generateMessages();
|
final messages = _generateMessages();
|
||||||
|
|
||||||
when(mockChannel.query(
|
when(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: beforePagination,
|
messagesPagination: beforePagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).thenAnswer((_) async => ChannelState(messages: messages));
|
)).thenAnswer((_) async => ChannelState(messages: messages));
|
||||||
|
|
||||||
when(mockChannel.query(
|
when(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: afterPagination,
|
messagesPagination: afterPagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).thenAnswer((_) async => ChannelState(messages: messages));
|
)).thenAnswer((_) async => ChannelState(messages: messages));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -279,23 +258,23 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
verify(mockChannel.query(
|
verify(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: beforePagination,
|
messagesPagination: beforePagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
verify(mockChannel.query(
|
verify(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: afterPagination,
|
messagesPagination: afterPagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
_stateSetter(() => initialMessageId = 'testInitialMessageId2');
|
_stateSetter?.call(() => initialMessageId = 'testInitialMessageId2');
|
||||||
|
|
||||||
final updatedBeforePagination = beforePagination.copyWith(
|
final updatedBeforePagination = beforePagination.copyWith(
|
||||||
lessThan: initialMessageId,
|
lessThan: initialMessageId,
|
||||||
@@ -305,39 +284,39 @@ void main() {
|
|||||||
greaterThanOrEqual: initialMessageId,
|
greaterThanOrEqual: initialMessageId,
|
||||||
);
|
);
|
||||||
|
|
||||||
when(mockChannel.query(
|
when(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: updatedBeforePagination,
|
messagesPagination: updatedBeforePagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).thenAnswer((_) async => ChannelState(messages: messages));
|
)).thenAnswer((_) async => ChannelState(messages: messages));
|
||||||
|
|
||||||
when(mockChannel.query(
|
when(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: updatedAfterPagination,
|
messagesPagination: updatedAfterPagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).thenAnswer((_) async => ChannelState(messages: messages));
|
)).thenAnswer((_) async => ChannelState(messages: messages));
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
verify(mockChannel.query(
|
verify(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: updatedBeforePagination,
|
messagesPagination: updatedBeforePagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
verify(mockChannel.query(
|
verify(() => mockChannel.query(
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
messagesPagination: updatedAfterPagination,
|
messagesPagination: updatedAfterPagination,
|
||||||
membersPagination: anyNamed('membersPagination'),
|
membersPagination: any(named: 'membersPagination'),
|
||||||
watchersPagination: anyNamed('watchersPagination'),
|
watchersPagination: any(named: 'watchersPagination'),
|
||||||
preferOffline: anyNamed('preferOffline'),
|
preferOffline: any(named: 'preferOffline'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
import 'mocks.dart';
|
import 'mocks.dart';
|
||||||
@@ -12,29 +12,6 @@ class MockOnBackgroundEventReceived extends Mock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test(
|
|
||||||
'should throw assertion error in case client is null',
|
|
||||||
() {
|
|
||||||
final streamChatCore = () => StreamChatCore(
|
|
||||||
client: null,
|
|
||||||
child: Offstage(),
|
|
||||||
);
|
|
||||||
expect(streamChatCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case child is null',
|
|
||||||
() {
|
|
||||||
final mockClient = MockClient();
|
|
||||||
final streamChatCore = () => StreamChatCore(
|
|
||||||
client: mockClient,
|
|
||||||
child: null,
|
|
||||||
);
|
|
||||||
expect(streamChatCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should render StreamChatCore if both client and child is provided',
|
'should render StreamChatCore if both client and child is provided',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
@@ -92,7 +69,7 @@ void main() {
|
|||||||
expect(find.byKey(streamChatCoreKey), findsOneWidget);
|
expect(find.byKey(streamChatCoreKey), findsOneWidget);
|
||||||
expect(find.byKey(childKey), findsOneWidget);
|
expect(find.byKey(childKey), findsOneWidget);
|
||||||
|
|
||||||
when(mockClient.disconnect()).thenAnswer((_) async {
|
when(() => mockClient.disconnect()).thenAnswer((_) async {
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -102,7 +79,7 @@ void main() {
|
|||||||
|
|
||||||
streamChatCoreState.didChangeAppLifecycleState(AppLifecycleState.paused);
|
streamChatCoreState.didChangeAppLifecycleState(AppLifecycleState.paused);
|
||||||
|
|
||||||
verify(mockClient.disconnect()).called(1);
|
verify(() => mockClient.disconnect()).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -131,8 +108,8 @@ void main() {
|
|||||||
expect(find.byKey(childKey), findsOneWidget);
|
expect(find.byKey(childKey), findsOneWidget);
|
||||||
|
|
||||||
final event = Event();
|
final event = Event();
|
||||||
when(mockClient.on()).thenAnswer((_) => Stream.value(event));
|
when(() => mockClient.on()).thenAnswer((_) => Stream.value(event));
|
||||||
when(mockClient.disconnect()).thenAnswer((_) async {
|
when(() => mockClient.disconnect()).thenAnswer((_) async {
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -143,14 +120,14 @@ void main() {
|
|||||||
streamChatCoreState
|
streamChatCoreState
|
||||||
.didChangeAppLifecycleState(AppLifecycleState.paused);
|
.didChangeAppLifecycleState(AppLifecycleState.paused);
|
||||||
|
|
||||||
await untilCalled(mockOnBackgroundEventReceived.call(event));
|
await untilCalled(() => mockOnBackgroundEventReceived.call(event));
|
||||||
|
|
||||||
verify(mockOnBackgroundEventReceived.call(event)).called(1);
|
verify(() => mockOnBackgroundEventReceived.call(event)).called(1);
|
||||||
|
|
||||||
await Future.delayed(backgroundKeepAlive);
|
await Future.delayed(backgroundKeepAlive);
|
||||||
|
|
||||||
verify(mockClient.disconnect()).called(1);
|
verify(() => mockClient.disconnect()).called(1);
|
||||||
verifyNever(mockOnBackgroundEventReceived.call(event));
|
verifyNever(() => mockOnBackgroundEventReceived.call(event));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -180,7 +157,7 @@ void main() {
|
|||||||
expect(find.byKey(childKey), findsOneWidget);
|
expect(find.byKey(childKey), findsOneWidget);
|
||||||
|
|
||||||
final event = Event();
|
final event = Event();
|
||||||
when(mockClient.on()).thenAnswer((_) => Stream.value(event));
|
when(() => mockClient.on()).thenAnswer((_) => Stream.value(event));
|
||||||
|
|
||||||
final streamChatCoreState = tester.state<StreamChatCoreState>(
|
final streamChatCoreState = tester.state<StreamChatCoreState>(
|
||||||
find.byKey(streamChatCoreKey),
|
find.byKey(streamChatCoreKey),
|
||||||
@@ -189,14 +166,14 @@ void main() {
|
|||||||
streamChatCoreState
|
streamChatCoreState
|
||||||
.didChangeAppLifecycleState(AppLifecycleState.paused);
|
.didChangeAppLifecycleState(AppLifecycleState.paused);
|
||||||
|
|
||||||
await untilCalled(mockOnBackgroundEventReceived.call(event));
|
await untilCalled(() => mockOnBackgroundEventReceived.call(event));
|
||||||
|
|
||||||
verify(mockOnBackgroundEventReceived.call(event)).called(1);
|
verify(() => mockOnBackgroundEventReceived.call(event)).called(1);
|
||||||
|
|
||||||
streamChatCoreState
|
streamChatCoreState
|
||||||
.didChangeAppLifecycleState(AppLifecycleState.resumed);
|
.didChangeAppLifecycleState(AppLifecycleState.resumed);
|
||||||
|
|
||||||
verifyNever(mockOnBackgroundEventReceived.call(event));
|
verifyNever(() => mockOnBackgroundEventReceived.call(event));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -222,9 +199,10 @@ void main() {
|
|||||||
expect(find.byKey(childKey), findsOneWidget);
|
expect(find.byKey(childKey), findsOneWidget);
|
||||||
|
|
||||||
final event = Event();
|
final event = Event();
|
||||||
when(mockClient.on()).thenAnswer((_) => Stream.value(event));
|
when(() => mockClient.on()).thenAnswer((_) => Stream.value(event));
|
||||||
when(mockClient.connect()).thenAnswer((_) async => event);
|
when(() => mockClient.connect()).thenAnswer((_) async => event);
|
||||||
when(mockClient.wsConnectionStatus)
|
when(mockClient.disconnect).thenAnswer((_) async => null);
|
||||||
|
when(() => mockClient.wsConnectionStatus)
|
||||||
.thenReturn(ConnectionStatus.disconnected);
|
.thenReturn(ConnectionStatus.disconnected);
|
||||||
|
|
||||||
final streamChatCoreState = tester.state<StreamChatCoreState>(
|
final streamChatCoreState = tester.state<StreamChatCoreState>(
|
||||||
@@ -239,7 +217,7 @@ void main() {
|
|||||||
streamChatCoreState
|
streamChatCoreState
|
||||||
.didChangeAppLifecycleState(AppLifecycleState.resumed);
|
.didChangeAppLifecycleState(AppLifecycleState.resumed);
|
||||||
|
|
||||||
verify(mockClient.connect()).called(1);
|
verify(() => mockClient.connect()).called(1);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -265,7 +243,7 @@ void main() {
|
|||||||
expect(find.byKey(streamChatCoreKey), findsOneWidget);
|
expect(find.byKey(streamChatCoreKey), findsOneWidget);
|
||||||
expect(find.byKey(childKey), findsOneWidget);
|
expect(find.byKey(childKey), findsOneWidget);
|
||||||
|
|
||||||
when(mockClient.state.userStream)
|
when(() => mockClient.state.userStream)
|
||||||
.thenAnswer((_) => userController.stream);
|
.thenAnswer((_) => userController.stream);
|
||||||
|
|
||||||
final streamChatCoreState = tester.state<StreamChatCoreState>(
|
final streamChatCoreState = tester.state<StreamChatCoreState>(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat_flutter_core/src/user_list_core.dart';
|
import 'package:stream_chat_flutter_core/src/user_list_core.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
|
||||||
@@ -33,58 +33,6 @@ void main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case listBuilder is null',
|
|
||||||
() {
|
|
||||||
final userListCore = () => UserListCore(
|
|
||||||
listBuilder: null,
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: (Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(userListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case loadingBuilder is null',
|
|
||||||
() {
|
|
||||||
final userListCore = () => UserListCore(
|
|
||||||
listBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: null,
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: (Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(userListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case emptyBuilder is null',
|
|
||||||
() {
|
|
||||||
final userListCore = () => UserListCore(
|
|
||||||
listBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: null,
|
|
||||||
errorBuilder: (Object error) => Offstage(),
|
|
||||||
);
|
|
||||||
expect(userListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error in case errorBuilder is null',
|
|
||||||
() {
|
|
||||||
final userListCore = () => UserListCore(
|
|
||||||
listBuilder: (_, __) => Offstage(),
|
|
||||||
loadingBuilder: (BuildContext context) => Offstage(),
|
|
||||||
emptyBuilder: (BuildContext context) => Offstage(),
|
|
||||||
errorBuilder: null,
|
|
||||||
);
|
|
||||||
expect(userListCore, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'should throw if UserListCore is used where UsersBloc is not present '
|
'should throw if UserListCore is used where UsersBloc is not present '
|
||||||
'in the widget tree',
|
'in the widget tree',
|
||||||
@@ -183,12 +131,12 @@ void main() {
|
|||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
const error = 'Error! Error! Error!';
|
const error = 'Error! Error! Error!';
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -203,12 +151,12 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(errorWidgetKey), findsOneWidget);
|
expect(find.byKey(errorWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -228,12 +176,12 @@ void main() {
|
|||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
const users = <User>[];
|
const users = <User>[];
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -248,12 +196,12 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(emptyWidgetKey), findsOneWidget);
|
expect(find.byKey(emptyWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -273,12 +221,12 @@ void main() {
|
|||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final users = _generateUsers();
|
final users = _generateUsers();
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
StreamChatCore(
|
StreamChatCore(
|
||||||
@@ -293,12 +241,12 @@ void main() {
|
|||||||
|
|
||||||
expect(find.byKey(listWidgetKey), findsOneWidget);
|
expect(find.byKey(listWidgetKey), findsOneWidget);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -314,7 +262,7 @@ void main() {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
children: items.map((e) {
|
children: items.map((e) {
|
||||||
return Container(
|
return Container(
|
||||||
key: Key(e.key),
|
key: Key(e.key ?? ''),
|
||||||
child: e.when(
|
child: e.when(
|
||||||
headerItem: (heading) => Text(heading),
|
headerItem: (heading) => Text(heading),
|
||||||
userItem: (user) => Text(user.id),
|
userItem: (user) => Text(user.id),
|
||||||
@@ -332,12 +280,12 @@ void main() {
|
|||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final users = _generateUsers();
|
final users = _generateUsers();
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -359,12 +307,12 @@ void main() {
|
|||||||
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -382,7 +330,7 @@ void main() {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
children: items.map((e) {
|
children: items.map((e) {
|
||||||
return Container(
|
return Container(
|
||||||
key: Key(e.key),
|
key: Key(e.key ?? ''),
|
||||||
child: e.when(
|
child: e.when(
|
||||||
headerItem: (heading) => Text(heading),
|
headerItem: (heading) => Text(heading),
|
||||||
userItem: (user) => Text(user.id),
|
userItem: (user) => Text(user.id),
|
||||||
@@ -401,12 +349,12 @@ void main() {
|
|||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final users = _generateUsers();
|
final users = _generateUsers();
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -428,12 +376,12 @@ void main() {
|
|||||||
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final userListCoreState = tester.state<UserListCoreState>(
|
final userListCoreState = tester.state<UserListCoreState>(
|
||||||
find.byKey(userListCoreKey),
|
find.byKey(userListCoreKey),
|
||||||
@@ -442,12 +390,14 @@ void main() {
|
|||||||
final offset = users.length;
|
final offset = users.length;
|
||||||
final paginatedUsers = _generateUsers(offset: offset);
|
final paginatedUsers = _generateUsers(offset: offset);
|
||||||
final updatedPagination = pagination.copyWith(offset: offset);
|
final updatedPagination = pagination.copyWith(offset: offset);
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: updatedPagination,
|
pagination: updatedPagination,
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = paginatedUsers);
|
))
|
||||||
|
.thenAnswer(
|
||||||
|
(_) async => QueryUsersResponse()..users = paginatedUsers);
|
||||||
|
|
||||||
await userListCoreState.paginateData();
|
await userListCoreState.paginateData();
|
||||||
|
|
||||||
@@ -458,12 +408,12 @@ void main() {
|
|||||||
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: updatedPagination,
|
pagination: updatedPagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -473,7 +423,7 @@ void main() {
|
|||||||
(tester) async {
|
(tester) async {
|
||||||
const pagination = PaginationParams();
|
const pagination = PaginationParams();
|
||||||
|
|
||||||
StateSetter _stateSetter;
|
StateSetter? _stateSetter;
|
||||||
int limit = pagination.limit;
|
int limit = pagination.limit;
|
||||||
|
|
||||||
const userListCoreKey = Key('userListCore');
|
const userListCoreKey = Key('userListCore');
|
||||||
@@ -485,7 +435,7 @@ void main() {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
children: items.map((e) {
|
children: items.map((e) {
|
||||||
return Container(
|
return Container(
|
||||||
key: Key(e.key),
|
key: Key(e.key ?? ''),
|
||||||
child: e.when(
|
child: e.when(
|
||||||
headerItem: (heading) => Text(heading),
|
headerItem: (heading) => Text(heading),
|
||||||
userItem: (user) => Text(user.id),
|
userItem: (user) => Text(user.id),
|
||||||
@@ -504,12 +454,12 @@ void main() {
|
|||||||
final mockClient = MockClient();
|
final mockClient = MockClient();
|
||||||
|
|
||||||
final users = _generateUsers();
|
final users = _generateUsers();
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
@@ -535,24 +485,25 @@ void main() {
|
|||||||
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
// Rebuilding UserListCore with new pagination limit
|
// Rebuilding UserListCore with new pagination limit
|
||||||
_stateSetter(() => limit = 6);
|
_stateSetter?.call(() => limit = 6);
|
||||||
|
|
||||||
final updatedUsers = _generateUsers(count: limit);
|
final updatedUsers = _generateUsers(count: limit);
|
||||||
final updatedPagination = pagination.copyWith(limit: limit);
|
final updatedPagination = pagination.copyWith(limit: limit);
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: updatedPagination,
|
pagination: updatedPagination,
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = updatedUsers);
|
))
|
||||||
|
.thenAnswer((_) async => QueryUsersResponse()..users = updatedUsers);
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
@@ -561,12 +512,12 @@ void main() {
|
|||||||
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: updatedPagination,
|
pagination: updatedPagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:mocktail/mocktail.dart';
|
||||||
import 'package:stream_chat/stream_chat.dart';
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
import 'package:stream_chat_flutter_core/src/stream_chat_core.dart';
|
import 'package:stream_chat_flutter_core/src/stream_chat_core.dart';
|
||||||
import 'package:stream_chat_flutter_core/src/users_bloc.dart';
|
import 'package:stream_chat_flutter_core/src/users_bloc.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
|
||||||
|
|
||||||
import 'matchers/users_matcher.dart';
|
import 'matchers/users_matcher.dart';
|
||||||
import 'mocks.dart';
|
import 'mocks.dart';
|
||||||
@@ -31,18 +31,6 @@ void main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
|
||||||
'should throw assertion error if child is null',
|
|
||||||
() async {
|
|
||||||
const usersBlocKey = Key('usersBloc');
|
|
||||||
final usersBloc = () => UsersBloc(
|
|
||||||
key: usersBlocKey,
|
|
||||||
child: null,
|
|
||||||
);
|
|
||||||
expect(usersBloc, throwsA(isA<AssertionError>()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'usersBlocState.queryUsers() should throw if used where '
|
'usersBlocState.queryUsers() should throw if used where '
|
||||||
'StreamChat is not present in the widget tree',
|
'StreamChat is not present in the widget tree',
|
||||||
@@ -96,12 +84,12 @@ void main() {
|
|||||||
|
|
||||||
final users = _generateUsers();
|
final users = _generateUsers();
|
||||||
|
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
usersBlocState.queryUsers();
|
usersBlocState.queryUsers();
|
||||||
|
|
||||||
@@ -110,12 +98,12 @@ void main() {
|
|||||||
emits(isSameUserListAs(users)),
|
emits(isSameUserListAs(users)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -145,12 +133,12 @@ void main() {
|
|||||||
|
|
||||||
final error = 'Error! Error! Error!';
|
final error = 'Error! Error! Error!';
|
||||||
|
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
usersBlocState.queryUsers();
|
usersBlocState.queryUsers();
|
||||||
|
|
||||||
@@ -159,12 +147,12 @@ void main() {
|
|||||||
emitsError(error),
|
emitsError(error),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -195,12 +183,12 @@ void main() {
|
|||||||
|
|
||||||
final users = _generateUsers();
|
final users = _generateUsers();
|
||||||
|
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
usersBlocState.queryUsers();
|
usersBlocState.queryUsers();
|
||||||
|
|
||||||
@@ -209,23 +197,25 @@ void main() {
|
|||||||
emits(isSameUserListAs(users)),
|
emits(isSameUserListAs(users)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final offset = users.length;
|
final offset = users.length;
|
||||||
final paginatedUsers = _generateUsers(offset: offset);
|
final paginatedUsers = _generateUsers(offset: offset);
|
||||||
final pagination = PaginationParams(offset: offset);
|
final pagination = PaginationParams(offset: offset);
|
||||||
|
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: pagination,
|
pagination: pagination,
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = paginatedUsers);
|
))
|
||||||
|
.thenAnswer(
|
||||||
|
(_) async => QueryUsersResponse()..users = paginatedUsers);
|
||||||
|
|
||||||
usersBlocState.queryUsers(pagination: pagination);
|
usersBlocState.queryUsers(pagination: pagination);
|
||||||
|
|
||||||
@@ -240,12 +230,12 @@ void main() {
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: pagination,
|
pagination: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -276,12 +266,12 @@ void main() {
|
|||||||
|
|
||||||
final users = _generateUsers();
|
final users = _generateUsers();
|
||||||
|
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
|
||||||
|
|
||||||
usersBlocState.queryUsers();
|
usersBlocState.queryUsers();
|
||||||
|
|
||||||
@@ -290,24 +280,24 @@ void main() {
|
|||||||
emits(isSameUserListAs(users)),
|
emits(isSameUserListAs(users)),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: anyNamed('pagination'),
|
pagination: any(named: 'pagination'),
|
||||||
)).called(1);
|
)).called(1);
|
||||||
|
|
||||||
final offset = users.length;
|
final offset = users.length;
|
||||||
final pagination = PaginationParams(offset: offset);
|
final pagination = PaginationParams(offset: offset);
|
||||||
|
|
||||||
final error = 'Error! Error! Error!';
|
final error = 'Error! Error! Error!';
|
||||||
|
|
||||||
when(mockClient.queryUsers(
|
when(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: pagination,
|
pagination: pagination,
|
||||||
)).thenThrow(error);
|
)).thenThrow(error);
|
||||||
|
|
||||||
usersBlocState.queryUsers(pagination: pagination);
|
usersBlocState.queryUsers(pagination: pagination);
|
||||||
|
|
||||||
@@ -316,12 +306,12 @@ void main() {
|
|||||||
emitsError(error),
|
emitsError(error),
|
||||||
);
|
);
|
||||||
|
|
||||||
verify(mockClient.queryUsers(
|
verify(() => mockClient.queryUsers(
|
||||||
filter: anyNamed('filter'),
|
filter: any(named: 'filter'),
|
||||||
sort: anyNamed('sort'),
|
sort: any(named: 'sort'),
|
||||||
options: anyNamed('options'),
|
options: any(named: 'options'),
|
||||||
pagination: pagination,
|
pagination: pagination,
|
||||||
)).called(1);
|
)).called(1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user