stream-chat-swift icon indicating copy to clipboard operation
stream-chat-swift copied to clipboard

Multiple didUpdateChannel with unreadCount 0

Open glennposadas opened this issue 1 year ago • 15 comments

What did you do?

The project is set up like so:

  1. Project List - each projects/cell rows (up to 20 max) have a badge count (unread messages).
  2. Project Details - at the top of this screen, it has a message button that has a badge count (unread messages) too. It pushes the chat screen for the project.
  3. Chat Channel - FNChatChannelVC is a subclass of ChatChannelVC.

FNChatChannelVC has in its viewWillAppear and viewWillDisappear the following:

    channelController.markRead()
    project.unreadChatsCount = 0
    try? project.managedObjectContext?.save()

So, FNProjectsViewController --> presents FNProjectContainerViewController --> pushes FNChatChannelVC

What did you expect to happen?

The ChatChannelControllerDelegate didUpdateChannel should return the correct unread count for the user that is a member of the updated channel, without a delay, and duplication.

What happened instead?

The didUpdateChannel sometimes gets triggered twice and the unread count is 0.

Here's my logs when there's no issue:

2024-03-14 01:43:58.540 MyApp[5202:ea5b] [CHAT]: FNProjectContainerViewController: didUpdateChannel. --> 1 || channel.item.unreadCount -> ChannelUnreadCount(messages: 1, mentions: 0)
2024-03-14 01:43:58.540 MyApp[5202:e747] 

[CHAT]: setBadgeCount 1 | PROJECT ID: 542409

And here's my logs whenever the issue happens:

2024-03-14 01:42:58.471 MyApp[5202:ea5b] [CHAT]: FNProjectContainerViewController: didUpdateChannel. --> 1 || channel.item.unreadCount -> ChannelUnreadCount(messages: 1, mentions: 0)
2024-03-14 01:42:58.471 MyApp[5202:12433] 

[CHAT]: setBadgeCount 1 | PROJECT ID: 542409

2024-03-14 01:42:59.872 MyApp[5202:1ce27] [CHAT]: FNProjectContainerViewController: didUpdateChannel. --> 0 || channel.item.unreadCount -> ChannelUnreadCount(messages: 0, mentions: 0)
2024-03-14 01:42:59.872 MyApp[5202:29d0f] 

[CHAT]: setBadgeCount 0 | PROJECT ID: 542409
2024-03-14 01:43:00.374 MyApp[5202:2a70b] [CHAT]: FNProjectContainerViewController: didUpdateChannel. --> 0 || channel.item.unreadCount -> ChannelUnreadCount(messages: 0, mentions: 0)
2024-03-14 01:43:00.375 MyApp[5202:29d0f] 

[CHAT]: setBadgeCount 0 | PROJECT ID: 542409

Steps to reproduce:

User 1 sends a message to the channel. User 2 is in the project list. User 2 sees "1" badge count in Project 1. ✅ User 2 opens project details with Project 1. User 2 sees "1" badge count on message icon ✅

User 2 opens chat. User 2 taps on the back button. User 2 arrives in the previous screen (project details screen) User 1 sends another message. User 2 sees "1" badge count in Project 1. ✅ After 1 second: User 2 sees "0" badge count (badge count view clears up). ❌

If the issue does not happen, repeat the steps. Some users experience it in only 1 try. Some users like myself only experience the issue after 9 up to 11 repeats.


GetStream Environment

GetStream Chat version: 4.49.0 GetStream Chat frameworks: StreamChat, StreamChatUI 4.49.0 iOS version: 17.3.x Swift version: 5.9.2 Xcode version: 15.2 Device: iPhone 15 Pro Max (and many more devices)

Additional context

glennposadas avatar Mar 14 '24 20:03 glennposadas

Hi @glennposadas,

Do you have any video to show the problem so that it is clearer? You can also send it to [email protected] if you don't want to share it here.

But my understanding is that the issue might be this:

channelController.markRead()
project.unreadChatsCount = 0
try? project.managedObjectContext?.save()

