fix(chats): fix unread counters in many instances

Fixes #10076

Reverts the refactor that makes getChannelGroups (ie getChats) not return chats (now it does return all chats too).
That way, we actually have the right mentions and unread count when receiving new messages

Also fixes an issue where mentions and unread count would get reset to 0 when getting a community update, because the signal doesn't have enough info
This commit is contained in:
Jonathan Rainville 2023-04-28 15:39:07 -04:00
parent 7b31929f85
commit 6997e05586
10 changed files with 84 additions and 102 deletions

View File

@ -109,22 +109,6 @@ proc authenticateToRequestToJoinCommunity*(self: Controller, communityId: string
proc init*(self: Controller) =
self.events.on(SIGNAL_CHATS_LOADED) do(e:Args):
let args = ChannelGroupArgs(e)
if args.channelGroup.id == self.sectionId:
self.delegate.onChatsLoaded(
args.channelGroup,
self.events,
self.settingsService,
self.nodeConfigurationService,
self.contactService,
self.chatService,
self.communityService,
self.messageService,
self.gifService,
self.mailserversService,
)
self.events.on(SIGNAL_SENDING_SUCCESS) do(e:Args):
let args = MessageSendingSuccess(e)
self.delegate.updateLastMessageTimestamp(args.chat.id, args.chat.timestamp.int)
@ -394,13 +378,25 @@ proc getChats*(self: Controller, communityId: string, categoryId: string): seq[C
proc getAllChats*(self: Controller, communityId: string): seq[ChatDto] =
return self.communityService.getAllChats(communityId)
proc getChatsAndBuildUI*(self: Controller) =
let channelGroup = self.chatService.getChannelGroupById(self.sectionId)
self.delegate.onChatsLoaded(
channelGroup,
self.events,
self.settingsService,
self.nodeConfigurationService,
self.contactService,
self.chatService,
self.communityService,
self.messageService,
self.gifService,
self.mailserversService,
)
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)
proc getChatDetails*(self: Controller, chatId: string): ChatDto =
return self.chatService.getChatById(chatId)

View File

@ -493,6 +493,8 @@ proc updateParentBadgeNotifications(self: Module) =
proc updateBadgeNotifications(self: Module, chat: ChatDto, hasUnreadMessages: bool, unviewedMentionsCount: int) =
let chatId = chat.id
if self.chatsLoaded:
# update model of this module (appropriate chat from the chats list (chats model))
self.view.chatsModel().updateNotificationsForItemById(chatId, hasUnreadMessages, unviewedMentionsCount)
# update child module
@ -502,6 +504,7 @@ proc updateBadgeNotifications(self: Module, chat: ChatDto, hasUnreadMessages: bo
if chat.categoryId != "":
let hasUnreadMessages = self.controller.chatsWithCategoryHaveUnreadMessages(chat.communityId, chat.categoryId)
self.view.chatsModel().setCategoryHasUnreadMessages(chat.categoryId, hasUnreadMessages)
# update parent module
self.updateParentBadgeNotifications()
@ -514,7 +517,7 @@ method onActiveSectionChange*(self: Module, sectionId: string) =
return
if not self.view.getChatsLoaded:
self.controller.asyncGetChats()
self.controller.getChatsAndBuildUI()
self.controller.setIsCurrentSectionActive(true)
let activeChatId = self.controller.getActiveChatId()

View File

@ -421,17 +421,9 @@ proc getNumOfNotificaitonsForChat*(self: Controller): tuple[unviewed:int, mentio
result.unviewed += chat.unviewedMessagesCount
result.mentions += chat.unviewedMentionsCount
proc getNumOfNotificationsForCommunity*(self: Controller, communityId: string): tuple[unviewed:int, mentions:int] =
result.unviewed = 0
result.mentions = 0
let chats = self.chatService.getAllChats()
for chat in chats:
if(chat.communityId != communityId):
continue
if not chat.muted:
result.unviewed += chat.unviewedMessagesCount
result.mentions += chat.unviewedMentionsCount
proc sectionUnreadMessagesAndMentionsCount*(self: Controller, communityId: string):
tuple[unviewedMessagesCount: int, unviewedMentionsCount: int] =
return self.chatService.sectionUnreadMessagesAndMentionsCount(communityId)
proc setCurrentUserStatus*(self: Controller, status: StatusType) =
if(self.settingsService.saveSendStatusUpdates(status)):

View File

@ -923,7 +923,14 @@ method communityEdited*[T](
self: Module[T],
community: CommunityDto) =
let channelGroup = community.toChannelGroupDto()
self.view.editItem(self.createChannelGroupItem(channelGroup))
var channelGroupItem = self.createChannelGroupItem(channelGroup)
# We need to calculate the unread counts because the community update doesn't come with it
let (unviewedMessagesCount, unviewedMentionsCount) = self.controller.sectionUnreadMessagesAndMentionsCount(
channelGroupItem.id
)
channelGroupItem.setHasNotification(unviewedMessagesCount > 0)
channelGroupItem.setNotificationsCount(unviewedMentionsCount)
self.view.editItem(channelGroupItem)
method onCommunityMuted*[T](
self: Module[T],

View File

@ -215,9 +215,15 @@ proc hasNotification*(self: SectionItem): bool {.inline.} =
proc `hasNotification=`*(self: var SectionItem, value: bool) {.inline.} =
self.hasNotification = value
proc setHasNotification*(self: var SectionItem, value: bool) {.inline.} =
self.hasNotification = value
proc notificationsCount*(self: SectionItem): int {.inline.} =
self.notificationsCount
proc setNotificationsCount*(self: var SectionItem, value: int) {.inline.} =
self.notificationsCount = value
proc `notificationsCount=`*(self: var SectionItem, value: int) {.inline.} =
self.notificationsCount = value

View File

@ -13,18 +13,3 @@ const asyncGetChannelGroupsTask: Task = proc(argEncoded: string) {.gcsafe, nimca
"channelGroups": response.result
}
arg.finish(responseJson)
type
AsyncGetChatsByChannelGroupIdTaskArg = ref object of QObjectTaskArg
channelGroupId: string
const asyncGetChatsByChannelGroupIdTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncGetChatsByChannelGroupIdTaskArg](argEncoded)
let response = status_chat.getChatsByChannelGroupId(arg.channelGroupId)
let responseJson = %*{
"channelGroupId": arg.channelGroupId,
"channelGroup": response.result,
}
arg.finish(responseJson)

View File

@ -87,9 +87,7 @@ type
# Signals which may be emitted by this service:
const SIGNAL_CHANNEL_GROUPS_LOADED* = "channelGroupsLoaded"
const SIGNAL_CHATS_LOADED* = "chatsLoaded"
const SIGNAL_CHANNEL_GROUPS_LOADING_FAILED* = "channelGroupsLoadingFailed"
const SIGNAL_CHATS_LOADING_FAILED* = "chatsLoadingFailed"
const SIGNAL_CHAT_UPDATE* = "chatUpdate"
const SIGNAL_CHAT_LEFT* = "channelLeft"
const SIGNAL_SENDING_FAILED* = "messageSendingFailed"
@ -135,7 +133,7 @@ QtObject:
# Forward declarations
proc updateOrAddChat*(self: Service, chat: ChatDto)
proc hydrateChannelGroups*(self: Service, data: JsonNode)
proc updateOrAddChannelGroup*(self: Service, channelGroup: ChannelGroupDto)
proc updateOrAddChannelGroup*(self: Service, channelGroup: ChannelGroupDto, isCommunityChannelGroup: bool = false)
proc doConnect(self: Service) =
self.events.on(SignalType.Message.event) do(e: Args):
@ -151,7 +149,6 @@ QtObject:
# Handling members update
if self.chats.hasKey(chatDto.id) and self.chats[chatDto.id].members != chatDto.members:
self.events.emit(SIGNAL_CHAT_MEMBERS_CHANGED, ChatMembersChangedArgs(chatId: chatDto.id, members: chatDto.members))
self.updateOrAddChat(chatDto)
self.events.emit(SIGNAL_CHAT_UPDATE, ChatUpdateArgs(messages: receivedData.messages, chats: chats))
@ -163,8 +160,8 @@ QtObject:
# Handling community updates
if (receivedData.communities.len > 0):
for community in receivedData.communities:
if (community.joined):
self.updateOrAddChannelGroup(community.toChannelGroupDto())
if community.joined:
self.updateOrAddChannelGroup(community.toChannelGroupDto(), isCommunityChannelGroup = true)
proc getChannelGroups*(self: Service): seq[ChannelGroupDto] =
return toSeq(self.channelGroups.values)
@ -174,18 +171,14 @@ QtObject:
let response = status_chat.getChannelGroups()
self.hydrateChannelGroups(response.result)
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
error "error loadChannelGroups: ", errorDescription = e.msg
proc loadChannelGroupById*(self: Service, channelGroupId: string) =
try:
let response = status_chat.getChatsByChannelGroupId(channelGroupId)
self.hydrateChannelGroups(%*{
channelGroupId: response.result
})
let response = status_chat.getChannelGroupById(channelGroupId)
self.hydrateChannelGroups(response.result)
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
error "error loadChannelGroupById: ", errorDescription = e.msg
proc asyncGetChannelGroups*(self: Service) =
let arg = AsyncGetChannelGroupsTaskArg(
@ -195,15 +188,6 @@ QtObject:
)
self.threadpool.start(arg)
proc asyncGetChatsByChannelGroupId*(self: Service, channelGroupId: string) =
let arg = AsyncGetChatsByChannelGroupIdTaskArg(
tptr: cast[ByteAddress](asyncGetChatsByChannelGroupIdTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onAsyncGetChatsByChannelGroupIdResponse",
channelGroupId: channelGroupId,
)
self.threadpool.start(arg)
proc sortPersonnalChatAsFirst[T, D](x, y: (T, D)): int =
if (x[1].channelGroupType == Personal): return -1
if (y[1].channelGroupType == Personal): return 1
@ -243,23 +227,6 @@ QtObject:
error "error get channel groups: ", errDesription
self.events.emit(SIGNAL_CHANNEL_GROUPS_LOADING_FAILED, Args())
proc onAsyncGetChatsByChannelGroupIdResponse*(self: Service, response: string) {.slot.} =
try:
let rpcResponseObj = response.parseJson
if(rpcResponseObj["channelGroup"].kind == JNull):
raise newException(RpcException, "No channel group returned")
let channelGroupId = rpcResponseObj["channelGroupId"].getStr
self.hydrateChannelGroups(%*{
channelGroupId: rpcResponseObj["channelGroup"]
})
self.events.emit(SIGNAL_CHATS_LOADED, ChannelGroupArgs(channelGroup: self.channelGroups[channelGroupId]))
except Exception as e:
let errDesription = e.msg
error "error get chats by channel group: ", errDesription
self.events.emit(SIGNAL_CHATS_LOADING_FAILED, Args())
proc init*(self: Service) =
self.doConnect()
@ -328,11 +295,36 @@ QtObject:
else:
self.channelGroups[channelGroupId].chats[index] = self.chats[chat.id]
proc updateOrAddChannelGroup*(self: Service, channelGroup: ChannelGroupDto) =
self.channelGroups[channelGroup.id] = channelGroup
for chat in channelGroup.chats:
proc updateMissingFieldsInCommunityChat(self: Service, channelGroupId: string, newChat: ChatDto): ChatDto =
var chat = newChat
for previousChat in self.channelGroups[channelGroupId].chats:
if previousChat.id != newChat.id:
continue
chat.unviewedMessagesCount = previousChat.unviewedMessagesCount
chat.unviewedMentionsCount = previousChat.unviewedMentionsCount
chat.muted = previousChat.muted
chat.highlight = previousChat.highlight
break
return chat
# Community channel groups have less info because they come from community signals
proc updateOrAddChannelGroup*(self: Service, channelGroup: ChannelGroupDto, isCommunityChannelGroup: bool = false) =
var newChannelGroups = channelGroup
if isCommunityChannelGroup and self.channelGroups.contains(channelGroup.id):
# We need to update missing fields in the chats seq before saving
let newChats = channelGroup.chats.mapIt(self.updateMissingFieldsInCommunityChat(channelGroup.id, it))
newChannelGroups.chats = newChats
self.channelGroups[channelGroup.id] = newChannelGroups
for chat in newChannelGroups.chats:
self.updateOrAddChat(chat)
proc getChannelGroupById*(self: Service, channelGroupId: string): ChannelGroupDto =
if (not self.channelGroups.contains(channelGroupId)):
warn "Unknown channel group", channelGroupId
return
return self.channelGroups[channelGroupId]
proc parseChatResponse*(self: Service, response: RpcResponse[JsonNode]): (seq[ChatDto], seq[MessageDto]) =
var chats: seq[ChatDto] = @[]
var messages: seq[MessageDto] = @[]

View File

@ -798,6 +798,7 @@ QtObject:
updatedCommunity.settings = communitySettings
self.communities[communityId] = updatedCommunity
# TODO improve this by only loading the data for the wanted community
self.chatService.loadChannelGroupById(communityId)
for k, chat in updatedCommunity.chats:

View File

@ -36,9 +36,9 @@ proc getChannelGroups*(): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* []
result = callPrivateRPC("chat_getChannelGroups", payload)
proc getChatsByChannelGroupId*(channelGroupId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
proc getChannelGroupById*(channelGroupId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [channelGroupId]
result = callPrivateRPC("chat_getChatsByChannelGroupID", payload)
result = callPrivateRPC("chat_getChannelGroupByID", payload)
proc createOneToOneChat*(chatId: string, ensName: string = ""): RpcResponse[JsonNode] {.raises: [Exception].} =
let communityId = ""

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit c8161a5fa4ba87f7ae9b1e1e50c2d2bc93123103
Subproject commit e7fbc191f4916f5801704ed9b6a06c738019a73e