Unread

LAST EDIT Feb 27 2021

The most common use case for client level events are unread counts. Here's an example of a complete unread count integration for your chat app. As a first step we get the unread count when the user connects:

1
2
3
4
const user = await client.connectUser({ id: 'myid' }, token); 
 
// response.me.total_unread_count returns the unread count 
// response.me.unread_channels returns the count of channels with unread messages
1
2
3
4
final response = await client.setUser(user, "CHAT_USER_TOKEN"); 
 
print("There are ${response.me.unreadChannels} unread channels"); 
print("There are ${response.me.totalUnreadCount} unread messages");
1
2
3
4
5
6
7
client.connectUser(User("user-id"), "{{ chat_user_token }}").enqueue { result -> 
    if (result.isSuccess) { 
        val user = result.data().user 
        val unreadChannels = user.unreadChannels 
        val totalUnreadCount = user.totalUnreadCount 
    } 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Unread count globally. 
let subscription = Client.shared.subscribeToUnreadCount { count in 
    // handle new unread count 
		// count.channels is unread channels 
		// count.messages is unread messages 
} 
// Cancel subscription when you want to stop receiving events 
subscription.cancel() 
 
// Unread count for a channel. 
let channel = Client.shared.channel(type: .messaging, id: "general") 
let subscription = channel.subscribeToUnreadCount { count in 
    // handle new unread count 
} 
// Cancel subscription when you want to stop receiving events 
subscription.cancel()
1
2
3
4
5
6
7
8
9
User user = new User(); 
user.setId("user-id"); 
client.connectUser(user, "{{ chat_user_token }}").enqueue(result -> { 
    if (result.isSuccess()) { 
        User userRes = result.data().getUser(); 
        int unreadChannels = userRes.getUnreadChannels(); 
        int totalUnreadCount = userRes.getTotalUnreadCount(); 
    } 
});

By default the UI component SDKs (React, React Native, ...) mark messages as read automatically when the channel is visible. You can also make the call manually like this:

1
2
// mark all messages on a channel as read 
await channel.markRead();
1
await channel.markRead();
1
2
3
4
5
6
7
channelClient.markRead().enqueue { result -> 
    if (result.isSuccess) { 
        // Messages in the channel marked as read 
    } else { 
        // Handle result.error() 
    } 
}
1
2
3
4
5
let channel = Client.shared.channel(type: .messaging, id: "general") 
 
channel.markRead { (result) in 
    // handle result 
}
1
2
3
4
5
6
7
channelClient.markRead().enqueue(result -> { 
    if (result.isSuccess()) { 
        // Messages in the channel marked as read 
    } else { 
        // Handle result.error() 
    } 
});

While you're using the app, the unread count can change. A user can be added to a channel, a new message can be created, or the user can mark the messages as seen on another tab/device.

Unread counts are only stored and returned at connection time for channel members.

The markRead function can also be executed server-side by passing a user ID as shown in the example below:

1
2
// mark all messages on a channel as read (server side) 
await channel.markRead({ user_id: 'foo' });
1
2
// mark all messages on a channel as read (server side) 
$mark = $channel->markRead('user-id');

To support updating the unread count in real time, you can listen to these events:

  • notification.message_new

  • notification.mark_read

These two events include the fields total_unread_count and unread_channels. You can listen to them all at once like this:

1
2
3
4
5
6
7
8
9
client.on((event) => { 
     if (event.total_unread_count !== undefined) { 
         console.log(event.total_unread_count); 
     } 
 
     if (event.unread_channels !== undefined) { 
         console.log(event.unread_channels); 
     } 
});
1
2
3
4
5
6
7
client.on().where((Event event) => event.unreadChannels != null).listen((Event event) { 
  print("Unread channels count changed to:${event.unreadChannels}"); 
}); 
 
client.on().where((Event event) => event.totalUnreadCount != null).listen((Event event) { 
  print("Unread messages count changed to:${event.totalUnreadCount}"); 
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
channelClient.subscribeFor( 
    NewMessageEvent::class, 
    NotificationMessageNewEvent::class, 
    MarkAllReadEvent::class, 
    NotificationMarkReadEvent::class 
) { event -> 
    when (event) { 
        is NewMessageEvent -> { 
            val unreadChannels = event.unreadChannels 
            val totalUnreadCount = event.totalUnreadCount 
        } 
        is NotificationMessageNewEvent -> { 
            val unreadChannels = event.unreadChannels 
            val totalUnreadCount = event.totalUnreadCount 
        } 
        is MarkAllReadEvent -> { 
            val unreadChannels = event.unreadChannels 
            val totalUnreadCount = event.totalUnreadCount 
        } 
        is NotificationMarkReadEvent -> { 
            val unreadChannels = event.unreadChannels 
            val totalUnreadCount = event.totalUnreadCount 
        } 
    } 
}
1
2
3
4
5
6
7
8
9
10
11
let channel = Client.shared.channel(type: .messaging, id: "general") 
 
let subscription = channel.subscribe(forEvents: [.notificationAddedToChannel, 
                                                 .notificationRemovedFromChannel, 
                                                 .notificationMessageNew, 
                                                 .notificationMarkRead]) { (event) in 
    // handle event 
} 
 
// Cancel subscription when you want to stop receiving events 
subscription.cancel()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
channelClient.subscribeFor( 
        new Class[]{ 
                NewMessageEvent.class, 
                NotificationMessageNewEvent.class, 
                MarkAllReadEvent.class, 
                NotificationMarkReadEvent.class 
        }, 
        event -> { 
            if (event instanceof NewMessageEvent) { 
                NewMessageEvent newMessageEvent = (NewMessageEvent) event; 
                Integer unreadChannels = newMessageEvent.getUnreadChannels(); 
                Integer totalUnreadCount = newMessageEvent.getTotalUnreadCount(); 
            } else if (event instanceof NotificationMessageNewEvent) { 
                NotificationMessageNewEvent notificationMessageNewEvent = (NotificationMessageNewEvent) event; 
                Integer unreadChannels = notificationMessageNewEvent.getUnreadChannels(); 
                Integer totalUnreadCount = notificationMessageNewEvent.getTotalUnreadCount(); 
            } else if (event instanceof MarkAllReadEvent) { 
                MarkAllReadEvent markAllReadEvent = (MarkAllReadEvent) event; 
                Integer unreadChannels = markAllReadEvent.getUnreadChannels(); 
                Integer totalUnreadCount = markAllReadEvent.getTotalUnreadCount(); 
            } else if (event instanceof NotificationMarkReadEvent) { 
                NotificationMarkReadEvent notificationMarkReadEvent = (NotificationMarkReadEvent) event; 
                Integer unreadChannels = notificationMarkReadEvent.getUnreadChannels(); 
                Integer totalUnreadCount = notificationMarkReadEvent.getTotalUnreadCount(); 
            } 
        } 
);