If you do that on the viewWillAppear() what might happen, is that the user sends a message, but markRead() maybe takes more time and resets the previous message send? But I'm not sure I fully understood the problem TBH. A video would help for sure.

Best, Nuno

nuno-vieira avatar Mar 15 '24 15:03 nuno-vieira

Hi @nuno-vieira . I sent a video to your email. And no, removing the code you mentioned does not work. Thanks!

glennposadas avatar Mar 15 '24 19:03 glennposadas

Hi @glennposadas,

I'm not able to reproduce the issue. Can you try the following things: 1- Update to 4.50.0 (We have fixed some issues related to the current user cache, which could be causing those issues 2- Make sure the same user is not logged in on another device and marking the channel as read 3- Why is markRead() in viewWillDisappear? That could lead to race conditions. In fact, you probably don't need to call markRead() yourself, we already do it ourselves in viewDidAppear(), and it has a bit of additional logic.

Thanks, Nuno

nuno-vieira avatar Mar 18 '24 16:03 nuno-vieira

Thanks, @nuno-vieira . I will try these and get back to you soon. I hope you tried going ( for 10-20 times) to the chat screen and going back to the previous screen (that observes unread messages in the channel).

Some codes:

In the project details:

// MARK: -
// MARK: ChatChannelControllerDelegate

extension FNProjectContainerViewController: ChatChannelControllerDelegate {
  public func channelController(_ channelController: ChatChannelController, didUpdateChannel channel: EntityChange<ChatChannel>) {
    let countFromChannel = channelController.channel?.unreadCount.messages ?? 0
    DDLogDebug("[CHAT]: FNProjectContainerViewController: didUpdateChannel. --> \(countFromChannel) || channel.item.unreadCount -> \(channel.item.unreadCount)")
    setBadgeCount(countFromChannel)
  }
}


- (void)setBadgeCount:(NSInteger)count {
  DDLogDebug(@"\n\n[CHAT]: setBadgeCount %ld | PROJECT ID: %@", (long)count, self.project.objectId.stringValue);
  self.project.unreadChatsCount = [NSNumber numberWithInteger:count];
  [self.chatButton setEnabled:YES];
  [self.chatButton setBadgeValue:count];
  [self.project.managedObjectContext save:nil];
}

glennposadas avatar Mar 18 '24 16:03 glennposadas

@glennposadas, yes I tried a couple of times, but calling markRead() on both viewWillAppear and viewWillDisappear, it will be likely there will be some race conditions. If you call markRead() after sending a message and leave the channel quickly, it will be likely depending on network conditions the markRead call can be finished only after the message being published and vice-versa

nuno-vieira avatar Mar 18 '24 18:03 nuno-vieira

Hi @nuno-vieira . Sorry for the late update.

I did both the following but didn't help:

  1. Updated to 4.50.
  2. Removed all markRead().

Still, the didUpdateChannel gets triggered thirce!

  • First trigger: the expected one and has the correct badge count (1).
  • After about 1 second of the above first delegate call, the 2 unexpected calls come in, this time with the incorrect unread count (0).

Is there a way to check who sets the messages as unread? I tried the Stream explorer, but to no avail.


For what it's worth, here's the complete logs of the 3 didUpdateChannel events.

EVENT #1: Unread 1 ✅

