fix(unread): fix badge disappearing because of wrong calculation

Fixes #10058

We were calling `updateParentBadgeNotifications` with wrong values, so we basically removed the badge all the time by accident.
Now, we calculate the unread messages and messages from the service's cache.
Also, we still called `updateParentBadgeNotifications` when a contact is updated, as if the contact requests still went in the old contact request popup.
This commit is contained in:
Jonathan Rainville 2023-03-28 15:25:33 -04:00
parent f360a9c193
commit 44b9522edb
10 changed files with 104 additions and 44 deletions

View File

@ -152,6 +152,9 @@ proc init*(self: Controller) =
let args = message_service.MessagesMarkedAsReadArgs(e)
# update chat entity in chat service
var chat = self.chatService.getChatById(args.chatId)
if ((self.isCommunitySection and chat.communityId != self.sectionId) or
(not self.isCommunitySection and chat.communityId != "")):
return
chat.unviewedMessagesCount = 0
chat.unviewedMentionsCount = 0
self.chatService.updateOrAddChat(chat)
@ -181,14 +184,14 @@ proc init*(self: Controller) =
var args = ChatUpdateArgs(e)
for chat in args.chats:
let belongsToCommunity = chat.communityId.len > 0
self.delegate.addChatIfDontExist(chat, belongsToCommunity, self.events, self.settingsService, self.nodeConfigurationService,
self.delegate.addOrUpdateChat(chat, belongsToCommunity, self.events, self.settingsService, self.nodeConfigurationService,
self.contactService, self.chatService, self.communityService, self.messageService, self.gifService,
self.mailserversService, setChatAsActive = false)
self.events.on(SIGNAL_CHAT_CREATED) do(e: Args):
var args = CreatedChatArgs(e)
let belongsToCommunity = args.chat.communityId.len > 0
self.delegate.addChatIfDontExist(args.chat, belongsToCommunity, self.events, self.settingsService, self.nodeConfigurationService,
self.delegate.addOrUpdateChat(args.chat, belongsToCommunity, self.events, self.settingsService, self.nodeConfigurationService,
self.contactService, self.chatService, self.communityService, self.messageService, self.gifService,
self.mailserversService, setChatAsActive = true)
@ -203,7 +206,7 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_COMMUNITY_CHANNEL_CREATED) do(e:Args):
let args = CommunityChatArgs(e)
let belongsToCommunity = args.chat.communityId.len > 0
self.delegate.addChatIfDontExist(args.chat, belongsToCommunity, self.events, self.settingsService, self.nodeConfigurationService,
self.delegate.addOrUpdateChat(args.chat, belongsToCommunity, self.events, self.settingsService, self.nodeConfigurationService,
self.contactService, self.chatService, self.communityService, self.messageService, self.gifService,
self.mailserversService, setChatAsActive = true)
@ -392,6 +395,10 @@ proc getChats*(self: Controller, communityId: string, categoryId: string): seq[C
proc getAllChats*(self: Controller, communityId: string): seq[ChatDto] =
return self.communityService.getAllChats(communityId)
proc sectionUnreadMessagesAndMentionsCount*(self: Controller, communityId: string):
tuple[unviewedMessagesCount: int, unviewedMentionsCount: int] =
return self.chatService.sectionUnreadMessagesAndMentionsCount(communityId)
proc asyncGetChats*(self: Controller) =
self.chatService.asyncGetChatsByChannelGroupId(self.sectionId)
@ -431,7 +438,7 @@ proc getOneToOneChatNameAndImage*(self: Controller, chatId: string):
proc createOneToOneChat*(self: Controller, communityID: string, chatId: string, ensName: string) =
let response = self.chatService.createOneToOneChat(communityID, chatId, ensName)
if(response.success):
self.delegate.addChatIfDontExist(response.chatDto, false, self.events, self.settingsService, self.nodeConfigurationService,
self.delegate.addOrUpdateChat(response.chatDto, false, self.events, self.settingsService, self.nodeConfigurationService,
self.contactService, self.chatService, self.communityService, self.messageService,
self.gifService, self.mailserversService)
@ -501,14 +508,14 @@ proc makeAdmin*(self: Controller, communityID: string, chatId: string, pubKey: s
proc createGroupChat*(self: Controller, communityID: string, groupName: string, pubKeys: seq[string]) =
let response = self.chatService.createGroupChat(communityID, groupName, pubKeys)
if(response.success):
self.delegate.addChatIfDontExist(response.chatDto, false, self.events, self.settingsService, self.nodeConfigurationService,
self.delegate.addOrUpdateChat(response.chatDto, false, self.events, self.settingsService, self.nodeConfigurationService,
self.contactService, self.chatService, self.communityService, self.messageService,
self.gifService, self.mailserversService)
proc joinGroupChatFromInvitation*(self: Controller, groupName: string, chatId: string, adminPK: string) =
let response = self.chatService.createGroupChatFromInvitation(groupName, chatId, adminPK)
if(response.success):
self.delegate.addChatIfDontExist(response.chatDto, false, self.events, self.settingsService, self.nodeConfigurationService,
self.delegate.addOrUpdateChat(response.chatDto, false, self.events, self.settingsService, self.nodeConfigurationService,
self.contactService, self.chatService, self.communityService, self.messageService,
self.gifService, self.mailserversService)

View File

@ -86,7 +86,7 @@ method doesCatOrChatExist*(self: AccessInterface, chatId: string): bool {.base.}
method doesTopLevelChatExist*(self: AccessInterface, chatId: string): bool {.base.} =
raise newException(ValueError, "No implementation available")
method addChatIfDontExist*(self: AccessInterface,
method addOrUpdateChat*(self: AccessInterface,
chat: ChatDto,
belongsToCommunity: bool,
events: UniqueUUIDEventEmitter,

View File

@ -444,6 +444,13 @@ QtObject:
let modelIndex = self.createIndex(index, 0, nil)
self.dataChanged(modelIndex, modelIndex, @[ModelRole.HasUnreadMessages.int, ModelRole.NotificationsCount.int])
proc incrementNotificationsForItemByIdAndGetNotificationCount*(self: Model, id: string): int =
let index = self.getItemIdxById(id)
if index == -1:
return 0
self.updateNotificationsForItemById(id, hasUnreadMessages = true, self.items[index].notificationsCount + 1)
return self.items[index].notificationsCount
proc updateLastMessageTimestampOnItemById*(self: Model, id: string, lastMessageTimestamp: int) =
let index = self.getItemIdxById(id)
if index == -1:
@ -454,13 +461,6 @@ QtObject:
let modelIndex = self.createIndex(index, 0, nil)
self.dataChanged(modelIndex, modelIndex, @[ModelRole.LastMessageTimestamp.int])
proc getAllNotifications*(self: Model): tuple[hasNotifications: bool, notificationsCount: int] =
result.hasNotifications = false
result.notificationsCount = 0
for i in 0 ..< self.items.len:
result.hasNotifications = result.hasNotifications or self.items[i].hasUnreadMessages
result.notificationsCount = result.notificationsCount + self.items[i].notificationsCount
proc reorderChatById*(
self: Model,
chatId: string,

View File

@ -68,7 +68,7 @@ proc buildChatSectionUI(self: Module,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service)
proc addChatIfDontExist(self: Module,
proc addOrUpdateChat(self: Module,
chat: ChatDto,
channelGroup: ChannelGroupDto,
belongsToCommunity: bool,
@ -221,7 +221,7 @@ proc buildChatSectionUI(
categoryPosition = category.position
break
self.addChatIfDontExist(
self.addOrUpdateChat(
chatDto,
channelGroup,
belongsToCommunity = chatDto.communityId.len > 0,
@ -472,13 +472,19 @@ method getChatContentModule*(self: Module, chatId: string): QVariant =
return self.chatContentModules[chatId].getModuleAsVariant()
proc updateParentBadgeNotifications(self: Module, sectionHasUnreadMessagesArg: bool = false, unviewedMentionsCountArg: int = 0) =
proc updateParentBadgeNotifications(self: Module) =
let (unviewedMessagesCount, unviewedMentionsCount) = self.controller.sectionUnreadMessagesAndMentionsCount(
self.controller.getMySectionId()
)
self.delegate.onNotificationsUpdated(
self.controller.getMySectionId(),
sectionHasUnreadMessagesArg,
unviewedMentionsCountArg
unviewedMessagesCount > 0,
unviewedMentionsCount
)
proc incrementParentBadgeNotifications(self: Module) =
self.delegate.onNotificationsIncremented(self.controller.getMySectionId())
proc updateBadgeNotifications(self: Module, chatId: string, hasUnreadMessages: bool, unviewedMentionsCount: int) =
# update model of this module (appropriate chat from the chats list (chats model))
self.view.chatsModel().updateNotificationsForItemById(chatId, hasUnreadMessages, unviewedMentionsCount)
@ -486,7 +492,16 @@ proc updateBadgeNotifications(self: Module, chatId: string, hasUnreadMessages: b
if (self.chatContentModules.contains(chatId)):
self.chatContentModules[chatId].onNotificationsUpdated(hasUnreadMessages, unviewedMentionsCount)
# update parent module
self.updateParentBadgeNotifications(hasUnreadMessages, unviewedMentionsCount)
self.updateParentBadgeNotifications()
proc incrementBadgeNotifications(self: Module, chatId: string) =
if self.chatsLoaded:
let notificationCount = self.view.chatsModel().incrementNotificationsForItemByIdAndGetNotificationCount(chatId)
# update child module
if (self.chatContentModules.contains(chatId)):
self.chatContentModules[chatId].onNotificationsUpdated(hasUnreadMessages = true, notificationCount)
# update parent module
self.incrementParentBadgeNotifications()
method updateLastMessageTimestamp*(self: Module, chatId: string, lastMessageTimestamp: int) =
self.view.chatsModel().updateLastMessageTimestampOnItemById(chatId, lastMessageTimestamp)
@ -850,8 +865,6 @@ method onContactAdded*(self: Module, publicKey: string) =
if (contact.isContact):
self.switchToOrCreateOneToOneChat(publicKey)
self.updateParentBadgeNotifications()
method acceptAllContactRequests*(self: Module) =
let pubKeys = self.view.contactRequestsModel().getItemIds()
for pk in pubKeys:
@ -862,7 +875,6 @@ method dismissContactRequest*(self: Module, publicKey: string) =
method onContactRejected*(self: Module, publicKey: string) =
self.view.contactRequestsModel().removeItemById(publicKey)
self.updateParentBadgeNotifications()
method dismissAllContactRequests*(self: Module) =
let pubKeys = self.view.contactRequestsModel().getItemIds()
@ -875,7 +887,6 @@ method blockContact*(self: Module, publicKey: string) =
method onContactBlocked*(self: Module, publicKey: string) =
self.view.contactRequestsModel().removeItemById(publicKey)
self.view.chatsModel().changeBlockedOnItemById(publicKey, blocked=true)
self.updateParentBadgeNotifications()
method onContactUnblocked*(self: Module, publicKey: string) =
self.view.chatsModel().changeBlockedOnItemById(publicKey, blocked=false)
@ -891,7 +902,6 @@ method onContactDetailsUpdated*(self: Module, publicKey: string) =
not self.view.contactRequestsModel().isContactWithIdAdded(publicKey)):
let item = self.createItemFromPublicKey(publicKey)
self.view.contactRequestsModel().addItem(item)
self.updateParentBadgeNotifications()
singletonInstance.globalEvents.showNewContactRequestNotification("New Contact Request",
fmt "{contactDetails.defaultDisplayName} added you as contact",
singletonInstance.userProfile.getPubKey())
@ -914,10 +924,6 @@ method onNewMessagesReceived*(self: Module, sectionIdMsgBelongsTo: string, chatI
let chatDetails = self.controller.getChatDetails(chatIdMsgBelongsTo)
# Badge notification
let showBadge = (not chatDetails.muted and unviewedMessagesCount > 0) or unviewedMentionsCount > 0
self.updateBadgeNotifications(chatIdMsgBelongsTo, showBadge, unviewedMentionsCount)
if (chatDetails.muted):
# No need to send a notification
return
@ -965,8 +971,8 @@ method onMeMentionedInEditedMessage*(self: Module, chatId: string, editedMessage
(editedMessage.communityId.len > 0 and
self.controller.getMySectionId() != editedMessage.communityId)):
return
var (sectionHasUnreadMessages, sectionNotificationCount) = self.view.chatsModel().getAllNotifications()
self.updateBadgeNotifications(chatId, sectionHasUnreadMessages, sectionNotificationCount + 1)
self.incrementBadgeNotifications(chatId)
method addGroupMembers*(self: Module, chatId: string, pubKeys: string) =
self.controller.addGroupMembers(chatId, self.convertPubKeysToJson(pubKeys))
@ -1117,7 +1123,7 @@ method reorderCommunityChat*(self: Module, categoryId: string, chatId: string, p
method setLoadingHistoryMessagesInProgress*(self: Module, isLoading: bool) =
self.view.setLoadingHistoryMessagesInProgress(isLoading)
proc addChatIfDontExist(self: Module,
proc addOrUpdateChat(self: Module,
chat: ChatDto,
channelGroup: ChannelGroupDto,
belongsToCommunity: bool,
@ -1131,15 +1137,25 @@ proc addChatIfDontExist(self: Module,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service,
setChatAsActive: bool = true) =
if not self.chatsLoaded:
return
let sectionId = self.controller.getMySectionId()
if(belongsToCommunity and sectionId != chat.communityId or
not belongsToCommunity and sectionId != singletonInstance.userProfile.getPubKey()):
return
if self.doesCatOrChatExist(chat.id):
let chatExists = self.doesCatOrChatExist(chat.id)
if not self.chatsLoaded or chatExists:
# Update badges
var hasUnreadMessages = false
if not chat.muted:
hasUnreadMessages = chat.unviewedMessagesCount > 0
self.updateBadgeNotifications(chat.id, hasUnreadMessages, chat.unviewedMentionsCount)
if not self.chatsLoaded:
return
if chatExists:
if (chat.chatType == ChatType.PrivateGroupChat):
self.onGroupChatDetailsUpdated(chat.id, chat.name, chat.color, chat.icon)
elif (chat.chatType != ChatType.OneToOne):
@ -1162,7 +1178,7 @@ proc addChatIfDontExist(self: Module,
setChatAsActive,
)
method addChatIfDontExist*(self: Module,
method addOrUpdateChat*(self: Module,
chat: ChatDto,
belongsToCommunity: bool,
events: UniqueUUIDEventEmitter,
@ -1175,7 +1191,7 @@ method addChatIfDontExist*(self: Module,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service,
setChatAsActive: bool = true) =
self.addChatIfDontExist(
self.addOrUpdateChat(
chat,
ChannelGroupDto(),
belongsToCommunity,

View File

@ -123,6 +123,9 @@ method onNotificationsUpdated*(self: AccessInterface, sectionId: string, section
sectionNotificationCount: int) {.base.} =
raise newException(ValueError, "No implementation available")
method onNotificationsIncremented*(self: AccessInterface, sectionId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onNotificationsIncreased*(self: AccessInterface, sectionId: string, addedSectionNotificationCount: bool,
sectionNotificationCount: int) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -827,6 +827,9 @@ method onNotificationsUpdated[T](self: Module[T], sectionId: string, sectionHasU
sectionNotificationCount: int) =
self.view.model().updateNotifications(sectionId, sectionHasUnreadMessages, sectionNotificationCount)
method onNotificationsIncremented[T](self: Module[T], sectionId: string) =
self.view.model().incrementNotifications(sectionId)
method onNetworkConnected[T](self: Module[T]) =
self.view.setConnected(true)

View File

@ -1,11 +1,10 @@
import NimQml, Tables, strutils, strformat
import json, json_serialization
import json
import section_item, member_model
import ../main/communities/tokens/models/token_item
type
ModelRole {.pure.} = enum
Id = UserRole + 1
@ -261,6 +260,7 @@ QtObject:
self.items[index].muted = muted
let dataIndex = self.createIndex(index, 0, nil)
defer: dataIndex.delete
self.dataChanged(dataIndex, dataIndex, @[ModelRole.Muted.int])
@ -271,6 +271,7 @@ QtObject:
self.items[index] = item
let dataIndex = self.createIndex(index, 0, nil)
defer: dataIndex.delete
self.dataChanged(dataIndex, dataIndex, @[
ModelRole.Name.int,
ModelRole.Description.int,
@ -330,11 +331,13 @@ QtObject:
for i in 0 ..< self.items.len:
if(self.items[i].active):
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.items[i].active = false
self.dataChanged(index, index, @[ModelRole.Active.int])
if(self.items[i].id == id):
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.items[i].active = true
self.items[i].loaderActive = true
@ -349,6 +352,7 @@ QtObject:
for i in 0 ..< self.items.len:
if(self.items[i].sectionType == sectionType):
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.items[i].enabled = value
self.dataChanged(index, index, @[ModelRole.Enabled.int])
else:
@ -386,16 +390,30 @@ QtObject:
for i in 0 ..< self.items.len:
if(self.items[i].id == id):
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.items[i].hasNotification = hasNotification
self.items[i].notificationsCount = notificationsCount
self.dataChanged(index, index, @[ModelRole.HasNotification.int, ModelRole.NotificationsCount.int])
self.notificationsCountChanged()
return
proc incrementNotifications*(self: SectionModel, id: string) =
let index = self.getItemIndex(id)
if (index == -1):
return
self.items[index].hasNotification = true
self.items[index].notificationsCount = self.items[index].notificationsCount + 1
let modelIndex = self.createIndex(index, 0, nil)
defer: modelIndex.delete
self.dataChanged(modelIndex, modelIndex, @[ModelRole.HasNotification.int, ModelRole.NotificationsCount.int])
self.notificationsCountChanged()
proc appendCommunityToken*(self: SectionModel, id: string, item: TokenItem) =
for i in 0 ..< self.items.len:
if(self.items[i].id == id):
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.items[i].appendCommunityToken(item)
self.dataChanged(index, index, @[ModelRole.CommunityTokensModel.int])
return
@ -443,5 +461,6 @@ QtObject:
for i in 0 ..< self.items.len:
if(self.items[i].id == sectionId):
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.items[i].loaderActive = false
self.dataChanged(index, index, @[ModelRole.LoaderActive.int])

View File

@ -277,7 +277,6 @@ QtObject:
i.inc()
return -1
proc chatsWithCategoryHaveUnreadMessages*(self: Service, communityId: string, categoryId: string): bool =
if communityId == "" or categoryId == "":
return false
@ -287,6 +286,20 @@ QtObject:
return true
return false
proc sectionUnreadMessagesAndMentionsCount*(self: Service, communityId: string):
tuple[unviewedMessagesCount: int, unviewedMentionsCount: int] =
if communityId == "":
return
result.unviewedMentionsCount = 0
result.unviewedMessagesCount = 0
for chat in self.channelGroups[communityId].chats:
result.unviewedMentionsCount += chat.unviewedMentionsCount
if chat.muted:
continue
if chat.unviewedMessagesCount > 0:
result.unviewedMessagesCount = result.unviewedMessagesCount + chat.unviewedMessagesCount
proc updateOrAddChat*(self: Service, chat: ChatDto) =
# status-go doesn't seem to preserve categoryIDs from chat
# objects received via new messages. So we rely on what we

View File

@ -727,7 +727,7 @@ QtObject:
## Returns all chats belonging to the community with passed `communityId`, sorted by position.
## Returned chats are sorted by position following set `order` parameter.
if(not self.communities.contains(communityId)):
error "trying to get all community chats for an unexisting community id"
error "trying to get all community chats for an unexisting community id", communityId
return
result = self.communities[communityId].chats

View File

@ -110,11 +110,10 @@ type
const asyncMarkAllMessagesReadTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncMarkAllMessagesReadTaskArg](argEncoded)
discard status_go.markAllMessagesFromChatWithIdAsRead(arg.chatId)
let response = status_go.markAllMessagesFromChatWithIdAsRead(arg.chatId)
let responseJson = %*{
"chatId": arg.chatId,
"error": ""
"error": response.error
}
arg.finish(responseJson)
#################################################