From 1a3b75fc9dc0311e8034f7669625e1b443926210 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 12 Sep 2024 11:55:16 -0400 Subject: [PATCH] fix(categories): make categories collapsing async to fix performance (#16271) Fixes #16270 Makes the category collapsing and opening async, so UI feedback is immediate, while the actual save in the DB is done async in the background. --- .../modules/main/chat_section/controller.nim | 10 +--- .../main/chat_section/io_interface.nim | 5 +- src/app/modules/main/chat_section/module.nim | 7 +-- src/app/modules/main/chat_section/view.nim | 3 +- .../modules/main/communities/io_interface.nim | 3 -- .../service/community/async_tasks.nim | 24 ++++++++- src/app_service/service/community/service.nim | 49 ++++++++++--------- 7 files changed, 57 insertions(+), 44 deletions(-) diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index 989fc1f8f2..3ed2bb12e6 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -173,12 +173,6 @@ proc init*(self: Controller) = self.mailserversService, self.sharedUrlsService, setChatAsActive = true) if (self.isCommunitySection): - self.events.on(SIGNAL_COMMUNITY_CATEGORY_COLLAPSED_TOGGLED) do(e: Args): - let args = CommunityCategoryCollapsedArgs(e) - - if (args.communityId == self.sectionId): - self.delegate.onToggleCollapsedCommunityCategory(args.categoryId, args.collapsed) - self.events.on(SIGNAL_COMMUNITY_CHANNEL_CREATED) do(e:Args): let args = CommunityChatArgs(e) let belongsToCommunity = args.chat.communityId.len > 0 @@ -699,8 +693,8 @@ proc shareCommunityToUsers*(self: Controller, pubKeys: string, inviteMessage: st proc reorderCommunityCategories*(self: Controller, categoryId: string, position: int) = self.communityService.reorderCommunityCategories(self.sectionId, categoryId, position) -proc toggleCollapsedCommunityCategory*(self: Controller, categoryId: string, collapsed: bool) = - self.communityService.toggleCollapsedCommunityCategory(self.sectionId, categoryId, collapsed) +proc toggleCollapsedCommunityCategoryAsync*(self: Controller, categoryId: string, collapsed: bool) = + self.communityService.toggleCollapsedCommunityCategoryAsync(self.sectionId, categoryId, collapsed) proc reorderCommunityChat*(self: Controller, categoryId: string, chatId: string, position: int) = self.communityService.reorderCommunityChat(self.sectionId, categoryId, chatId, position) diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim index d65af7b15c..4614faf4d5 100644 --- a/src/app/modules/main/chat_section/io_interface.nim +++ b/src/app/modules/main/chat_section/io_interface.nim @@ -318,10 +318,7 @@ method prepareEditCategoryModel*(self: AccessInterface, categoryId: string) {.ba method reorderCommunityCategories*(self: AccessInterface, categoryId: string, position: int) {.base.} = raise newException(ValueError, "No implementation available") -method toggleCollapsedCommunityCategory*(self: AccessInterface, categoryId: string, collapsed: bool) {.base.} = - raise newException(ValueError, "No implementation available") - -method onToggleCollapsedCommunityCategory*(self: AccessInterface, categoryId: string, collapsed: bool) {.base.} = +method toggleCollapsedCommunityCategoryAsync*(self: AccessInterface, categoryId: string, collapsed: bool) {.base.} = raise newException(ValueError, "No implementation available") method reorderCommunityChat*(self: AccessInterface, categoryId: string, chatId: string, position: int) {.base.} = diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index 5207782ce1..a3a8e22062 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -1427,11 +1427,8 @@ method reorderCommunityCategories*(self: Module, categoryId: string, categoryPos self.controller.reorderCommunityCategories(categoryId, finalPosition) -method toggleCollapsedCommunityCategory*(self: Module, categoryId: string, collapsed: bool) = - self.controller.toggleCollapsedCommunityCategory(categoryId, collapsed) - -method onToggleCollapsedCommunityCategory*(self: Module, categoryId: string, collapsed: bool) = - self.view.chatsModel().changeCategoryOpened(categoryId, not collapsed) +method toggleCollapsedCommunityCategoryAsync*(self: Module, categoryId: string, collapsed: bool) = + self.controller.toggleCollapsedCommunityCategoryAsync(categoryId, collapsed) method reorderCommunityChat*(self: Module, categoryId: string, chatId: string, toPosition: int) = self.controller.reorderCommunityChat(categoryId, chatId, toPosition + 1) diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim index 4cf7303303..e526602a89 100644 --- a/src/app/modules/main/chat_section/view.nim +++ b/src/app/modules/main/chat_section/view.nim @@ -357,7 +357,8 @@ QtObject: self.delegate.reorderCommunityCategories(categoryId, categoryPosition) proc toggleCollapsedCommunityCategory*(self: View, categoryId: string, collapsed: bool) {.slot} = - self.delegate.toggleCollapsedCommunityCategory(categoryId, collapsed) + self.model.changeCategoryOpened(categoryId, not collapsed) + self.delegate.toggleCollapsedCommunityCategoryAsync(categoryId, collapsed) proc reorderCommunityChat*(self: View, categoryId: string, chatId: string, position: int) {.slot} = self.delegate.reorderCommunityChat(categoryId, chatId, position) diff --git a/src/app/modules/main/communities/io_interface.nim b/src/app/modules/main/communities/io_interface.nim index 6948461faa..151d144559 100644 --- a/src/app/modules/main/communities/io_interface.nim +++ b/src/app/modules/main/communities/io_interface.nim @@ -119,9 +119,6 @@ method communityImported*(self: AccessInterface, community: CommunityDto) {.base method communityDataImported*(self: AccessInterface, community: CommunityDto) {.base.} = raise newException(ValueError, "No implementation available") -method toggleCollapsedCommunityCategory*(self: AccessInterface, communityId:string, categoryId: string, collapsed: bool) {.base.} = - raise newException(ValueError, "No implementation available") - method communityInfoRequestFailed*(self: AccessInterface, communityId: string, errorMsg: string) {.base.} = raise newException(ValueError, "No implementation available") diff --git a/src/app_service/service/community/async_tasks.nim b/src/app_service/service/community/async_tasks.nim index ff7db4193a..76cb0094bf 100644 --- a/src/app_service/service/community/async_tasks.nim +++ b/src/app_service/service/community/async_tasks.nim @@ -282,7 +282,6 @@ proc asyncReevaluateCommunityMembersPermissionsTask(argEncoded: string) {.gcsafe "error": e.msg, }) - type AsyncSetCommunityShardArg = ref object of QObjectTaskArg communityId: string @@ -302,3 +301,26 @@ proc asyncSetCommunityShardTask(argEncoded: string) {.gcsafe, nimcall.} = "communityId": arg.communityId, "error": e.msg, }) + +type + AsyncCollapseCategory = ref object of QObjectTaskArg + communityId: string + categoryId: string + collapsed: bool + +proc asyncCollapseCategoryTask(argEncoded: string) {.gcsafe, nimcall.} = + let arg = decode[AsyncCollapseCategory](argEncoded) + try: + let response = status_go.toggleCollapsedCommunityCategory( + arg.communityId, + arg.categoryId, + arg.collapsed, + ) + arg.finish(%* { + "response": response, + "error": "", + }) + except Exception as e: + arg.finish(%* { + "error": e.msg, + }) diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim index 1ce877b947..e67bd4d96a 100644 --- a/src/app_service/service/community/service.nim +++ b/src/app_service/service/community/service.nim @@ -199,7 +199,6 @@ const SIGNAL_COMMUNITY_CATEGORY_EDITED* = "communityCategoryEdited" const SIGNAL_COMMUNITY_CATEGORY_NAME_EDITED* = "communityCategoryNameEdited" const SIGNAL_COMMUNITY_CATEGORY_DELETED* = "communityCategoryDeleted" const SIGNAL_COMMUNITY_CATEGORY_REORDERED* = "communityCategoryReordered" -const SIGNAL_COMMUNITY_CATEGORY_COLLAPSED_TOGGLED* = "communityCategoryCollapsedToggled" const SIGNAL_COMMUNITY_CHANNEL_CATEGORY_CHANGED* = "communityChannelCategoryChanged" const SIGNAL_COMMUNITY_MEMBER_APPROVED* = "communityMemberApproved" const SIGNAL_COMMUNITY_MEMBER_STATUS_CHANGED* = "communityMemberStatusChanged" @@ -1479,19 +1478,28 @@ QtObject: except Exception as e: error "Error creating community category", msg = e.msg, communityId, name - proc toggleCollapsedCommunityCategory*(self: Service, communityId: string, categoryId: string, collapsed: bool) = + proc toggleCollapsedCommunityCategoryAsync*(self: Service, communityId: string, categoryId: string, collapsed: bool) = + let arg = AsyncCollapseCategory( + tptr: asyncCollapseCategoryTask, + vptr: cast[ByteAddress](self.vptr), + slot: "onAsyncCollapseCategoryDone", + communityId: communityId, + categoryId: categoryId, + collapsed: collapsed, + ) + self.threadpool.start(arg) + + proc onAsyncCollapseCategoryDone*(self: Service, rpcResponse: string) {.slot.} = try: - let response = status_go.toggleCollapsedCommunityCategory(communityId, categoryId, collapsed) - - if response.error != nil: - let error = Json.decode($response.error, RpcError) - raise newException(RpcException, "Error toggling collapsed community category: " & error.message) - - self.events.emit(SIGNAL_COMMUNITY_CATEGORY_COLLAPSED_TOGGLED, CommunityCategoryCollapsedArgs( - communityId: communityId, categoryId: categoryId, collapsed: collapsed)) + let rpcResponseObj = rpcResponse.parseJson + if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "": + raise newException(CatchableError, rpcResponseObj["error"].getStr) + if rpcResponseObj["response"]{"error"}.kind != JNull: + let error = Json.decode(rpcResponseObj["response"]["error"].getStr, RpcError) + raise newException(RpcException, error.message) except Exception as e: - error "Error toggling collapsed community category ", msg = e.msg, communityId, collapsed + error "Error toggling collapsed community category", msg = e.msg proc editCommunityCategory*( self: Service, @@ -2362,17 +2370,14 @@ QtObject: error "error while reevaluating community members permissions", msg = e.msg proc asyncSetCommunityShard*(self: Service, communityId: string, shardIndex: int) = - try: - let arg = AsyncSetCommunityShardArg( - tptr: asyncSetCommunityShardTask, - vptr: cast[ByteAddress](self.vptr), - slot: "onAsyncSetCommunityShardDone", - communityId: communityId, - shardIndex: shardIndex, - ) - self.threadpool.start(arg) - except Exception as e: - error "Error request to join community", msg = e.msg + let arg = AsyncSetCommunityShardArg( + tptr: asyncSetCommunityShardTask, + vptr: cast[ByteAddress](self.vptr), + slot: "onAsyncSetCommunityShardDone", + communityId: communityId, + shardIndex: shardIndex, + ) + self.threadpool.start(arg) proc onAsyncSetCommunityShardDone*(self: Service, communityIdAndRpcResponse: string) {.slot.} = let rpcResponseObj = communityIdAndRpcResponse.parseJson