2024-03-24 02:54:09.675 SiteCapture[2920:691b] [CHAT]: FNProjectContainerViewController: didUpdateChannel.
--> 1 || channel.item.unreadCount -> ChannelUnreadCount(messages: 1, mentions: 0)
---> Channel: Update:
    ChatChannel(
        cid: messaging:project-542409,
        name: Optional("Boom mighnyt"),
        imageURL: nil,
        lastMessageAt: Optional(2024-03-23 18:54:08 +0000),
        createdAt: 2024-03-05 13:47:51 +0000,
        updatedAt: 2024-03-23 18:53:58 +0000,
        deletedAt: nil,
        truncatedAt: nil,
        isHidden: false,
        createdBy: Optional(StreamChat.ChatUser),
        config: StreamChat.ChannelConfig,
        ownCapabilities: Set([
            StreamChat.ChannelCapability(rawValue: "join-channel"),
            StreamChat.ChannelCapability(rawValue: "update-channel"),
            StreamChat.ChannelCapability(rawValue: "quote-message"),
            StreamChat.ChannelCapability(rawValue: "delete-channel"),
            StreamChat.ChannelCapability(rawValue: "delete-any-message"),
            StreamChat.ChannelCapability(rawValue: "read-events"),
            StreamChat.ChannelCapability(rawValue: "update-own-message"),
            StreamChat.ChannelCapability(rawValue: "send-custom-events"),
            StreamChat.ChannelCapability(rawValue: "send-message"),
            StreamChat.ChannelCapability(rawValue: "upload-file"),
            StreamChat.ChannelCapability(rawValue: "join-call"),
            StreamChat.ChannelCapability(rawValue: "ban-channel-members"),
            StreamChat.ChannelCapability(rawValue: "update-thread"),
            StreamChat.ChannelCapability(rawValue: "leave-channel"),
            StreamChat.ChannelCapability(rawValue: "send-reaction"),
            StreamChat.ChannelCapability(rawValue: "set-channel-cooldown"),
            StreamChat.ChannelCapability(rawValue: "search-messages"),
            StreamChat.ChannelCapability(rawValue: "freeze-channel"),
            StreamChat.ChannelCapability(rawValue: "send-reply"),
            StreamChat.ChannelCapability(rawValue: "mute-channel"),
            StreamChat.ChannelCapability(rawValue: "typing-events"),
            StreamChat.ChannelCapability(rawValue: "pin-message"),
            StreamChat.ChannelCapability(rawValue: "delete-own-message"),
            StreamChat.ChannelCapability(rawValue: "update-any-message"),
            StreamChat.ChannelCapability(rawValue: "update-channel-members"),
            StreamChat.ChannelCapability(rawValue: "create-call"),
            StreamChat.ChannelCapability(rawValue: "flag-message"),
            StreamChat.ChannelCapability(rawValue: "send-typing-events"),
            StreamChat.ChannelCapability(rawValue: "connect-events"),
            StreamChat.ChannelCapability(rawValue: "send-links")
        ]),
        isFrozen: false,
        memberCount: 4,
        __lastActiveMembers: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatChannelMember>>,
        __currentlyTypingUsers: StreamChat.CoreDataLazy<Swift.Set<StreamChat.ChatUser>>,
        membership: Optional(StreamChat.ChatChannelMember),
        __lastActiveWatchers: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatUser>>,
        watcherCount: 2,
        team: nil,
        __unreadCount: StreamChat.CoreDataLazy<StreamChat.ChannelUnreadCount>,
        __latestMessages: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatMessage>>,
        __lastMessageFromCurrentUser: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.ChatMessage>>,
        __pinnedMessages: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatMessage>>,
        reads: [
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-23 18:54:09 +0000,
                lastReadMessageId: Optional("352afc7f-be4e-40f0-8d25-414ce1e3f19b"),
                unreadMessagesCount: 0,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-13 21:24:53 +0000,
                lastReadMessageId: Optional("88b5f86f-1337-4cce-b9a0-eaeddc39b0f6"),
                unreadMessagesCount: 64,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-15 19:12:26 +0000,
                lastReadMessageId: Optional("93dd2b8f-289d-40a8-bc23-87216599bdce"),
                unreadMessagesCount: 62,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-23 18:53:58 +0000,
                lastReadMessageId: Optional("352afc7f-be4e-40f0-8d25-414ce1e3f19b"),
                unreadMessagesCount: 1,
                user: StreamChat.ChatUser
            )
        ],
        __muteDetails: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.MuteDetails>>,
        cooldownDuration: 0,
        extraData: ["disabled": StreamChat.RawJSON.bool(false)],
        __previewMessage: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.ChatMessage>>
    )
| Controller: StreamChat.ChatChannelController
2024-03-24 02:54:09.675 SiteCapture[2920:7007]

EVENT #2 and #3, Unread: 0 ❌

