Skip to content

Commit 367d3f8

Browse files
authored
fix(llc, core): retain cached channel messages on offline access with unread messages (#2299)
1 parent d6abb6d commit 367d3f8

File tree

6 files changed

+144
-3
lines changed

6 files changed

+144
-3
lines changed

packages/stream_chat/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
## Upcoming
22

3+
🐞 Fixed
4+
5+
- Fixed cached messages are cleared from channels with unread messages when accessed
6+
offline. [[#2083]](https://github.com/GetStream/stream-chat-flutter/issues/2083)
7+
38
🔄 Changed
49

510
- Deprecated `SortOption.new` constructor in favor of `SortOption.desc` and `SortOption.asc`.

packages/stream_chat/lib/src/client/channel.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1776,7 +1776,18 @@ class Channel {
17761776
if (this.state == null) {
17771777
_initState(channelState);
17781778
} else {
1779-
// Otherwise, update the channel state.
1779+
// Otherwise, we update the existing state with the new channel state.
1780+
//
1781+
// But, before updating the state, we check if we are querying around a
1782+
// message, If we are, we have to truncate the state to avoid potential
1783+
// gaps in the message sequence.
1784+
final isQueryingAround = switch (messagesPagination) {
1785+
PaginationParams(idAround: _?) => true,
1786+
PaginationParams(createdAtAround: _?) => true,
1787+
_ => false,
1788+
};
1789+
1790+
if (isQueryingAround) this.state?.truncate();
17801791
this.state?.updateChannelState(channelState);
17811792
}
17821793

packages/stream_chat/lib/src/core/api/requests.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ class PaginationParams extends Equatable {
137137
greaterThanOrEqual,
138138
lessThan,
139139
lessThanOrEqual,
140+
createdAtAfterOrEqual,
141+
createdAtAfter,
142+
createdAtBeforeOrEqual,
143+
createdAtBefore,
144+
createdAtAround,
140145
];
141146
}
142147

packages/stream_chat/test/src/client/channel_test.dart

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2749,6 +2749,121 @@ void main() {
27492749
),
27502750
).called(1);
27512751
});
2752+
2753+
test('should truncate state when querying around message id', () async {
2754+
final initialMessages = [
2755+
Message(id: 'msg1', text: 'Hello 1'),
2756+
Message(id: 'msg2', text: 'Hello 2'),
2757+
Message(id: 'msg3', text: 'Hello 3'),
2758+
];
2759+
2760+
final stateWithMessages = _generateChannelState(
2761+
channelId,
2762+
channelType,
2763+
).copyWith(messages: initialMessages);
2764+
2765+
channel.state!.updateChannelState(stateWithMessages);
2766+
expect(channel.state!.messages, hasLength(3));
2767+
2768+
final newState = _generateChannelState(
2769+
channelId,
2770+
channelType,
2771+
).copyWith(messages: [
2772+
Message(id: 'msg-before-1', text: 'Message before 1'),
2773+
Message(id: 'msg-before-2', text: 'Message before 2'),
2774+
Message(id: 'target-message-id', text: 'Target message'),
2775+
Message(id: 'msg-after-1', text: 'Message after 1'),
2776+
Message(id: 'msg-after-2', text: 'Message after 2'),
2777+
]);
2778+
2779+
when(
2780+
() => client.queryChannel(
2781+
channelType,
2782+
channelId: channelId,
2783+
channelData: any(named: 'channelData'),
2784+
messagesPagination: any(named: 'messagesPagination'),
2785+
membersPagination: any(named: 'membersPagination'),
2786+
watchersPagination: any(named: 'watchersPagination'),
2787+
),
2788+
).thenAnswer((_) async => newState);
2789+
2790+
const pagination = PaginationParams(idAround: 'target-message-id');
2791+
2792+
final res = await channel.query(messagesPagination: pagination);
2793+
2794+
expect(res, isNotNull);
2795+
expect(channel.state!.messages, hasLength(5));
2796+
expect(channel.state!.messages[2].id, 'target-message-id');
2797+
2798+
verify(
2799+
() => client.queryChannel(
2800+
channelType,
2801+
channelId: channelId,
2802+
channelData: any(named: 'channelData'),
2803+
messagesPagination: pagination,
2804+
membersPagination: any(named: 'membersPagination'),
2805+
watchersPagination: any(named: 'watchersPagination'),
2806+
),
2807+
).called(1);
2808+
});
2809+
2810+
test('should truncate state when querying around created date', () async {
2811+
final initialMessages = [
2812+
Message(id: 'msg1', text: 'Hello 1'),
2813+
Message(id: 'msg2', text: 'Hello 2'),
2814+
Message(id: 'msg3', text: 'Hello 3'),
2815+
];
2816+
2817+
final stateWithMessages = _generateChannelState(
2818+
channelId,
2819+
channelType,
2820+
).copyWith(messages: initialMessages);
2821+
2822+
channel.state!.updateChannelState(stateWithMessages);
2823+
expect(channel.state!.messages, hasLength(3));
2824+
2825+
final targetDate = DateTime.now();
2826+
final newState = _generateChannelState(
2827+
channelId,
2828+
channelType,
2829+
).copyWith(messages: [
2830+
Message(id: 'msg-before-1', text: 'Message before 1'),
2831+
Message(id: 'msg-before-2', text: 'Message before 2'),
2832+
Message(id: 'target-message', text: 'Target message'),
2833+
Message(id: 'msg-after-1', text: 'Message after 1'),
2834+
Message(id: 'msg-after-2', text: 'Message after 2'),
2835+
]);
2836+
2837+
when(
2838+
() => client.queryChannel(
2839+
channelType,
2840+
channelId: channelId,
2841+
channelData: any(named: 'channelData'),
2842+
messagesPagination: any(named: 'messagesPagination'),
2843+
membersPagination: any(named: 'membersPagination'),
2844+
watchersPagination: any(named: 'watchersPagination'),
2845+
),
2846+
).thenAnswer((_) async => newState);
2847+
2848+
final pagination = PaginationParams(createdAtAround: targetDate);
2849+
2850+
final res = await channel.query(messagesPagination: pagination);
2851+
2852+
expect(res, isNotNull);
2853+
expect(channel.state!.messages, hasLength(5));
2854+
expect(channel.state!.messages[2].id, 'target-message');
2855+
2856+
verify(
2857+
() => client.queryChannel(
2858+
channelType,
2859+
channelId: channelId,
2860+
channelData: any(named: 'channelData'),
2861+
messagesPagination: pagination,
2862+
membersPagination: any(named: 'membersPagination'),
2863+
watchersPagination: any(named: 'watchersPagination'),
2864+
),
2865+
).called(1);
2866+
});
27522867
});
27532868

27542869
test('`.queryMembers`', () async {

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 cached messages are cleared from channels with unread messages when accessed
6+
offline. [[#2083]](https://github.com/GetStream/stream-chat-flutter/issues/2083)
7+
18
## 9.13.0
29

310
🐞 Fixed

packages/stream_chat_flutter_core/lib/src/stream_channel.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,6 @@ class StreamChannelState extends State<StreamChannel> {
358358
}) async {
359359
if (channel.state == null) return null;
360360
channel.state?.isUpToDate = false;
361-
channel.state?.truncate();
362361

363362
final pagination = PaginationParams(
364363
limit: limit,
@@ -461,7 +460,6 @@ class StreamChannelState extends State<StreamChannel> {
461460
}) async {
462461
if (channel.state == null) return null;
463462
channel.state?.isUpToDate = false;
464-
channel.state?.truncate();
465463

466464
final pagination = PaginationParams(
467465
limit: limit,

0 commit comments

Comments
 (0)