@@ -1611,9 +1611,6 @@ class Channel {
16111611 /// read from a particular message onwards.
16121612 Future <EmptyResponse > markRead ({String ? messageId}) async {
16131613 _checkInitialized ();
1614- client.state.totalUnreadCount =
1615- max (0 , (client.state.totalUnreadCount) - (state! .unreadCount));
1616- state! .unreadCount = 0 ;
16171614 return _client.markChannelRead (id! , type, messageId: messageId);
16181615 }
16191616
@@ -1623,29 +1620,7 @@ class Channel {
16231620 /// to be marked as unread.
16241621 Future <EmptyResponse > markUnread (String messageId) async {
16251622 _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);
16491624 }
16501625
16511626 /// Mark the thread with [threadId] in the channel as read.
@@ -2750,16 +2725,21 @@ class ChannelClientState {
27502725 EventType .notificationMessageNew,
27512726 )
27522727 .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) {
27572738 updateMessage (message);
27582739 }
27592740
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 ;
27632743 }));
27642744 }
27652745
@@ -2783,6 +2763,24 @@ class ChannelClientState {
27832763 return true ;
27842764 }
27852765
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+
27862784 /// Updates the [message] in the state if it exists. Adds it otherwise.
27872785 void updateMessage (Message message) {
27882786 // Determine if the message should be displayed in the channel view.
@@ -2947,35 +2945,23 @@ class ChannelClientState {
29472945 _subscriptions
29482946 ..add (
29492947 _channel
2950- .on (EventType .messageRead, EventType .notificationMarkRead)
2948+ .on (
2949+ EventType .messageRead,
2950+ EventType .notificationMarkRead,
2951+ )
29512952 .listen (
29522953 (event) {
29532954 final user = event.user;
29542955 if (user == null ) return ;
29552956
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,
29782962 );
2963+
2964+ return updateRead ([updatedRead]);
29792965 },
29802966 ),
29812967 )
@@ -2985,29 +2971,14 @@ class ChannelClientState {
29852971 final user = event.user;
29862972 if (user == null ) return ;
29872973
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,
30102979 );
2980+
2981+ return updateRead ([updatedRead]);
30112982 },
30122983 ),
30132984 );
@@ -3116,26 +3087,32 @@ class ChannelClientState {
31163087
31173088 /// Setter for unread count.
31183089 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 ;
31213092
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+ }
31233101
3124- reads[currentUserReadIndex] =
3125- reads[currentUserReadIndex].copyWith (unreadMessages: count);
3126- _channelState = _channelState.copyWith (read: reads);
3102+ return updateRead ([existingUserRead.copyWith (unreadMessages: count)]);
31273103 }
31283104
31293105 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 ;
31333108
31343109 // Don't count if the channel is muted.
31353110 if (_channel.isMuted) return false ;
31363111
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 ;
31393116
31403117 // Don't count thread replies which are not shown in the channel as unread.
31413118 if (message.parentId != null && message.showInChannel == false ) {
@@ -3153,6 +3130,9 @@ class ChannelClientState {
31533130 // Don't count user's own messages as unread.
31543131 if (messageUser.id == currentUser.id) return false ;
31553132
3133+ // Don't count restricted messages as unread.
3134+ if (message.isNotVisibleTo (currentUser.id)) return false ;
3135+
31563136 // Don't count messages from muted users as unread.
31573137 final isMuted = currentUser.mutes.any ((it) => it.user.id == messageUser.id);
31583138 if (isMuted) return false ;
0 commit comments