2024-03-24 02:54:44.872 SiteCapture[2920:460f] [CHAT]: FNProjectContainerViewController: didUpdateChannel.
--> 0 || channel.item.unreadCount -> ChannelUnreadCount(messages: 0, mentions: 0)
---> Channel: Update:
    ChatChannel(
        cid: messaging:project-542409,
        name: Optional("Boom mighnyt"),
        imageURL: nil,
        lastMessageAt: Optional(2024-03-23 18:54:42 +0000),
        createdAt: 2024-03-05 13:47:51 +0000,
        updatedAt: 2024-03-23 18:54:38 +0000,
        deletedAt: nil,
        truncatedAt: nil,
        isHidden: false,
        createdBy: Optional(StreamChat.ChatUser),
        config: StreamChat.ChannelConfig,
        ownCapabilities: Set([
            StreamChat.ChannelCapability(rawValue: "create-call"),
            StreamChat.ChannelCapability(rawValue: "quote-message"),
            StreamChat.ChannelCapability(rawValue: "read-events"),
            StreamChat.ChannelCapability(rawValue: "search-messages"),
            StreamChat.ChannelCapability(rawValue: "send-custom-events"),
            StreamChat.ChannelCapability(rawValue: "delete-channel"),
            StreamChat.ChannelCapability(rawValue: "update-channel"),
            StreamChat.ChannelCapability(rawValue: "mute-channel"),
            StreamChat.ChannelCapability(rawValue: "join-channel"),
            StreamChat.ChannelCapability(rawValue: "send-message"),
            StreamChat.ChannelCapability(rawValue: "send-typing-events"),
            StreamChat.ChannelCapability(rawValue: "send-reply"),
            StreamChat.ChannelCapability(rawValue: "update-channel-members"),
            StreamChat.ChannelCapability(rawValue: "update-own-message"),
            StreamChat.ChannelCapability(rawValue: "freeze-channel"),
            StreamChat.ChannelCapability(rawValue: "send-links"),
            StreamChat.ChannelCapability(rawValue: "update-any-message"),
            StreamChat.ChannelCapability(rawValue: "leave-channel"),
            StreamChat.ChannelCapability(rawValue: "flag-message"),
            StreamChat.ChannelCapability(rawValue: "ban-channel-members"),
            StreamChat.ChannelCapability(rawValue: "upload-file"),
            StreamChat.ChannelCapability(rawValue: "send-reaction"),
            StreamChat.ChannelCapability(rawValue: "delete-any-message"),
            StreamChat.ChannelCapability(rawValue: "set-channel-cooldown"),
            StreamChat.ChannelCapability(rawValue: "typing-events"),
            StreamChat.ChannelCapability(rawValue: "connect-events"),
            StreamChat.ChannelCapability(rawValue: "update-thread"),
            StreamChat.ChannelCapability(rawValue: "join-call"),
            StreamChat.ChannelCapability(rawValue: "pin-message"),
            StreamChat.ChannelCapability(rawValue: "delete-own-message")
        ]),
        isFrozen: false,
        memberCount: 4,
        __lastActiveMembers: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatChannelMember>>,
        __currentlyTypingUsers: StreamChat.CoreDataLazy<Swift.Set<StreamChat.ChatUser>>,
        membership: Optional(StreamChat.ChatChannelMember),
        __lastActiveWatchers: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatUser>>,
        watcherCount: 2,
        team: nil,
        __unreadCount: StreamChat.CoreDataLazy<StreamChat.ChannelUnreadCount>,
        __latestMessages: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatMessage>>,
        __lastMessageFromCurrentUser: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.ChatMessage>>,
        __pinnedMessages: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatMessage>>,
        reads: [
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-23 18:54:44 +0000,
                lastReadMessageId: Optional("e10af15c-81d5-41aa-80bc-773e9642a94f"),
                unreadMessagesCount: 0,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-15 19:12:26 +0000,
                lastReadMessageId: Optional("93dd2b8f-289d-40a8-bc23-87216599bdce"),
                unreadMessagesCount: 63,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-23 18:54:42 +0000,
                lastReadMessageId: Optional("e10af15c-81d5-41aa-80bc-773e9642a94f"),
                unreadMessagesCount: 0,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-13 21:24:53 +0000,
                lastReadMessageId: Optional("88b5f86f-1337-4cce-b9a0-eaeddc39b0f6"),
                unreadMessagesCount: 65,
                user: StreamChat.ChatUser
            )
        ],
        __muteDetails: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.MuteDetails>>,
        cooldownDuration: 0,
        extraData: ["disabled": StreamChat.RawJSON.bool(false)],
        __previewMessage: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.ChatMessage>>
    )
