Skip to content

Commit 30eb3a8

Browse files
authored
fix(core): handle channel reload failure on dispose (#2311)
1 parent 39beb8e commit 30eb3a8

File tree

6 files changed

+31
-7
lines changed

6 files changed

+31
-7
lines changed

packages/stream_chat_flutter/lib/src/message_list_view/message_list_view.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,6 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
471471

472472
@override
473473
void dispose() {
474-
if (!_upToDate) {
475-
streamChannel!.reloadChannel();
476-
}
477474
debouncedMarkRead?.cancel();
478475
debouncedMarkThreadRead?.cancel();
479476
_messageNewListener?.cancel();

packages/stream_chat_flutter/test/src/mocks.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class MockChannelState extends Mock implements ChannelClientState {
6868
when(() => typingEvents).thenReturn({});
6969
when(() => typingEventsStream).thenAnswer((_) => Stream.value({}));
7070
when(() => unreadCount).thenReturn(0);
71+
when(() => isUpToDate).thenReturn(true);
7172
when(() => read).thenReturn([]);
7273
}
7374
}

packages/stream_chat_flutter_core/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## Upcoming
2+
3+
🐞 Fixed
4+
5+
- Fixed `MessageListCore.dispose()` crash when channel reload fails due to insufficient permissions.
6+
- Fixed incorrect parent message comparison in `MessageListCore.didUpdateWidget()`.
7+
18
## 9.14.0
29

310
🐞 Fixed

packages/stream_chat_flutter_core/lib/src/message_list_core.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class MessageListCoreState extends State<MessageListCore> {
210210
_setupController();
211211
}
212212

213-
if (widget.parentMessage?.id != widget.parentMessage?.id) {
213+
if (widget.parentMessage?.id != oldWidget.parentMessage?.id) {
214214
if (_isThreadConversation) {
215215
_streamChannel!.getReplies(
216216
widget.parentMessage!.id,
@@ -233,11 +233,22 @@ class MessageListCoreState extends State<MessageListCore> {
233233
}
234234
}
235235

236+
Future<void> _reloadChannelIfNeeded() async {
237+
// If the channel is up to date, we don't need to reload it.
238+
if (_upToDate) return;
239+
240+
try {
241+
return await _streamChannel?.reloadChannel();
242+
} catch (_) {
243+
// We just ignore the error here, as we can't do anything about it.
244+
// The reload might fail for various reasons, such as user already
245+
// left the channel, or the channel is deleted.
246+
}
247+
}
248+
236249
@override
237250
void dispose() {
238-
if (!_upToDate) {
239-
_streamChannel!.reloadChannel();
240-
}
251+
_reloadChannelIfNeeded();
241252
super.dispose();
242253
}
243254
}

packages/stream_chat_flutter_core/lib/src/stream_channel.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,10 @@ class StreamChannelState extends State<StreamChannel> {
673673
// Otherwise, load the channel at the last read date.
674674
return loadChannelAtTimestamp(currentUserRead.lastRead);
675675
}
676+
677+
// If nothing above applies, we just load the channel at the latest
678+
// messages if we are not already at the latest messages.
679+
if (channel.state?.isUpToDate == false) return loadChannelAtMessage(null);
676680
}
677681

678682
late Future<void> _channelInitFuture;

packages/stream_chat_flutter_core/test/stream_channel_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ void main() {
7676
final mockChannel = MockChannel();
7777
when(() => mockChannel.cid).thenReturn('test:channel');
7878
when(() => mockChannel.state.unreadCount).thenReturn(0);
79+
when(() => mockChannel.state.isUpToDate).thenReturn(true);
7980

8081
// A simple widget that provides StreamChannel
8182
final testWidget = MaterialApp(
@@ -319,6 +320,7 @@ void main() {
319320
final mockChannel1 = MockChannel();
320321
when(() => mockChannel1.cid).thenReturn('test:channel1');
321322
when(() => mockChannel1.state.unreadCount).thenReturn(0);
323+
when(() => mockChannel1.state.isUpToDate).thenReturn(true);
322324

323325
// Build with first channel
324326
await tester.pumpWidget(
@@ -471,6 +473,7 @@ void main() {
471473
(tester) async {
472474
when(() => mockChannel.state.messages).thenReturn([]);
473475
when(() => mockChannel.state.unreadCount).thenReturn(0);
476+
when(() => mockChannel.state.isUpToDate).thenReturn(true);
474477

475478
final streamChannel = await _pumpStreamChannel(tester);
476479

@@ -499,6 +502,7 @@ void main() {
499502
when(() => mockChannel.state.unreadCount).thenReturn(0);
500503
when(() => mockChannel.state.messages).thenReturn(messages);
501504
when(() => mockChannel.state.currentUserRead).thenReturn(mockRead);
505+
when(() => mockChannel.state.isUpToDate).thenReturn(true);
502506

503507
final streamChannel = await _pumpStreamChannel(tester);
504508

0 commit comments

Comments
 (0)