migrate code

This commit is contained in:
Salvatore Giordano
2021-04-20 12:44:11 +02:00
parent 34f2539595
commit 987da10cba
25 changed files with 986 additions and 1264 deletions
@@ -69,23 +69,7 @@ class ChannelListCore extends StatefulWidget {
limit: 25,
),
this.channelListController,
}) : assert(
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);
}) : super(key: key);
/// A [ChannelListController] allows reloading and pagination.
/// Use [ChannelListController.loadData] and
@@ -100,7 +84,7 @@ class ChannelListCore extends StatefulWidget {
final WidgetBuilder loadingBuilder;
/// 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.
final WidgetBuilder emptyBuilder;
@@ -142,14 +126,14 @@ class ChannelListCoreState extends State<ChannelListCore> {
return _buildListView(channelsBloc);
}
StreamBuilder<List<Channel?>> _buildListView(
StreamBuilder<List<Channel>> _buildListView(
ChannelsBlocState channelsBlocState,
) =>
StreamBuilder<List<Channel?>>(
StreamBuilder<List<Channel>>(
stream: channelsBlocState.channelsStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return widget.errorBuilder(context, snapshot.error);
return widget.errorBuilder(context, snapshot.error!);
}
if (!snapshot.hasData) {
return widget.loadingBuilder(context);
@@ -215,8 +199,8 @@ class ChannelListCoreState extends State<ChannelListCore> {
if (widget.filter?.toString() != oldWidget.filter?.toString() ||
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
widget.options?.toString() != oldWidget.options?.toString() ||
widget.pagination?.toJson()?.toString() !=
oldWidget.pagination?.toJson()?.toString()) {
widget.pagination.toJson().toString() !=
oldWidget.pagination.toJson().toString()) {
loadData();
}
}
@@ -35,7 +35,7 @@ class ChannelsBloc extends StatefulWidget {
final bool lockChannelsOrder;
/// 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
/// message.new event is received
@@ -68,14 +68,14 @@ class ChannelsBlocState extends State<ChannelsBloc>
}
/// The current channel list
List<Channel>? get channels => _channelsController.value as List<Channel>?;
List<Channel>? get channels => _channelsController.value;
/// 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 BehaviorSubject<List<Channel?>> _channelsController =
final BehaviorSubject<List<Channel>> _channelsController =
BehaviorSubject<List<Channel>>();
/// The stream notifying the state of queryChannel call
@@ -90,7 +90,7 @@ class ChannelsBlocState extends State<ChannelsBloc>
Future<void> queryChannels({
Map<String, dynamic>? filter,
List<SortOption<ChannelModel>>? sortOptions,
PaginationParams? paginationParams,
PaginationParams paginationParams = const PaginationParams(limit: 30),
Map<String, dynamic>? options,
}) async {
final client = StreamChatCore.of(context).client;
@@ -104,14 +104,14 @@ class ChannelsBlocState extends State<ChannelsBloc>
}
try {
final clear = paginationParams == null || paginationParams.offset == 0;
final clear = paginationParams.offset == 0;
final oldChannels = List<Channel>.from(channels ?? []);
var newChannels = <Channel>[];
await for (final channels in client.queryChannels(
filter: filter!,
sort: sortOptions!,
options: options!,
paginationParams: paginationParams!,
filter: filter,
sort: sortOptions,
options: options,
paginationParams: paginationParams,
)) {
newChannels = channels;
if (clear) {
@@ -147,8 +147,8 @@ class ChannelsBlocState extends State<ChannelsBloc>
if (!widget.lockChannelsOrder) {
_subscriptions.add(client.on(EventType.messageNew).listen((e) {
final newChannels = List<Channel?>.from(channels ?? []);
final index = newChannels.indexWhere((c) => c!.cid == e.cid);
final newChannels = List<Channel>.from(channels ?? []);
final index = newChannels.indexWhere((c) => c.cid == e.cid);
if (index != -1) {
if (index > 0) {
final channel = newChannels.removeAt(index);
@@ -162,7 +162,7 @@ class ChannelsBlocState extends State<ChannelsBloc>
} else {
if (client.state.channels != null &&
client.state.channels?[e.cid] != null) {
newChannels.insert(0, client.state.channels?[e.cid]);
newChannels.insert(0, client.state.channels![e.cid]!);
}
}
}
@@ -17,8 +17,7 @@ class LazyLoadScrollView extends StatefulWidget {
this.onPageScrollEnd,
this.onInBetweenOfPage,
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
final Widget child;
@@ -46,7 +45,7 @@ class LazyLoadScrollView extends StatefulWidget {
}
class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
_LoadingStatus _loadMoreStatus = _LoadingStatus.stable;
var _loadMoreStatus = _LoadingStatus.stable;
double _scrollPosition = 0;
@override
@@ -73,7 +72,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
final pixels = notification.metrics.pixels;
final maxScrollExtent = notification.metrics.maxScrollExtent;
final minScrollExtent = notification.metrics.minScrollExtent;
final scrollOffset = widget.scrollOffset ?? 0;
final scrollOffset = widget.scrollOffset;
if (pixels > (minScrollExtent + scrollOffset) &&
pixels < (maxScrollExtent - scrollOffset)) {
@@ -114,7 +113,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
}
void _onEndOfPage() {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) {
if (_loadMoreStatus == _LoadingStatus.stable) {
if (widget.onEndOfPage != null) {
_loadMoreStatus = _LoadingStatus.loading;
widget.onEndOfPage!().whenComplete(() {
@@ -125,7 +124,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
}
void _onStartOfPage() {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) {
if (_loadMoreStatus == _LoadingStatus.stable) {
if (widget.onStartOfPage != null) {
_loadMoreStatus = _LoadingStatus.loading;
widget.onStartOfPage!().whenComplete(() {
@@ -111,18 +111,18 @@ class MessageListCore extends StatefulWidget {
class MessageListCoreState extends State<MessageListCore> {
late StreamChannelState _streamChannel;
bool get _upToDate => _streamChannel.channel.state.isUpToDate;
bool get _upToDate => _streamChannel.channel.state?.isUpToDate ?? true;
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>[];
@override
Widget build(BuildContext context) {
final messagesStream = _isThreadConversation
? _streamChannel.channel.state.threadsStream
? _streamChannel.channel.state?.threadsStream
.where((threads) => threads.containsKey(widget.parentMessage!.id))
.map((threads) => threads[widget.parentMessage!.id])
: _streamChannel.channel.state?.messagesStream;
@@ -141,7 +141,7 @@ class MessageListCoreState extends State<MessageListCore> {
)),
builder: (context, snapshot) {
if (snapshot.hasError) {
return widget.errorWidgetBuilder(context, snapshot.error);
return widget.errorWidgetBuilder(context, snapshot.error!);
} else if (!snapshot.hasData) {
return widget.loadingBuilder(context);
} else {
@@ -163,8 +163,9 @@ class MessageListCoreState extends State<MessageListCore> {
/// Fetches more messages with updated pagination and updates the widget.
///
/// Optionally pass the fetch direction, defaults to [QueryDirection.bottom]
Future<void> paginateData(
{QueryDirection? direction = QueryDirection.bottom}) {
Future<void> paginateData({
QueryDirection direction = QueryDirection.bottom,
}) {
if (!_isThreadConversation) {
return _streamChannel.queryMessages(direction: direction);
} else {
@@ -199,5 +200,5 @@ class MessageListCoreState extends State<MessageListCore> {
/// Controller used for paginating data in [ChannelListView]
class MessageListController {
/// Call this function to load further data
Future<void> Function({QueryDirection? direction})? paginateData;
Future<void> Function({QueryDirection direction})? paginateData;
}
@@ -58,7 +58,7 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
/// Calls [StreamChatClient.search] updating
/// [messagesStream] and [queryMessagesLoading] stream
Future<void> search({
Map<String, dynamic>? filter,
required Map<String, dynamic> filter,
Map<String, dynamic>? messageFilter,
List<SortOption>? sort,
String? query,
@@ -77,20 +77,18 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
final oldMessages = List<GetMessageResponse>.from(messageResponses ?? []);
final messages = await client.search(
filter!,
sort: sort!,
query: query!,
paginationParams: pagination!,
messageFilters: messageFilter!,
filter,
sort: sort,
query: query,
paginationParams: pagination,
messageFilters: messageFilter,
);
if (messages.results != null) {
if (clear) {
_messageResponses.add(messages.results!);
} else {
final temp = oldMessages + messages.results!;
_messageResponses.add(temp);
}
if (clear) {
_messageResponses.add(messages.results);
} else {
final temp = oldMessages + messages.results;
_messageResponses.add(temp);
}
if (_messageResponses.hasValue &&
_queryMessagesLoadingController.value!) {
@@ -47,17 +47,13 @@ class MessageSearchListCore extends StatefulWidget {
required this.errorBuilder,
required this.loadingBuilder,
required this.childBuilder,
required this.filters,
this.messageQuery,
this.filters,
this.sortOptions,
this.paginationParams,
this.messageFilters,
this.messageSearchListController,
}) : assert(emptyBuilder != null, 'emptyBuilder should not be null'),
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);
}) : super(key: key);
/// A [MessageSearchListController] allows reloading and pagination.
/// Use [MessageSearchListController.loadData] and
@@ -71,7 +67,7 @@ class MessageSearchListCore extends StatefulWidget {
/// The query filters to use.
/// You can query on any of the custom fields you've defined on the [Channel].
/// 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.
/// Sorting is based on field and direction, multiple sorting options can be
@@ -92,7 +88,7 @@ class MessageSearchListCore extends StatefulWidget {
final Map<String, dynamic>? messageFilters;
/// 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.
final WidgetBuilder emptyBuilder;
@@ -130,7 +126,7 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
stream: messageSearchBloc.messagesStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return widget.errorBuilder(context, snapshot.error);
return widget.errorBuilder(context, snapshot.error!);
}
if (!snapshot.hasData) {
return widget.loadingBuilder(context);
@@ -139,7 +135,7 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
if (items.isEmpty) {
return widget.emptyBuilder(context);
}
return widget.childBuilder(snapshot.data);
return widget.childBuilder(items);
},
);
@@ -172,13 +168,13 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
@override
void didUpdateWidget(MessageSearchListCore oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.filters?.toString() != oldWidget.filters?.toString() ||
if (widget.filters.toString() != oldWidget.filters.toString() ||
jsonEncode(widget.sortOptions) != jsonEncode(oldWidget.sortOptions) ||
widget.messageQuery?.toString() != oldWidget.messageQuery?.toString() ||
widget.messageFilters?.toString() !=
oldWidget.messageFilters?.toString() ||
widget.paginationParams?.toJson()?.toString() !=
oldWidget.paginationParams?.toJson()?.toString()) {
widget.paginationParams?.toJson().toString() !=
oldWidget.paginationParams?.toJson().toString()) {
loadData();
}
}
@@ -1,5 +1,6 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
@@ -28,7 +29,7 @@ class StreamChannel extends StatefulWidget {
this.initialMessageId,
}) : super(key: key);
// ignore: public_member_api_docs
/// The child of the widget
final Widget child;
/// [channel] specifies the channel with which child should be wrapped
@@ -68,8 +69,8 @@ class StreamChannelState extends State<StreamChannel> {
String? get initialMessageId => widget.initialMessageId;
/// Current channel state stream
Stream<ChannelState> get channelStateStream =>
widget.channel.state.channelStateStream;
Stream<ChannelState>? get channelStateStream =>
widget.channel.state?.channelStateStream;
final _queryTopMessagesController = BehaviorSubject.seeded(false);
final _queryBottomMessagesController = BehaviorSubject.seeded(false);
@@ -87,16 +88,18 @@ class StreamChannelState extends State<StreamChannel> {
int limit = 20,
bool preferOffline = false,
}) async {
if (_topPaginationEnded || _queryTopMessagesController?.value == true) {
if (_topPaginationEnded ||
_queryTopMessagesController.value == true ||
channel.state == null) {
return;
}
_queryTopMessagesController.add(true);
if (channel.state.messages.isEmpty) {
if (channel.state!.messages.isEmpty) {
return _queryTopMessagesController.add(false);
}
final oldestMessage = channel.state.messages.first;
final oldestMessage = channel.state!.messages.first;
try {
final state = await queryBeforeMessage(
@@ -118,15 +121,16 @@ class StreamChannelState extends State<StreamChannel> {
bool preferOffline = false,
}) async {
if (_bottomPaginationEnded ||
_queryBottomMessagesController?.value == true ||
channel?.state?.isUpToDate == true) return;
_queryBottomMessagesController.value == true ||
channel.state == null ||
channel.state!.isUpToDate == true) return;
_queryBottomMessagesController.add(true);
if (channel.state.messages.isEmpty) {
if (channel.state!.messages.isEmpty) {
return _queryBottomMessagesController.add(false);
}
final recentMessage = channel.state.messages.last;
final recentMessage = channel.state!.messages.last;
try {
final state = await queryAfterMessage(
@@ -155,12 +159,14 @@ class StreamChannelState extends State<StreamChannel> {
int limit = 50,
bool preferOffline = false,
}) async {
if (_topPaginationEnded || _queryTopMessagesController.value!) return;
if (_topPaginationEnded ||
_queryTopMessagesController.value! ||
channel.state == null) return;
_queryTopMessagesController.add(true);
late Message message;
if (channel.state.threads.containsKey(parentId)) {
final thread = channel.state.threads[parentId]!;
if (channel.state!.threads.containsKey(parentId)) {
final thread = channel.state!.threads[parentId]!;
if (thread.isNotEmpty) {
message = thread.first;
}
@@ -170,7 +176,7 @@ class StreamChannelState extends State<StreamChannel> {
final response = await channel.getReplies(
parentId,
PaginationParams(
lessThan: message?.id,
lessThan: message.id,
limit: limit,
),
preferOffline: preferOffline,
@@ -224,8 +230,8 @@ class StreamChannelState extends State<StreamChannel> {
bool preferOffline = false,
}) async {
if (channel.state == null) return [];
channel.state.isUpToDate = false;
channel.state.truncate();
channel.state!.isUpToDate = false;
channel.state!.truncate();
if (messageId == null) {
await channel.query(
@@ -234,7 +240,7 @@ class StreamChannelState extends State<StreamChannel> {
),
preferOffline: preferOffline,
);
channel.state.isUpToDate = true;
channel.state!.isUpToDate = true;
return [];
}
@@ -280,14 +286,14 @@ class StreamChannelState extends State<StreamChannel> {
preferOffline: preferOffline,
);
if (state.messages.isEmpty || state.messages.length < limit) {
channel.state.isUpToDate = true;
channel.state?.isUpToDate = true;
}
return state;
}
///
Future<Message> getMessage(String messageId) async {
var message = channel.state.messages.firstWhereOrNull(
var message = channel.state?.messages.firstWhereOrNull(
(it) => it.id == messageId,
);
if (message == null) {
@@ -43,9 +43,7 @@ class StreamChatCore extends StatefulWidget {
required this.child,
this.onBackgroundEventReceived,
this.backgroundKeepAlive = const Duration(minutes: 1),
}) : assert(client != null, 'Stream Chat Client should not be null'),
assert(child != null, 'Child should not be null'),
super(key: key);
}) : super(key: key);
/// Instance of Stream Chat Client containing information about the current
/// application.
@@ -93,15 +91,15 @@ class StreamChatCoreState extends State<StreamChatCore>
Widget build(BuildContext context) => widget.child;
/// The current user
User? get user => client.state?.user;
User? get user => client.state.user;
/// The current user as a stream
Stream<User>? get userStream => client.state?.userStream;
Stream<User?> get userStream => client.state.userStream;
@override
void initState() {
super.initState();
WidgetsBinding.instance!.addObserver(this);
WidgetsBinding.instance?.addObserver(this);
}
StreamSubscription? _eventSubscription;
@@ -119,15 +117,15 @@ class StreamChatCoreState extends State<StreamChatCore>
);
void onTimerComplete() {
_eventSubscription!.cancel();
_eventSubscription?.cancel();
client.disconnect();
}
_disconnectTimer = Timer(widget.backgroundKeepAlive, onTimerComplete);
} else if (state == AppLifecycleState.resumed) {
if (_disconnectTimer?.isActive == true) {
_eventSubscription!.cancel();
_disconnectTimer!.cancel();
_eventSubscription?.cancel();
_disconnectTimer?.cancel();
} else {
if (client.wsConnectionStatus == ConnectionStatus.disconnected) {
client.connect();
@@ -139,7 +137,7 @@ class StreamChatCoreState extends State<StreamChatCore>
@override
void dispose() {
WidgetsBinding.instance!.removeObserver(this);
WidgetsBinding.instance?.removeObserver(this);
_eventSubscription?.cancel();
_disconnectTimer?.cancel();
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.
/// This Callback can be used in cases where an API failure occurs and the
/// 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].
typedef EventHandler = void Function(Event event);
@@ -68,11 +68,7 @@ class UserListCore extends StatefulWidget {
this.pagination,
this.groupAlphabetically = false,
this.userListController,
}) : assert(errorBuilder != null, ''),
assert(emptyBuilder != null, ''),
assert(loadingBuilder != null, ''),
assert(listBuilder != null, ''),
super(key: key);
}) : super(key: key);
/// A [UserListController] allows reloading and pagination.
/// Use [UserListController.loadData] and [UserListController.paginateData]
@@ -80,7 +76,7 @@ class UserListCore extends StatefulWidget {
final UserListController? userListController;
/// 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
final Widget Function(BuildContext context, List<ListItem> users) listBuilder;
@@ -180,7 +176,7 @@ class UserListCoreState extends State<UserListCore>
stream: _buildUserStream(usersBlocState),
builder: (context, snapshot) {
if (snapshot.hasError) {
return widget.errorBuilder(snapshot.error);
return widget.errorBuilder(snapshot.error!);
}
if (!snapshot.hasData) {
return widget.loadingBuilder(context);
@@ -223,8 +219,8 @@ class UserListCoreState extends State<UserListCore>
if (widget.filter?.toString() != oldWidget.filter?.toString() ||
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
widget.options?.toString() != oldWidget.options?.toString() ||
widget.pagination?.toJson()?.toString() !=
oldWidget.pagination?.toJson()?.toString()) {
widget.pagination?.toJson().toString() !=
oldWidget.pagination?.toJson().toString()) {
loadData();
}
}
@@ -16,11 +16,7 @@ class UsersBloc extends StatefulWidget {
const UsersBloc({
required this.child,
Key? key,
}) : assert(
child != null,
'When constructing a UsersBloc, the parameter '
'child should not be null.'),
super(key: key);
}) : super(key: key);
/// The widget child
final Widget child;
@@ -76,17 +72,15 @@ class UsersBlocState extends State<UsersBloc>
}
try {
final clear = pagination == null ||
pagination.offset == null ||
pagination.offset == 0;
final clear = pagination == null || pagination.offset == 0;
final oldUsers = List<User>.from(users ?? []);
final usersResponse = await client.queryUsers(
filter: filter!,
sort: sort!,
options: options!,
pagination: pagination!,
filter: filter,
sort: sort,
options: options,
pagination: pagination,
);
if (clear) {