| Controller: StreamChat.ChatChannelController

2024-03-24 02:54:44.873 SiteCapture[2920:a91b] 

2024-03-24 02:54:45.384 SiteCapture[2920:a91b] [CHAT]: setBadgeCount 0 | PROJECT ID: 542409

2024-03-24 02:54:45.384 SiteCapture[2920:a91b] [CHAT]: FNProjectContainerViewController: didUpdateChannel.
--> 0 || channel.item.unreadCount -> ChannelUnreadCount(messages: 0, mentions: 0)
---> Channel: Update: 
    ChatChannel(
        cid: messaging:project-542409,
        name: Optional("Boom mighnyt"),
        imageURL: nil,
        lastMessageAt: Optional(2024-03-23 18:54:42 +0000),
        createdAt: 2024-03-05 13:47:51 +0000,
        updatedAt: 2024-03-23 18:54:38 +0000,
        deletedAt: nil,
        truncatedAt: nil,
        isHidden: false,
        createdBy: Optional(StreamChat.ChatUser),
        config: StreamChat.ChannelConfig,
        ownCapabilities: Set([
            StreamChat.ChannelCapability(rawValue: "create-call"),
            StreamChat.ChannelCapability(rawValue: "quote-message"),
            StreamChat.ChannelCapability(rawValue: "read-events"),
            StreamChat.ChannelCapability(rawValue: "search-messages"),
            StreamChat.ChannelCapability(rawValue: "send-custom-events"),
            StreamChat.ChannelCapability(rawValue: "delete-channel"),
            StreamChat.ChannelCapability(rawValue: "update-channel"),
            StreamChat.ChannelCapability(rawValue: "mute-channel"),
            StreamChat.ChannelCapability(rawValue: "join-channel"),
            StreamChat.ChannelCapability(rawValue: "send-message"),
            StreamChat.ChannelCapability(rawValue: "send-typing-events"),
            StreamChat.ChannelCapability(rawValue: "send-reply"),
            StreamChat.ChannelCapability(rawValue: "update-channel-members"),
            StreamChat.ChannelCapability(rawValue: "update-own-message"),
            StreamChat.ChannelCapability(rawValue: "freeze-channel"),
            StreamChat.ChannelCapability(rawValue: "send-links"),
            StreamChat.ChannelCapability(rawValue: "update-any-message"),
            StreamChat.ChannelCapability(rawValue: "leave-channel"),
            StreamChat.ChannelCapability(rawValue: "flag-message"),
            StreamChat.ChannelCapability(rawValue: "ban-channel-members"),
            StreamChat.ChannelCapability(rawValue: "upload-file"),
            StreamChat.ChannelCapability(rawValue: "send-reaction"),
            StreamChat.ChannelCapability(rawValue: "delete-any-message"),
            StreamChat.ChannelCapability(rawValue: "set-channel-cooldown"),
            StreamChat.ChannelCapability(rawValue: "typing-events"),
            StreamChat.ChannelCapability(rawValue: "connect-events"),
            StreamChat.ChannelCapability(rawValue: "update-thread"),
            StreamChat.ChannelCapability(rawValue: "join-call"),
            StreamChat.ChannelCapability(rawValue: "pin-message"),
            StreamChat.ChannelCapability(rawValue: "delete-own-message")
        ]),
        isFrozen: false,
        memberCount: 4,
        __lastActiveMembers: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatChannelMember>>,
        __currentlyTypingUsers: StreamChat.CoreDataLazy<Swift.Set<StreamChat.ChatUser>>,
        membership: Optional(StreamChat.ChatChannelMember),
        __lastActiveWatchers: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatUser>>,
        watcherCount: 2,
        team: nil,
        __unreadCount: StreamChat.CoreDataLazy<StreamChat.ChannelUnreadCount>,
        __latestMessages: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatMessage>>,
        __lastMessageFromCurrentUser: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.ChatMessage>>,
        __pinnedMessages: StreamChat.CoreDataLazy<Swift.Array<StreamChat.ChatMessage>>,
        reads: [
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-13 21:24:53 +0000,
                lastReadMessageId: Optional("88b5f86f-1337-4cce-b9a0-eaeddc39b0f6"),
                unreadMessagesCount: 65,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-23 18:54:44 +0000,
                lastReadMessageId: Optional("047cadcc-86ce-4637-a115-4cce27dabbb2"),
                unreadMessagesCount: 0,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-15 19:12:26 +0000,
                lastReadMessageId: Optional("93dd2b8f-289d-40a8-bc23-87216599bdce"),
                unreadMessagesCount: 63,
                user: StreamChat.ChatUser
            ),
            StreamChat.ChatChannelRead(
                lastReadAt: 2024-03-23 18:54:42 +0000,
                lastReadMessageId: Optional("e10af15c-81d5-41aa-80bc-773e9642a94f"),
                unreadMessagesCount: 0,
                user: StreamChat.ChatUser
            )
        ],
        __muteDetails: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.MuteDetails>>,
        cooldownDuration: 0,
        extraData: ["disabled": StreamChat.RawJSON.bool(false)],
        __previewMessage: StreamChat.CoreDataLazy<Swift.Optional<StreamChat.ChatMessage>>
    )
