added non-nullability for core

This commit is contained in:
Deven Joshi
2021-04-20 10:35:40 +02:00
committed by Salvatore Giordano
parent 228778f2b1
commit 74fb9d8dd8
16 changed files with 185 additions and 181 deletions
@@ -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,
@@ -91,7 +91,7 @@ class ChannelListCore extends StatefulWidget {
/// 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;
@@ -100,7 +100,7 @@ class ChannelListCore extends StatefulWidget {
final WidgetBuilder loadingBuilder; final WidgetBuilder loadingBuilder;
/// The builder which is used when list of channels loads /// The builder which is used when list of channels loads
final Function(BuildContext, List<Channel>) listBuilder; final Function(BuildContext, List<Channel?>) listBuilder;
/// The builder used when the channel list is empty. /// The builder used when the channel list is empty.
final WidgetBuilder emptyBuilder; final WidgetBuilder emptyBuilder;
@@ -108,20 +108,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)
@@ -142,10 +142,10 @@ class ChannelListCoreState extends State<ChannelListCore> {
return _buildListView(channelsBloc); return _buildListView(channelsBloc);
} }
StreamBuilder<List<Channel>> _buildListView( StreamBuilder<List<Channel?>> _buildListView(
ChannelsBlocState channelsBlocState, ChannelsBlocState channelsBlocState,
) => ) =>
StreamBuilder<List<Channel>>( StreamBuilder<List<Channel?>>(
stream: channelsBlocState.channelsStream, stream: channelsBlocState.channelsStream,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
@@ -154,7 +154,7 @@ class ChannelListCoreState extends State<ChannelListCore> {
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 +186,7 @@ class ChannelListCoreState extends State<ChannelListCore> {
); );
} }
StreamSubscription<Event> _subscription; late StreamSubscription<Event> _subscription;
@override @override
void initState() { void initState() {
@@ -203,8 +203,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;
} }
} }
@@ -233,10 +233,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,8 +20,8 @@ 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,
@@ -36,18 +36,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 +69,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 as List<Channel>?;
/// 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 +89,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,
Map<String, dynamic> options, Map<String, dynamic>? options,
}) async { }) async {
final client = StreamChatCore.of(context).client; final client = StreamChatCore.of(context).client;
@@ -110,10 +111,10 @@ class ChannelsBlocState extends State<ChannelsBloc>
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(
filter: filter, filter: filter!,
sort: sortOptions, sort: sortOptions!,
options: options, options: options!,
paginationParams: paginationParams, paginationParams: paginationParams!,
)) { )) {
newChannels = channels; newChannels = channels;
if (clear) { if (clear) {
@@ -123,7 +124,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);
} }
} }
@@ -149,8 +150,8 @@ class ChannelsBlocState extends State<ChannelsBloc>
if (!widget.lockChannelsOrder) { if (!widget.lockChannelsOrder) {
_subscriptions.add(client.on(EventType.messageNew).listen((e) { _subscriptions.add(client.on(EventType.messageNew).listen((e) {
final newChannels = List<Channel>.from(channels ?? []); final newChannels = List<Channel?>.from(channels ?? []);
final index = newChannels.indexWhere((c) => c.cid == e.cid); final index = newChannels.indexWhere((c) => c!.cid == e.cid);
if (index != -1) { if (index != -1) {
if (index > 0) { if (index > 0) {
final channel = newChannels.removeAt(index); final channel = newChannels.removeAt(index);
@@ -9,8 +9,8 @@ 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,
@@ -24,19 +24,19 @@ class LazyLoadScrollView extends StatefulWidget {
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;
@@ -59,13 +59,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;
} }
} }
@@ -78,7 +78,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
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;
} }
} }
@@ -117,7 +117,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) { if (_loadMoreStatus != null && _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;
}); });
} }
@@ -128,7 +128,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) { if (_loadMoreStatus != null && _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,11 +61,11 @@ 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,
@@ -84,7 +84,7 @@ class MessageListCore extends StatefulWidget {
/// 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 +108,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,7 +119,7 @@ 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;
@@ -133,8 +133,8 @@ class MessageListCoreState extends State<MessageListCore> {
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) {
@@ -144,7 +144,7 @@ class MessageListCoreState extends State<MessageListCore> {
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()),
builder: (context, snapshot) { builder: (context, snapshot) {
@@ -171,11 +171,11 @@ class MessageListCoreState extends State<MessageListCore> {
/// ///
/// Optionally pass the fetch direction, defaults to [QueryDirection.bottom] /// Optionally pass the fetch direction, defaults to [QueryDirection.bottom]
Future<void> paginateData( Future<void> paginateData(
{QueryDirection direction = QueryDirection.bottom}) { {QueryDirection? direction = QueryDirection.bottom}) {
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 +184,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 +206,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,9 +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.'), }) : assert(child != null, 'Parameter child should not be null.'),
super(key: key); super(key: key);
/// The widget child /// The widget child
@@ -26,7 +26,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 +42,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 +59,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, 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;
@@ -80,11 +80,11 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
final oldMessages = List<GetMessageResponse>.from(messageResponses ?? []); final oldMessages = List<GetMessageResponse>.from(messageResponses ?? []);
final messages = await client.search( final messages = await client.search(
filter, filter!,
sort: sort, sort: sort!,
query: query, query: query!,
paginationParams: pagination, paginationParams: pagination!,
messageFilters: messageFilter, messageFilters: messageFilter!,
); );
if (clear) { if (clear) {
@@ -93,7 +93,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,11 +42,11 @@ 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,
this.messageQuery, this.messageQuery,
this.filters, this.filters,
this.sortOptions, this.sortOptions,
@@ -63,36 +63,36 @@ class MessageSearchListCore extends StatefulWidget {
/// 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].
/// You can also filter other built-in channel fields. /// You can also filter other built-in channel fields.
final Map<String, dynamic> filters; final Map<String, dynamic>? filters;
/// 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> 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;
/// The builder used when the channel list is empty. /// The builder used when the channel list is empty.
final WidgetBuilder emptyBuilder; final WidgetBuilder emptyBuilder;
@@ -114,8 +114,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;
} }
} }
@@ -135,7 +135,7 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
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);
} }
@@ -161,7 +161,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,
@@ -187,8 +187,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' show IterableExtension;
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,9 +22,9 @@ 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'), }) : assert(child != null, 'Child should not be null'),
@@ -40,11 +41,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,7 +68,7 @@ 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 =>
@@ -146,7 +147,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 +158,12 @@ 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!) 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;
} }
@@ -202,7 +203,7 @@ class StreamChannelState extends State<StreamChannel> {
/// 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,13 +215,13 @@ 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();
@@ -232,7 +233,7 @@ 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([
@@ -284,9 +285,8 @@ class StreamChannelState extends State<StreamChannel> {
/// ///
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 +298,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 +358,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,9 +38,9 @@ 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'), }) : assert(client != null, 'Stream Chat Client should not be null'),
@@ -61,14 +61,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 +87,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 +119,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 +139,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();
@@ -4,7 +4,7 @@ import 'package:stream_chat/stream_chat.dart';
/// A signature for a callback which exposes an error and returns a function. /// A signature for a callback which exposes an error and returns a function.
/// This Callback can be used in cases where an API failure occurs and the /// This Callback can be used in cases where an API failure occurs and the
/// widget is unable to render data. /// widget is unable to render data.
typedef ErrorBuilder = Widget Function(BuildContext context, Object error); typedef ErrorBuilder = Widget Function(BuildContext context, Object? error);
/// A Signature for a handler function which will expose a [event]. /// A Signature for a handler function which will expose a [event].
typedef EventHandler = void Function(Event event); typedef EventHandler = void Function(Event event);
@@ -57,11 +57,11 @@ 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,
@@ -77,10 +77,10 @@ class UserListCore extends StatefulWidget {
/// 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;
/// The builder that will be used to build the list /// The builder that will be used to build the list
final Widget Function(BuildContext context, List<ListItem> users) listBuilder; final Widget Function(BuildContext context, List<ListItem> users) listBuilder;
@@ -94,25 +94,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 +131,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 +158,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;
} }
@@ -185,7 +185,7 @@ class UserListCoreState extends State<UserListCore>
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 +210,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,
@@ -235,7 +235,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 +250,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 +259,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 +284,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,8 +14,8 @@ 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( }) : assert(
child != null, child != null,
'When constructing a UsersBloc, the parameter ' 'When constructing a UsersBloc, the parameter '
@@ -30,7 +30,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 +46,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 +62,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;
@@ -83,10 +83,10 @@ class UsersBlocState extends State<UsersBloc>
final oldUsers = List<User>.from(users ?? []); final oldUsers = List<User>.from(users ?? []);
final usersResponse = await client.queryUsers( final usersResponse = await client.queryUsers(
filter: filter, filter: filter!,
sort: sort, sort: sort!,
options: options, options: options!,
pagination: pagination, pagination: pagination!,
); );
if (clear) { if (clear) {
@@ -95,7 +95,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,7 +8,7 @@ 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:
@@ -17,14 +17,15 @@ dependencies:
meta: ^1.2.4 meta: ^1.2.4
rxdart: ^0.26.0 rxdart: ^0.26.0
stream_chat: ^1.5.0 stream_chat: ^1.5.0
collection: ^1.15.0-nullsafety.4
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 mockito: ^5.0.3
@@ -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;
@@ -7,7 +7,7 @@ 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, ''); }) : assert(targetResponse != null, '');
final GetMessageResponse targetResponse; final GetMessageResponse targetResponse;
@@ -28,7 +28,7 @@ Matcher isSameMessageResponseListAs(
class _IsSameMessageResponseListAs extends Matcher { class _IsSameMessageResponseListAs extends Matcher {
const _IsSameMessageResponseListAs({ const _IsSameMessageResponseListAs({
@required this.targetResponseList, required this.targetResponseList,
}) : assert(targetResponseList != null, ''); }) : assert(targetResponseList != null, '');
final List<GetMessageResponse> targetResponseList; final List<GetMessageResponse> targetResponseList;
@@ -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;