Unread messages
The Unread Message Count feature shows users how many messages they missed while offline. Once they reconnect or log into the app again, they can get the number of messages published in a given channel while they were gone.
Chat SDK stores info about the timetoken of the last message the current user read on a given channel on the lastReadMessageTimetoken
property. lastReadMessageTimetoken
is available on the Membership
object.
This property is automatically set for a user when they first join (join()
) a given channel or are invited to it (invite()
and inviteMultiple()
). For all further updates of this property, you must decide what user actions will trigger methods that mark messages as read in your chat app - whether that's some user interaction on UI, like scrolling, your app going offline, or any other behavior.
Requires App Context and Message Persistence
To store message timetokens on the user-channel membership relationship at PubNub, you must enable App Context and Message Persistence for your app's keyset in the Admin Portal.
Get last read message
You can access the lastReadMessageTimetoken
property of the Membership
object to check what is the timetoken of the last message a user read on a given channel. lastReadMessageTimetoken
returns the last read message timetoken stored in the membership data between the channel and the current user. Use it to display markers on the message list denoting which messages haven't been read by the user yet.
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Get the timetoken of the last message read by the support_agent_15
user on the support
channel.
// Assuming you have a reference of type "ChatImpl" named "chat"
Task {
if let user = try await chat.getUser(userId: "support_agent_15") {
if let membership = try await user.getMemberships(filter: "channel.id == 'support'").memberships.first {
debugPrint("Last read message timetoken: \(String(describing: membership.lastReadMessageTimetoken))")
} else {
debugPrint("No memberships found for the \"support\" channel")
}
} else {
debugPrint("User not found")
}
}
Get unread messages count (one channel)
getUnreadMessagesCount()
returns the number of messages you didn't read on a given channel.
This includes all messages published after your last read timetoken, including messages sent by yourself and all other channel members. The method cannot filter messages by sender - it counts all unread messages regardless of who published them. You can display this number on UI in the channel list of your chat app.
Method signature
This method has the following signature:
membership.getUnreadMessagesCount() async throws -> UInt64?
Input
This method doesn't take any parameters.
Output
Parameter | Description |
---|---|
UInt64 | Retrieves from Message Persistence the number (count) of all messages unread by a given user on a given channel from the last read message. The method returns null when there is no last read message timetoken set on the MessageImpl object. |
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Get the number of all messages unread by the support_agent_15
user on the support
channel.
// Assuming you have a reference of type "ChatImpl" named "chat"
Task {
if let user = try await chat.getUser(userId: "support_agent_15") {
if let membership = try await user.getMemberships(filter: "channel.id == 'support'").memberships.first {
if let noOfUnreadMessages = try await membership.getUnreadMessagesCount() {
print("Unread messages count: \(noOfUnreadMessages)")
} else {
print("No unread messages count available")
}
} else {
debugPrint("No memberships found for the \"support\" channel")
}
} else {
debugPrint("User not found")
}
show all 16 linesGet unread messages count (all channels)
fetchUnreadMessagesCounts()
returns info on all messages you didn't read on joined channels that have unread messages.
This method only returns channels with unread message counts greater than 0 - channels with zero unread messages are filtered out. For each returned channel, this includes all messages published after your last read timetoken, including messages sent by yourself and all other channel members. While you can filter which channels to get unread counts for using the filter parameter (e.g., by channel type, membership status, or custom properties), the message count within each channel includes all messages after the last read timetoken regardless of who published them. You can display these counts in the UI in the channel list of your chat app.
The response includes pagination tokens that allow you to fetch more results if needed.
Method signature
This method has the following signature:
chat.fetchUnreadMessagesCounts(
limit: Int? = nil,
page: PubNubHashedPage? = nil,
filter: String? = nil,
sort: [PubNub.MembershipSortField] = [],
completion: ((Swift.Result<(countsByChannel: [GetUnreadMessagesCount<ChannelImpl, MembershipImpl>], page: PubNubHashedPage?), Error>) -> Void)? = nil
)
Input
Parameter | Description |
---|---|
limit Type: Int Default: nil | Number of objects to return in response. The default (and maximum) value is 100 . |
page Type: PubNubHashedPage Default: nil | Object used for pagination to define which previous or next result page you want to fetch. |
filter Type: String Default: nil | Expression used to filter which channel memberships to include in the results. Returns unread message counts only for channels whose membership properties satisfy the given expression. The filtering language is defined here. |
sort Type: [PubNub.MembershipSortField] Default: [] | Array of sorting criteria to sort by, and a sort direction. Available options are id , name , and updated . Use asc or desc to specify the sorting direction, or specify nil to take the default sorting direction (ascending). By default, the items are sorted by the last updated date. |
completion Type: ((Swift.Result<(countsByChannel: [GetUnreadMessagesCount<ChannelImpl, MembershipImpl>], page: PubNubHashedPage?), Error>) -> Void)? Default: nil | Completion closure called with the result of the operation. |
Output
Parameter | Description |
---|---|
Swift.Result<> Type: object | Result object containing either success data or an error. |
→ countsByChannel Type: [GetUnreadMessagesCount<ChannelImpl, MembershipImpl>] | Array of objects containing channel, membership, and count information. |
→ channel Type: ChannelImpl | Channel with unread messages. |
→ membership Type: MembershipImpl | Returned Membership object showing the user-channel data. |
→ count Type: UInt64 | Total number of messages unread by the current user on a given channel. |
→ page Type: PubNubHashedPage? | Object containing pagination information. |
→ start Type: string? | Token for fetching the next page of results. |
→ end Type: string? | Token for fetching the previous page of results. |
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Get the number of all messages unread by the support_agent_15
user on all joined channels.
// Assuming you have a reference of type "ChatImpl" named "chat"
chat.fetchUnreadMessagesCounts { result in
switch result {
case let .success(response):
// access the counts for each channel
let countsByChannel = response.countsByChannel
// iterate over unread message counts
countsByChannel.forEach { unreadCount in
print("Channel: \(unreadCount.channel.id)")
print("Unread messages count: \(unreadCount.count)")
}
// access pagination tokens if needed
let page = response.page
show all 20 linesMark messages as read (one channel)
setLastReadMessage()
and setLastReadMessageTimetoken()
let you set the timetoken of the last read message on a given channel to set a timeline from which you can count unread messages. You choose on your own which user action it is bound to.
Setting the last read message for users lets you implement the Read Receipts feature and monitor which channel member read which message.
Method signature
These methods take the following parameters:
-
setLastReadMessage()
membership.setLastReadMessage(
message: MessageImpl
) async throws -> MembershipImpl -
setLastReadMessageTimetoken()
membership.setLastReadMessageTimetoken(
_ timetoken: Timetoken
) async throws -> MembershipImpl
Input
Parameter | Required by setLastReadMessage() | Required by setLastReadMessageTimetoken() | Description |
---|---|---|---|
message Type: MessageImpl Default: n/a | Yes | No | Last read message on a given channel with the timestamp that gets added to the user-channel membership as the lastReadMessageTimetoken property. |
timetoken Type: Timetoken Default: n/a | No | Yes | Timetoken of the last read message on a given channel that gets added to the user-channel membership as the lastReadMessageTimetoken property. |
Output
Parameter | Description |
---|---|
MembershipImpl | Returned MembershipImpl object updated with the lastReadMessageTimetoken parameter. |
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Set the message with the 16200000000000001
timetoken as the last read message for the support_agent_15
user on the support
channel.
-
setLastReadMessage()
show all 16 lines// Assuming you have a reference of type "ChatImpl" named "chat"
Task {
if let user = try await chat.getUser(userId: "support_agent_15") {
if let membership = try await user.getMemberships(filter: "channel.id == 'support'").memberships.first {
if let message = try await membership.channel.getMessage(timetoken: 16200000000000001) {
let updatedMembership = try await membership.setLastReadMessage(message: message)
debugPrint("Successfully set the last read message")
debugPrint("Updated membership object: \(updatedMembership)")
} else {
debugPrint("Message not found")
}
}
} else {
debugPrint("User not found")
} -
setLastReadMessageTimetoken()
// Assuming you have a reference of type "ChatImpl" named "chat"
Task {
if let user = try await chat.getUser(userId: "support_agent_15") {
if let membership = try await user.getMemberships(filter: "channel.id == 'support'").memberships.first {
let updatedMembership = try await membership.setLastReadMessageTimetoken(16200000000000001)
debugPrint("Successfully set the last read message timetoken")
debugPrint("Updated membership object: \(updatedMembership)")
}
} else {
debugPrint("User not found")
}
}
Mark messages as read (all channels)
markAllMessagesAsRead()
lets you mark as read all messages you didn't read on all joined channels.
Method signature
This method has the following signature:
chat.markAllMessagesAsRead(
limit: Int? = nil,
page: PubNubHashedPage? = nil,
filter: String? = nil,
sort: [PubNub.MembershipSortField] = []
) async throws -> (memberships: [MembershipImpl], page: PubNubHashedPage?)
Input
Parameter | Description |
---|---|
limit Type: Int Default: 100 | Number of objects to return in response. The default (and maximum) value is 100 . |
page Type: PubNubHashedPage Default: n/a | Object used for pagination to define which previous or next result page you want to fetch. |
filter Type: String Default: n/a | Expression used to filter the results. Returns only these messages whose properties satisfy the given expression. The filter language is defined here. |
sort Type: [PubNub.MembershipSortField] Default: listOf() | Key-value pair of a property to sort by, and a sort direction. Available options are id , name , and updated . Use asc or desc to specify the sorting direction, or specify null to take the default sorting direction (ascending). For example: {name: "asc"} . By default, the items are sorted by the last updated date. |
Output
Parameter | Description |
---|---|
(memberships: [MembershipImpl], page: PubNubHashedPage?) | Returned object with a list of memberships and a page object with these fields: next , prev , total , and status . |
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Mark the total number of 50 messages as read and specify you want to fetch the results from the next page using a string that was previously returned from the PubNub server.
// Assuming you have a reference of type "ChatImpl" named "chat".
// Define your next page string for pagination
let nextPageString = "your_next_page_string"
Task {
let response = try await chat.markAllMessagesAsRead(
limit: 50,
page: PubNubHashedPageBase(start: nextPageString)
)
// Iterate over the returned memberships and print channel identifier
response.memberships.forEach { membership in
debugPrint("Channel: \(membership.channel.id) marked as read.")
}
// The next page for subsequent results
debugPrint(String(describing: response.page))
show all 16 linesGet unread messages count (all channels) (deprecated)
Deprecated
The getUnreadMessagesCounts()
method is deprecated. Use fetchUnreadMessagesCounts()
instead.
getUnreadMessagesCounts()
returns info on all messages you didn't read on joined channels that have unread messages.
This method only returns channels with unread message counts greater than 0 - channels with zero unread messages are filtered out. For each returned channel, this includes all messages published after your last read timetoken, including messages sent by yourself and all other channel members. The method cannot filter messages by sender - it counts all unread messages regardless of who published them. You can display this number on UI in the channel list of your chat app.
Method signature
This method has the following signature:
chat.getUnreadMessagesCount(
limit: Int? = nil,
page: PubNubHashedPage? = nil,
filter: String? = nil,
sort: [PubNub.MembershipSortField] = []
) async throws -> [GetUnreadMessagesCount<ChannelImpl, MembershipImpl>]
Input
Parameter | Description |
---|---|
limit Type: Int Default: 100 | Number of objects to return in response. The default (and maximum) value is 100 . |
page Type: PubNubHashedPage Default: n/a | Object used for pagination to define which previous or next result page you want to fetch. |
filter Type: String Default: n/a | Expression used to filter which channel memberships to include in the results. Returns unread message counts only for channels whose membership properties satisfy the given expression. The filter language is defined here. |
sort Type: [PubNub.MembershipSortField] Default: listOf() | Key-value pair of a property to sort by, and a sort direction. Available options are id , name , and updated . Use asc or desc to specify the sorting direction, or specify null to take the default sorting direction (ascending). For example: {name: "asc"} . By default, the items are sorted by the last updated date. |
Output
Parameter | Description |
---|---|
[GetUnreadMessagesCount<ChannelImpl, MembershipImpl>] | An array of GetUnreadMessagesCount representing unread messages for the current user in a given channel. It returns these details: channel , membership , count . |
Sample code
Sample code
The code samples in Swift Chat SDK focus on asynchronous code execution.
You can also write synchronous code as the parameters are shared between the async and sync methods but we don't provide usage examples of such.
Get the number of all messages unread by the support_agent_15
user on all joined channels.
// Assuming you have a reference of type "ChatImpl" named "chat"
Task {
// Returns info on all messages you didn't read on all joined channels
let unreadMessagesResult = try await chat.getUnreadMessagesCount()
// Iterate over an array of `GetUnreadMessagesCount`, printing details about each channel
// and its number of unread messages
unreadMessagesResult.forEach { unreadCount in
debugPrint("Channel: \(unreadCount.channel.id)")
debugPrint("Unread messages count: \(unreadCount.count)")
}
}