| Controller: StreamChat.ChatChannelController

2024-03-24 02:54:45.385 SiteCapture[2920:d30b]


glennposadas avatar Mar 23 '24 18:03 glennposadas

Hi @nuno-vieira , after some debugging, I found out the reason of the delayed "seen" is this delayed markRead from chatChannelVC.

    open func channelController(
        _ channelController: ChatChannelController,
        didUpdateMessages changes: [ListChange<ChatMessage>]
    ) {
        messageListVC.setPreviousMessagesSnapshot(messages)
        messageListVC.setNewMessagesSnapshot(channelController.messages)
        messageListVC.updateMessages(with: changes) { [weak self] in
            guard let self = self else { return }

            if let unreadCount = channelController.channel?.unreadCount.messages, channelController.firstUnreadMessageId == nil && unreadCount == 0 {
                self.hasSeenFirstUnreadMessage = true
            }

            self.updateJumpToUnreadRelatedComponents()
            if self.shouldMarkChannelRead {
                self.throttler.execute {
                    self.markRead()
                }
            } else if !self.hasSeenFirstUnreadMessage {
                self.updateUnreadMessagesBannerRelatedComponents()
            }
        }
        viewPaginationHandler.updateElementsCount(with: channelController.messages.count)
    }

Is there a way to somehow override this function to remove the call to self.markRead(), or the throttler to make it a second? Removing the markRead() resolves my problem - only by unlocking the Pod.

glennposadas avatar Mar 25 '24 18:03 glennposadas

Hello @glennposadas!

The Throttler should actually be public so that you can customize it. We need to change this, indeed. Another thing that does not look right is that the default value for the Throttler is 3 seconds, which is very high. We also need to change this.

We will make this change as soon as possible, and we will let you know once that is fixed.

Just one more question, the problem in your case is that markRead() is performed even after you left the ChatChannelVC?

nuno-vieira avatar Mar 26 '24 00:03 nuno-vieira

Okay, great! Yes, it still gets triggered even after leaving the chat screen.

glennposadas avatar Mar 26 '24 03:03 glennposadas

Hi @glennposadas, my bad, actually the value of 3s is there for a reason. So we will discuss internally how we can solve this in the best way, and we will let you know once have discussed it 👍

nuno-vieira avatar Mar 26 '24 10:03 nuno-vieira

Thanks, @nuno-vieira . May I suggest improving the implementation of ChatChannelControllerDelegate's didUpdateMessages in ChatChannelVC?

