diff --git a/packages/stream_chat_flutter/lib/src/message_list_view.dart b/packages/stream_chat_flutter/lib/src/message_list_view.dart index 7435a11b..e8f8cdbc 100644 --- a/packages/stream_chat_flutter/lib/src/message_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/message_list_view.dart @@ -274,15 +274,15 @@ class _MessageListViewState extends State { bool _showScrollToBottom = false; late final ItemPositionsListener _itemPositionListener; int? _messageListLength; - late StreamChannelState streamChannel; + StreamChannelState? streamChannel; int? get _initialIndex { if (widget.initialScrollIndex != null) return widget.initialScrollIndex; - if (streamChannel.initialMessageId != null) { - final messages = streamChannel.channel.state!.messages; + if (streamChannel!.initialMessageId != null) { + final messages = streamChannel!.channel.state!.messages; final totalMessages = messages.length; final messageIndex = - messages.indexWhere((e) => e.id == streamChannel.initialMessageId); + messages.indexWhere((e) => e.id == streamChannel!.initialMessageId); final index = totalMessages - messageIndex; if (index != 0) return index - 1; return index; @@ -295,9 +295,9 @@ class _MessageListViewState extends State { return 0; } - bool _isInitialMessage(String id) => streamChannel.initialMessageId == id; + bool _isInitialMessage(String id) => streamChannel!.initialMessageId == id; - bool get _upToDate => streamChannel.channel.state!.isUpToDate; + bool get _upToDate => streamChannel!.channel.state!.isUpToDate; bool get _isThreadConversation => widget.parentMessage != null; @@ -506,13 +506,13 @@ class _MessageListViewState extends State { } if (i == messages.length + 1) { return _buildLoadingIndicator( - streamChannel, + streamChannel!, QueryDirection.top, ); } if (i == 0) { return _buildLoadingIndicator( - streamChannel, + streamChannel!, QueryDirection.bottom, ); } @@ -525,7 +525,7 @@ class _MessageListViewState extends State { context, message, messages, - streamChannel, + streamChannel!, ); } else if (i == messages.length - 1) { messageWidget = _buildTopMessage( @@ -605,8 +605,8 @@ class _MessageListViewState extends State { Widget _buildScrollToBottom() => StreamBuilder>( stream: Rx.combineLatest2( - streamChannel.channel.state!.isUpToDateStream, - streamChannel.channel.state!.unreadCountStream, + streamChannel!.channel.state!.isUpToDateStream, + streamChannel!.channel.state!.unreadCountStream, (bool isUpToDate, int unreadCount) => Tuple2(isUpToDate, unreadCount), ), builder: (_, snapshot) { @@ -622,8 +622,8 @@ class _MessageListViewState extends State { } final unreadCount = snapshot.data!.item2; final showUnreadCount = unreadCount > 0 && - streamChannel.channel.state!.members.any((e) => - e.userId == streamChannel.channel.client.state.user!.id); + streamChannel!.channel.state!.members.any((e) => + e.userId == streamChannel!.channel.client.state.user!.id); final chatThemeData = StreamChatTheme.of(context); return Positioned( bottom: 8, @@ -637,12 +637,12 @@ class _MessageListViewState extends State { backgroundColor: chatThemeData.colorTheme.white, onPressed: () { if (unreadCount > 0) { - streamChannel.channel.markRead(); + streamChannel!.channel.markRead(); } if (!_upToDate) { _bottomPaginationActive = false; _topPaginationActive = false; - streamChannel.reloadChannel(); + streamChannel!.reloadChannel(); } else { setState(() => _showScrollToBottom = false); _scrollController!.scrollTo( @@ -888,7 +888,7 @@ class _MessageListViewState extends State { ); } - final channel = streamChannel.channel; + final channel = streamChannel!.channel; final readList = channel.state?.read?.where((read) { if (read.user.id == userId) return false; return read.lastRead.isAfter(message.createdAt) || @@ -962,7 +962,7 @@ class _MessageListViewState extends State { if (messages.map((e) => e.id).contains(quotedMessageId)) { scrollToIndex(); } else { - await streamChannel.loadChannelAtMessage(quotedMessageId).then((_) { + await streamChannel!.loadChannelAtMessage(quotedMessageId).then((_) { WidgetsBinding.instance!.addPostFrameCallback((_) { if (messages.map((e) => e.id).contains(quotedMessageId)) { scrollToIndex(); @@ -1093,20 +1093,22 @@ class _MessageListViewState extends State { @override void didChangeDependencies() { - streamChannel = StreamChannel.of(context); + final newStreamChannel = StreamChannel.of(context); - if (_messageNewListener == null) { + if (newStreamChannel != streamChannel) { + streamChannel = newStreamChannel; + _messageNewListener?.cancel(); initialIndex = _initialIndex; initialAlignment = _initialAlignment; _messageNewListener = - streamChannel.channel.on(EventType.messageNew).listen((event) { + streamChannel!.channel.on(EventType.messageNew).listen((event) { if (_upToDate) { _bottomPaginationActive = false; _topPaginationActive = false; } if (event.message!.user!.id == - streamChannel.channel.client.state.user!.id) { + streamChannel!.channel.client.state.user!.id) { WidgetsBinding.instance!.addPostFrameCallback((_) { _scrollController?.jumpTo( index: 0, @@ -1116,9 +1118,10 @@ class _MessageListViewState extends State { }); if (_isThreadConversation) { - streamChannel.getReplies(widget.parentMessage!.id); + streamChannel!.getReplies(widget.parentMessage!.id); } } + super.didChangeDependencies(); } @@ -1137,12 +1140,12 @@ class _MessageListViewState extends State { context, MaterialPageRoute( builder: (_) => StreamBuilder( - stream: streamChannel.channel.state!.messagesStream.map( + stream: streamChannel!.channel.state!.messagesStream.map( (messages) => messages!.firstWhere((m) => m.id == message.id)), initialData: message, builder: (_, snapshot) => StreamChannel( - channel: streamChannel.channel, + channel: streamChannel!.channel, child: widget.threadBuilder!(context, snapshot.data), ), ), @@ -1155,7 +1158,7 @@ class _MessageListViewState extends State { @override void dispose() { if (!_upToDate) { - streamChannel.reloadChannel(); + streamChannel!.reloadChannel(); } _messageNewListener?.cancel(); super.dispose(); diff --git a/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart b/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart index 084ee20f..a3be273d 100644 --- a/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/channel_list_core.dart @@ -120,7 +120,7 @@ class ChannelListCore extends StatefulWidget { /// The current state of the [ChannelListCore]. class ChannelListCoreState extends State { late ChannelsBlocState _channelsBloc; - late StreamChatCoreState _streamChatCoreState; + StreamChatCoreState? _streamChatCoreState; @override Widget build(BuildContext context) => _buildListView(_channelsBloc); @@ -174,11 +174,13 @@ class ChannelListCoreState extends State { @override void didChangeDependencies() { _channelsBloc = ChannelsBloc.of(context); - _streamChatCoreState = StreamChatCore.of(context); + final newStreamChatCoreState = StreamChatCore.of(context); - if (_subscription == null) { + if (newStreamChatCoreState != _streamChatCoreState) { + _streamChatCoreState = newStreamChatCoreState; loadData(); - final client = _streamChatCoreState.client; + final client = _streamChatCoreState!.client; + _subscription?.cancel(); _subscription = client .on( EventType.connectionRecovered, diff --git a/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart b/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart index b23b9fc4..d46ee4bd 100644 --- a/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart +++ b/packages/stream_chat_flutter_core/lib/src/channels_bloc.dart @@ -62,7 +62,7 @@ class ChannelsBloc extends StatefulWidget { /// The current state of the [ChannelsBloc]. class ChannelsBlocState extends State with AutomaticKeepAliveClientMixin { - late StreamChatCoreState _streamChatCoreState; + StreamChatCoreState? _streamChatCoreState; @override Widget build(BuildContext context) { @@ -98,7 +98,7 @@ class ChannelsBlocState extends State PaginationParams paginationParams = const PaginationParams(limit: 30), Map? options, }) async { - final client = _streamChatCoreState.client; + final client = _streamChatCoreState!.client; final clear = paginationParams.offset == 0; @@ -146,10 +146,13 @@ class ChannelsBlocState extends State @override void didChangeDependencies() { - _streamChatCoreState = StreamChatCore.of(context); - final client = _streamChatCoreState.client; + final newStreamChatCoreState = StreamChatCore.of(context); - if (_subscriptions.isEmpty) { + if (newStreamChatCoreState != _streamChatCoreState) { + _streamChatCoreState = newStreamChatCoreState; + final client = _streamChatCoreState!.client; + + _cancelSubscriptions(); if (!widget.lockChannelsOrder) { _subscriptions.add(client .on( diff --git a/packages/stream_chat_flutter_core/lib/src/message_list_core.dart b/packages/stream_chat_flutter_core/lib/src/message_list_core.dart index babbfd36..732ac3e6 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_list_core.dart @@ -109,23 +109,23 @@ class MessageListCore extends StatefulWidget { /// The current state of the [MessageListCore]. class MessageListCoreState extends State { - late StreamChannelState _streamChannel; + StreamChannelState? _streamChannel; - bool get _upToDate => _streamChannel.channel.state?.isUpToDate ?? true; + 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 = []; @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; + : _streamChannel!.channel.state?.messagesStream; bool defaultFilter(Message m) { final isMyMessage = m.user?.id == _currentUser?.id; @@ -167,21 +167,23 @@ class MessageListCoreState extends State { QueryDirection direction = QueryDirection.top, }) { if (!_isThreadConversation) { - return _streamChannel.queryMessages(direction: direction); + return _streamChannel!.queryMessages(direction: direction); } else { - return _streamChannel.getReplies(widget.parentMessage!.id); + return _streamChannel!.getReplies(widget.parentMessage!.id); } } - var _initialized = false; - @override void didChangeDependencies() { - _streamChannel = StreamChannel.of(context); - if (!_initialized && _isThreadConversation) { - _initialized = true; - _streamChannel.getReplies(widget.parentMessage!.id); + final newStreamChannel = StreamChannel.of(context); + + if (newStreamChannel != _streamChannel) { + _streamChannel = newStreamChannel; + if (_isThreadConversation) { + _streamChannel!.getReplies(widget.parentMessage!.id); + } } + super.didChangeDependencies(); } @@ -210,7 +212,7 @@ class MessageListCoreState extends State { @override void dispose() { if (!_upToDate) { - _streamChannel.reloadChannel(); + _streamChannel!.reloadChannel(); } super.dispose(); } diff --git a/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart b/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart index e6cb1aad..199852b9 100644 --- a/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/message_search_list_core.dart @@ -105,28 +105,22 @@ class MessageSearchListCore extends StatefulWidget { /// The current state of the [MessageSearchListCore]. class MessageSearchListCoreState extends State { - late MessageSearchBlocState _messageSearchBloc; - - var _initialized = false; + MessageSearchBlocState? _messageSearchBloc; @override void didChangeDependencies() { - _messageSearchBloc = MessageSearchBloc.of(context); + final newMessageSearchBloc = MessageSearchBloc.of(context); - if (!_initialized) { + if (newMessageSearchBloc != _messageSearchBloc) { + _messageSearchBloc = newMessageSearchBloc; loadData(); - _initialized = true; } - if (widget.messageSearchListController != null) { - widget.messageSearchListController!.loadData = loadData; - widget.messageSearchListController!.paginateData = paginateData; - } super.didChangeDependencies(); } @override - Widget build(BuildContext context) => _buildListView(_messageSearchBloc); + Widget build(BuildContext context) => _buildListView(_messageSearchBloc!); Widget _buildListView(MessageSearchBlocState messageSearchBloc) => StreamBuilder>( @@ -147,7 +141,7 @@ class MessageSearchListCoreState extends State { ); /// Fetches initial messages and updates the widget - Future loadData() => _messageSearchBloc.search( + Future loadData() => _messageSearchBloc!.search( filter: widget.filters, sort: widget.sortOptions, query: widget.messageQuery, @@ -156,11 +150,11 @@ class MessageSearchListCoreState extends State { ); /// Fetches more messages with updated pagination and updates the widget - Future paginateData() => _messageSearchBloc.search( + Future paginateData() => _messageSearchBloc!.search( filter: widget.filters, sort: widget.sortOptions, pagination: widget.paginationParams!.copyWith( - offset: _messageSearchBloc.messageResponses?.length ?? 0, + offset: _messageSearchBloc!.messageResponses?.length ?? 0, ), query: widget.messageQuery, messageFilter: widget.messageFilters, diff --git a/packages/stream_chat_flutter_core/lib/src/user_list_core.dart b/packages/stream_chat_flutter_core/lib/src/user_list_core.dart index da675706..3e4839b0 100644 --- a/packages/stream_chat_flutter_core/lib/src/user_list_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/user_list_core.dart @@ -122,34 +122,25 @@ class UserListCore extends StatefulWidget { /// The current state of the [UserListCore]. class UserListCoreState extends State with WidgetsBindingObserver { - var _initialized = false; + UsersBlocState? _usersBloc; @override void didChangeDependencies() { - if (!_initialized) { + final newUsersBloc = UsersBloc.of(context); + if (newUsersBloc != _usersBloc) { + _usersBloc = newUsersBloc; loadData(); - _initialized = true; - } - if (widget.userListController != null) { - widget.userListController!.loadData = loadData; - widget.userListController!.paginateData = paginateData; } super.didChangeDependencies(); } @override - Widget build(BuildContext context) { - final _usersBloc = UsersBloc.of(context); - return _buildListView(_usersBloc); - } + Widget build(BuildContext context) => _buildListView(); bool get _isListAlreadySorted => widget.sort?.any((e) => e.field == 'name' && e.direction == 1) ?? false; - Stream> _buildUserStream( - UsersBlocState usersBlocState, - ) => - usersBlocState.usersStream.map( + Stream> _buildUserStream() => _usersBloc!.usersStream.map( (users) { if (widget.groupAlphabetically) { var temp = users; @@ -174,11 +165,8 @@ class UserListCoreState extends State }, ); - StreamBuilder> _buildListView( - UsersBlocState usersBlocState, - ) => - StreamBuilder( - stream: _buildUserStream(usersBlocState), + StreamBuilder> _buildListView() => StreamBuilder( + stream: _buildUserStream(), builder: (context, snapshot) { if (snapshot.hasError) { return widget.errorBuilder(snapshot.error!); @@ -195,28 +183,22 @@ class UserListCoreState extends State ); // ignore: public_member_api_docs - Future loadData() { - final _usersBloc = UsersBloc.of(context); - return _usersBloc.queryUsers( - filter: widget.filter, - sort: widget.sort, - pagination: widget.pagination, - options: widget.options, - ); - } + Future loadData() => _usersBloc!.queryUsers( + filter: widget.filter, + sort: widget.sort, + pagination: widget.pagination, + options: widget.options, + ); // ignore: public_member_api_docs - Future paginateData() { - final _usersBloc = UsersBloc.of(context); - return _usersBloc.queryUsers( - filter: widget.filter, - sort: widget.sort, - pagination: widget.pagination!.copyWith( - offset: _usersBloc.users?.length ?? 0, - ), - options: widget.options, - ); - } + Future paginateData() => _usersBloc!.queryUsers( + filter: widget.filter, + sort: widget.sort, + pagination: widget.pagination!.copyWith( + offset: _usersBloc!.users?.length ?? 0, + ), + options: widget.options, + ); @override void didUpdateWidget(UserListCore oldWidget) {