@@ -1611,9 +1611,6 @@ class Channel {
1611
1611
/// read from a particular message onwards.
1612
1612
Future <EmptyResponse > markRead ({String ? messageId}) async {
1613
1613
_checkInitialized ();
1614
- client.state.totalUnreadCount =
1615
- max (0 , (client.state.totalUnreadCount) - (state! .unreadCount));
1616
- state! .unreadCount = 0 ;
1617
1614
return _client.markChannelRead (id! , type, messageId: messageId);
1618
1615
}
1619
1616
@@ -1623,29 +1620,7 @@ class Channel {
1623
1620
/// to be marked as unread.
1624
1621
Future <EmptyResponse > markUnread (String messageId) async {
1625
1622
_checkInitialized ();
1626
-
1627
- final response = await _client.markChannelUnread (id! , type, messageId);
1628
-
1629
- final lastReadDate = state! .currentUserRead? .lastRead;
1630
- final currentUnread = state! .currentUserRead? .unreadMessages ?? 0 ;
1631
-
1632
- final messagesFromMarked = state! .messages
1633
- .where ((message) => message.user? .id != client.state.currentUser? .id)
1634
- .skipWhile ((message) => message.id != messageId)
1635
- .toList ();
1636
- final channelUnreadCount = max (currentUnread, messagesFromMarked.length);
1637
- final additionalTotalUnreadCount = currentUnread > 0
1638
- ? messagesFromMarked
1639
- .takeWhile ((message) =>
1640
- lastReadDate == null ||
1641
- message.createdAt.isBefore (lastReadDate))
1642
- .length
1643
- : messagesFromMarked.length;
1644
-
1645
- client.state.totalUnreadCount += additionalTotalUnreadCount;
1646
- state! .unreadCount = channelUnreadCount;
1647
-
1648
- return response;
1623
+ return _client.markChannelUnread (id! , type, messageId);
1649
1624
}
1650
1625
1651
1626
/// Mark the thread with [threadId] in the channel as read.
@@ -2750,16 +2725,21 @@ class ChannelClientState {
2750
2725
EventType .notificationMessageNew,
2751
2726
)
2752
2727
.listen ((event) {
2753
- final message = event.message! ;
2754
- final showInChannel =
2755
- message.parentId != null && message.showInChannel != true ;
2756
- if (isUpToDate || showInChannel) {
2728
+ final message = event.message;
2729
+ if (message == null ) return ;
2730
+
2731
+ final isThreadMessage = message.parentId != null ;
2732
+ final isShownInChannel = message.showInChannel == true ;
2733
+ final isThreadOnlyMessage = isThreadMessage && ! isShownInChannel;
2734
+
2735
+ // Only add the message if the channel is upToDate or if the message is
2736
+ // a thread-only message.
2737
+ if (isUpToDate || isThreadOnlyMessage) {
2757
2738
updateMessage (message);
2758
2739
}
2759
2740
2760
- if (_countMessageAsUnread (message)) {
2761
- unreadCount += 1 ;
2762
- }
2741
+ // Otherwise, check if we can count the message as unread.
2742
+ if (_countMessageAsUnread (message)) unreadCount += 1 ;
2763
2743
}));
2764
2744
}
2765
2745
@@ -2783,6 +2763,24 @@ class ChannelClientState {
2783
2763
return true ;
2784
2764
}
2785
2765
2766
+ /// Updates the [read] in the state if it exists. Adds it otherwise.
2767
+ void updateRead ([Iterable <Read >? read]) {
2768
+ final existingReads = < Read > [...? channelState.read];
2769
+ final updatedReads = < Read > [
2770
+ ...existingReads.merge (
2771
+ read,
2772
+ key: (read) => read.user.id,
2773
+ update: (original, updated) => updated,
2774
+ ),
2775
+ ];
2776
+
2777
+ updateChannelState (
2778
+ channelState.copyWith (
2779
+ read: updatedReads,
2780
+ ),
2781
+ );
2782
+ }
2783
+
2786
2784
/// Updates the [message] in the state if it exists. Adds it otherwise.
2787
2785
void updateMessage (Message message) {
2788
2786
// Determine if the message should be displayed in the channel view.
@@ -2947,35 +2945,23 @@ class ChannelClientState {
2947
2945
_subscriptions
2948
2946
..add (
2949
2947
_channel
2950
- .on (EventType .messageRead, EventType .notificationMarkRead)
2948
+ .on (
2949
+ EventType .messageRead,
2950
+ EventType .notificationMarkRead,
2951
+ )
2951
2952
.listen (
2952
2953
(event) {
2953
2954
final user = event.user;
2954
2955
if (user == null ) return ;
2955
2956
2956
- final existingRead = [...? channelState.read];
2957
- // Return if the user does not have a existing read.
2958
- if (! existingRead.any ((r) => r.user.id == user.id)) return ;
2959
-
2960
- Read ? maybeUpdateRead (Read ? existingRead) {
2961
- if (existingRead == null ) return null ;
2962
- if (existingRead.user.id == user.id) {
2963
- return Read (
2964
- user: user,
2965
- lastRead: event.createdAt,
2966
- unreadMessages: event.unreadMessages,
2967
- lastReadMessageId: event.lastReadMessageId,
2968
- );
2969
- }
2970
-
2971
- return existingRead;
2972
- }
2973
-
2974
- updateChannelState (
2975
- channelState.copyWith (
2976
- read: [...existingRead.map (maybeUpdateRead).nonNulls],
2977
- ),
2957
+ final updatedRead = Read (
2958
+ user: user,
2959
+ lastRead: event.createdAt,
2960
+ unreadMessages: event.unreadMessages,
2961
+ lastReadMessageId: event.lastReadMessageId,
2978
2962
);
2963
+
2964
+ return updateRead ([updatedRead]);
2979
2965
},
2980
2966
),
2981
2967
)
@@ -2985,29 +2971,14 @@ class ChannelClientState {
2985
2971
final user = event.user;
2986
2972
if (user == null ) return ;
2987
2973
2988
- final existingRead = [...? channelState.read];
2989
- // Return if the user does not have a existing read.
2990
- if (! existingRead.any ((r) => r.user.id == user.id)) return ;
2991
-
2992
- Read ? maybeUpdateRead (Read ? existingRead) {
2993
- if (existingRead == null ) return null ;
2994
- if (existingRead.user.id == user.id) {
2995
- return Read (
2996
- user: user,
2997
- lastRead: event.lastReadAt! ,
2998
- unreadMessages: event.unreadMessages,
2999
- lastReadMessageId: event.lastReadMessageId,
3000
- );
3001
- }
3002
-
3003
- return existingRead;
3004
- }
3005
-
3006
- updateChannelState (
3007
- channelState.copyWith (
3008
- read: [...existingRead.map (maybeUpdateRead).nonNulls],
3009
- ),
2974
+ final updatedRead = Read (
2975
+ user: user,
2976
+ lastRead: event.lastReadAt! ,
2977
+ unreadMessages: event.unreadMessages,
2978
+ lastReadMessageId: event.lastReadMessageId,
3010
2979
);
2980
+
2981
+ return updateRead ([updatedRead]);
3011
2982
},
3012
2983
),
3013
2984
);
@@ -3116,26 +3087,32 @@ class ChannelClientState {
3116
3087
3117
3088
/// Setter for unread count.
3118
3089
set unreadCount (int count) {
3119
- final reads = [...read] ;
3120
- final currentUserReadIndex = reads. indexWhere (_isCurrentUserRead) ;
3090
+ final currentUser = _channel.client.state.currentUser ;
3091
+ if (currentUser == null ) return ;
3121
3092
3122
- if (currentUserReadIndex < 0 ) return ;
3093
+ var existingUserRead = currentUserRead;
3094
+ if (existingUserRead == null ) {
3095
+ final lastMessageAt = _channelState.channel? .lastMessageAt;
3096
+ existingUserRead = Read (
3097
+ user: currentUser,
3098
+ lastRead: lastMessageAt ?? DateTime .now (),
3099
+ );
3100
+ }
3123
3101
3124
- reads[currentUserReadIndex] =
3125
- reads[currentUserReadIndex].copyWith (unreadMessages: count);
3126
- _channelState = _channelState.copyWith (read: reads);
3102
+ return updateRead ([existingUserRead.copyWith (unreadMessages: count)]);
3127
3103
}
3128
3104
3129
3105
bool _countMessageAsUnread (Message message) {
3130
- // Don't count if the message is silent or shadowed.
3131
- if (message.silent) return false ;
3132
- if (message.shadowed) return false ;
3106
+ // Don't count if the channel doesn't allow read events.
3107
+ if (! _channel.canReceiveReadEvents) return false ;
3133
3108
3134
3109
// Don't count if the channel is muted.
3135
3110
if (_channel.isMuted) return false ;
3136
3111
3137
- // Don't count if the channel doesn't allow read events.
3138
- if (! _channel.canReceiveReadEvents) return false ;
3112
+ // Don't count if the message is silent or shadowed or ephemeral.
3113
+ if (message.silent) return false ;
3114
+ if (message.shadowed) return false ;
3115
+ if (message.isEphemeral) return false ;
3139
3116
3140
3117
// Don't count thread replies which are not shown in the channel as unread.
3141
3118
if (message.parentId != null && message.showInChannel == false ) {
@@ -3153,6 +3130,9 @@ class ChannelClientState {
3153
3130
// Don't count user's own messages as unread.
3154
3131
if (messageUser.id == currentUser.id) return false ;
3155
3132
3133
+ // Don't count restricted messages as unread.
3134
+ if (message.isNotVisibleTo (currentUser.id)) return false ;
3135
+
3156
3136
// Don't count messages from muted users as unread.
3157
3137
final isMuted = currentUser.mutes.any ((it) => it.user.id == messageUser.id);
3158
3138
if (isMuted) return false ;
0 commit comments