It is open, however, there are properties that are internal functions called. I could've removed the line self.markRead().

glennposadas avatar Mar 27 '24 19:03 glennposadas

Hi @glennposadas,

At the moment, we don't want to make that public because we want to be careful about how markRead() is called so that it does not overload our servers.

The current solution we have in mind is to cancel the debouncer whenever we leave the Channel. In this case, it should fix the problem since we guarantee the markRead() is not executed after leaving the channel.

We just need to prioritise this issue, and once we start working on it, we will let you know 👍

Best, Nuno

nuno-vieira avatar Mar 28 '24 11:03 nuno-vieira

Sounds good! Thank you!

glennposadas avatar Mar 28 '24 18:03 glennposadas

Hi @nuno-vieira Just wondering if we have any updates on this? Thanks a lot!

glennposadas avatar May 01 '24 17:05 glennposadas

Hi @glennposadas, we have been busy with a lot of stuff, so we did not have the opportunity to work on this.

We should be able to pick up this one soon. I'll let you know once we do it 👍

Best, Nuno

nuno-vieira avatar May 03 '24 11:05 nuno-vieira

Hi @glennposadas!

Just to let you know we already have an open PR to fix this 👍

Best, Nuno

nuno-vieira avatar May 10 '24 15:05 nuno-vieira

Hi @glennposadas!

This is now available on the latest release 👍

Best, Nuno

nuno-vieira avatar May 13 '24 17:05 nuno-vieira

Thank you @nuno-vieira and your team for your hard work.

glennposadas avatar May 13 '24 17:05 glennposadas

Hi @nuno-vieira . I still experience this same issue. Do I open a new ticket?

I've checked your fix here:

https://github.com/GetStream/stream-chat-swift/pull/3193/files

Throttle isn't still overridable. Sometimes, when exiting the chat screen, the value of delay is 3 instead of 0 which causes random delay.

    func execute(_ action: @escaping () -> Void) {
        workItem?.cancel()

        let workItem = DispatchWorkItem { [weak self] in
            guard let workItem = self?.workItem, !workItem.isCancelled else { return }
            action()
            self?.previousRun = Date()
            self?.workItem = nil
        }

        self.workItem = workItem

        let timeSinceLastRun = Date().timeIntervalSince(previousRun)
        let delay = timeSinceLastRun > interval ? 0 : interval
        // If the delay is 0, we always execute the action immediately.
        // If the delay is bigger than 0, we only execute it if `latest` was enabled.
        if delay == 0 || delay > 0 && broadcastLatestEvent {
            print("----- delay ---> \(delay)")
            queue.asyncAfter(deadline: .now() + delay, execute: workItem)
        }
    }

I'm wondering if Throttling is the right approach for this 'preventing spamming of markRead()`, or Debouncing should be better.

glennposadas avatar May 14 '24 20:05 glennposadas

Hi @glennposadas!

Even with Throttling, cancelling the throttler should cancel the delayed request 🤔

One thing that looks suspicious is that, you say that when you leave the channel the didUpdateMessages delegate is called, how is that possible? Shouldn't your custom ChatChannelVC view be destroyed at this point? Do you have a reference for ChatChannelVC? The throttler will only be canceled if the viewWillDisappear is triggered.

nuno-vieira avatar May 14 '24 22:05 nuno-vieira

Hi @nuno-vieira it was suspicious indeed. It was an issue on my end and I was able to figure it out. Thanks again!

glennposadas avatar May 16 '24 15:05 glennposadas

Hi @nuno-vieira I just wanna say that while I've resolved the retain-cycle issue on my end (Adding callback to the tapping of chat title), the 3-second long throttle still causes me the same issue.

Example: The ChatChannelVC a second after its deinit, the callback from the throttle still happens.

glennposadas avatar May 21 '24 21:05 glennposadas

@glennposadas Maybe you are overriding the viewWillDisappear? Can you verify that the throttler is cancelled? Can you share some logs or video?

nuno-vieira avatar May 29 '24 13:05 nuno-vieira