mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-22 07:59:48 +00:00
core, ui: don't count muted chats in profile unread counter, count chats marked unread
Unread counter above the profiles counted unread mentions in groups with mentions-only notifications, but nothing in muted chats, so two profiles with chats that both show as muted could show different counters. getUsersInfo now also counts chats marked unread - 1 per chat, unless the chat has unread items counted already. Muted chats are not counted at all, including when they are marked unread. Clients use the same rule in Chat.userUnreadCount and update the counter by the difference between what the chat contributed before and after, so that muting a chat or marking it unread updates the counter without reloading.
This commit is contained in:
@@ -567,12 +567,15 @@ final class ChatModel: ObservableObject {
|
||||
// Spec: spec/state.md#updateChatInfo
|
||||
func updateChatInfo(_ cInfo: ChatInfo) {
|
||||
if let i = getChatIndex(cInfo.id) {
|
||||
let prevUserUnread = chats[i].userUnreadCount
|
||||
if case let .group(groupInfo, groupChatScope) = cInfo, groupChatScope != nil {
|
||||
chats[i].chatInfo = .group(groupInfo: groupInfo, groupChatScope: nil)
|
||||
} else {
|
||||
chats[i].chatInfo = cInfo
|
||||
}
|
||||
chats[i].created = Date.now
|
||||
// muted chat does not count towards user unread counter, so it is updated when notifications change
|
||||
if let user = currentUser { changeUnreadCounter(user: user, by: chats[i].userUnreadCount - prevUserUnread) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,8 +962,10 @@ final class ChatModel: ObservableObject {
|
||||
func markChatUnread(_ cInfo: ChatInfo, unreadChat: Bool = true) {
|
||||
_updateChat(cInfo.id) { chat in
|
||||
let wasUnread = chat.unreadTag
|
||||
let prevUserUnread = chat.userUnreadCount
|
||||
chat.chatStats.unreadChat = unreadChat
|
||||
ChatTagsModel.shared.updateChatTagRead(chat, wasUnread: wasUnread)
|
||||
self.changeUnreadCounter(user: self.currentUser!, by: chat.userUnreadCount - prevUserUnread)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1103,11 +1108,12 @@ final class ChatModel: ObservableObject {
|
||||
|
||||
func changeUnreadCounter(_ chatIndex: Int, by count: Int, unreadMentions: Int) {
|
||||
let wasUnread = chats[chatIndex].unreadTag
|
||||
let prevUserUnread = chats[chatIndex].userUnreadCount
|
||||
let stats = chats[chatIndex].chatStats
|
||||
chats[chatIndex].chatStats.unreadCount = stats.unreadCount + count
|
||||
chats[chatIndex].chatStats.unreadMentions = stats.unreadMentions + unreadMentions
|
||||
ChatTagsModel.shared.updateChatTagRead(chats[chatIndex], wasUnread: wasUnread)
|
||||
changeUnreadCounter(user: currentUser!, by: count)
|
||||
changeUnreadCounter(user: currentUser!, by: chats[chatIndex].userUnreadCount - prevUserUnread)
|
||||
}
|
||||
|
||||
func increaseUnreadCounter(user: any UserLike) {
|
||||
@@ -1115,10 +1121,7 @@ final class ChatModel: ObservableObject {
|
||||
}
|
||||
|
||||
func decreaseUnreadCounter(user: any UserLike, chat: Chat) {
|
||||
let by = chat.chatInfo.chatSettings?.enableNtfs == .mentions
|
||||
? chat.chatStats.unreadMentions
|
||||
: chat.chatStats.unreadCount
|
||||
decreaseUnreadCounter(user: user, by: by)
|
||||
decreaseUnreadCounter(user: user, by: chat.userUnreadCount)
|
||||
}
|
||||
|
||||
func decreaseUnreadCounter(user: any UserLike, by: Int = 1) {
|
||||
@@ -1126,6 +1129,7 @@ final class ChatModel: ObservableObject {
|
||||
}
|
||||
|
||||
private func changeUnreadCounter(user: any UserLike, by: Int) {
|
||||
if by == 0 { return }
|
||||
if let i = users.firstIndex(where: { $0.user.userId == user.userId }) {
|
||||
users[i].unreadCount += by
|
||||
}
|
||||
@@ -1136,11 +1140,7 @@ final class ChatModel: ObservableObject {
|
||||
func totalUnreadCountForAllUsers() -> Int {
|
||||
var unread: Int = 0
|
||||
for chat in chats {
|
||||
switch chat.chatInfo.chatSettings?.enableNtfs {
|
||||
case .all: unread += chat.chatStats.unreadCount
|
||||
case .mentions: unread += chat.chatStats.unreadMentions
|
||||
default: ()
|
||||
}
|
||||
unread += chat.userUnreadCount
|
||||
}
|
||||
for u in users {
|
||||
if !u.user.activeUser {
|
||||
@@ -1391,6 +1391,15 @@ final class Chat: ObservableObject, Identifiable, ChatLike {
|
||||
}
|
||||
}
|
||||
|
||||
// what this chat adds to unread counter of its user profile - has to match getUsersInfo in Profiles.hs
|
||||
var userUnreadCount: Int {
|
||||
switch chatInfo.chatSettings?.enableNtfs {
|
||||
case .all: chatStats.unreadCount > 0 ? chatStats.unreadCount : (chatStats.unreadChat ? 1 : 0)
|
||||
case .mentions: chatStats.unreadMentions > 0 ? chatStats.unreadMentions : (chatStats.unreadChat ? 1 : 0)
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
|
||||
var id: ChatId { get { chatInfo.id } }
|
||||
|
||||
var viewId: String { get { "\(chatInfo.id) \(created.timeIntervalSince1970)" } }
|
||||
|
||||
@@ -1869,6 +1869,8 @@ func apiCallStatus(_ contact: Contact, _ status: String) async throws {
|
||||
|
||||
func markChatRead(_ im: ItemsModel, _ chat: Chat) async {
|
||||
do {
|
||||
// markAllChatItemsRead resets chat stats of the same chat object, so it has to be read before
|
||||
let unreadChat = chat.chatStats.unreadChat
|
||||
if chat.chatStats.unreadCount > 0 {
|
||||
let cInfo = chat.chatInfo
|
||||
try await apiChatRead(type: cInfo.chatType, id: cInfo.apiId)
|
||||
@@ -1876,7 +1878,7 @@ func markChatRead(_ im: ItemsModel, _ chat: Chat) async {
|
||||
withAnimation { ChatModel.shared.markAllChatItemsRead(im, cInfo) }
|
||||
}
|
||||
}
|
||||
if chat.chatStats.unreadChat {
|
||||
if unreadChat {
|
||||
await markChatUnread(chat, unreadChat: false)
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user