fix(category) Implement collapsed categories (#14135)

This PR implements the nim part for enabling having collapsed categories
that persist into the database
This fixes #13944
This commit is contained in:
Godfrain Jacques 2024-04-15 11:34:44 -07:00 committed by GitHub
parent ea40a6b11f
commit eccc9b3bd7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 111 additions and 18 deletions

View File

@ -184,6 +184,12 @@ proc init*(self: Controller) =
self.mailserversService, self.sharedUrlsService, setChatAsActive = true) self.mailserversService, self.sharedUrlsService, setChatAsActive = true)
if (self.isCommunitySection): 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): self.events.on(SIGNAL_COMMUNITY_CHANNEL_CREATED) do(e:Args):
let args = CommunityChatArgs(e) let args = CommunityChatArgs(e)
let belongsToCommunity = args.chat.communityId.len > 0 let belongsToCommunity = args.chat.communityId.len > 0
@ -691,6 +697,9 @@ proc shareCommunityToUsers*(self: Controller, pubKeys: string, inviteMessage: st
proc reorderCommunityCategories*(self: Controller, categoryId: string, position: int) = proc reorderCommunityCategories*(self: Controller, categoryId: string, position: int) =
self.communityService.reorderCommunityCategories(self.sectionId, categoryId, position) self.communityService.reorderCommunityCategories(self.sectionId, categoryId, position)
proc toggleCollapsedCommunityCategory*(self: Controller, categoryId: string, collapsed: bool) =
self.communityService.toggleCollapsedCommunityCategory(self.sectionId, categoryId, collapsed)
proc reorderCommunityChat*(self: Controller, categoryId: string, chatId: string, position: int) = proc reorderCommunityChat*(self: Controller, categoryId: string, chatId: string, position: int) =
self.communityService.reorderCommunityChat(self.sectionId, categoryId, chatId, position) self.communityService.reorderCommunityChat(self.sectionId, categoryId, chatId, position)

View File

@ -312,6 +312,12 @@ method prepareEditCategoryModel*(self: AccessInterface, categoryId: string) {.ba
method reorderCommunityCategories*(self: AccessInterface, categoryId: string, position: int) {.base.} = method reorderCommunityCategories*(self: AccessInterface, categoryId: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available") 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.} =
raise newException(ValueError, "No implementation available")
method reorderCommunityChat*(self: AccessInterface, categoryId: string, chatId: string, position: int) {.base.} = method reorderCommunityChat*(self: AccessInterface, categoryId: string, chatId: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -277,6 +277,7 @@ proc addCategoryItem(self: Module, category: Category, memberRole: MemberRole, c
viewOnlyPermissionsSatisfied = true, viewOnlyPermissionsSatisfied = true,
viewAndPostPermissionsSatisfied = true viewAndPostPermissionsSatisfied = true
) )
if insertIntoModel: if insertIntoModel:
self.view.chatsModel().appendItem(result) self.view.chatsModel().appendItem(result)
@ -679,20 +680,18 @@ proc addNewChat(
memberRole = community.memberRole memberRole = community.memberRole
var categoryOpened = true var categoryOpened = true
if chatDto.categoryId != "": if chatDto.categoryId != "":
let categoryItem = self.view.chatsModel.getItemById(chatDto.categoryId) let category = self.controller.getCommunityCategoryDetails(self.controller.getMySectionId(), chatDto.categoryId)
categoryOpened = categoryItem.categoryOpened if category.id == "":
if channelGroup.id != "": error "No category found for chat", chatName=chatDto.name, categoryId=chatDto.categoryId
for category in channelGroup.categories:
if category.id == chatDto.categoryId:
categoryPosition = category.position
break
else: else:
let category = self.controller.getCommunityCategoryDetails(self.controller.getMySectionId(), chatDto.categoryId) categoryOpened = category.categoryOpened
if category.id == "": categoryPosition = category.position
error "No category found for chat", chatName=chatDto.name, categoryId=chatDto.categoryId
else: # TODO: This call will update the model for each category in channels which is not
categoryPosition = category.position # preferable. Please fix-me in https://github.com/status-im/status-desktop/issues/14431
self.view.chatsModel().changeCategoryOpened(category.id, category.categoryOpened)
result = chat_item.initItem( result = chat_item.initItem(
chatDto.id, chatDto.id,
@ -1367,6 +1366,12 @@ method reorderCommunityCategories*(self: Module, categoryId: string, categoryPos
self.controller.reorderCommunityCategories(categoryId, finalPosition) 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, collapsed)
method reorderCommunityChat*(self: Module, categoryId: string, chatId: string, toPosition: int) = method reorderCommunityChat*(self: Module, categoryId: string, chatId: string, toPosition: int) =
self.controller.reorderCommunityChat(categoryId, chatId, toPosition + 1) self.controller.reorderCommunityChat(categoryId, chatId, toPosition + 1)

View File

@ -354,6 +354,9 @@ QtObject:
proc reorderCommunityCategories*(self: View, categoryId: string, categoryPosition: int) {.slot} = proc reorderCommunityCategories*(self: View, categoryId: string, categoryPosition: int) {.slot} =
self.delegate.reorderCommunityCategories(categoryId, categoryPosition) self.delegate.reorderCommunityCategories(categoryId, categoryPosition)
proc toggleCollapsedCommunityCategory*(self: View, categoryId: string, collapsed: bool) {.slot} =
self.delegate.toggleCollapsedCommunityCategory(categoryId, collapsed)
proc reorderCommunityChat*(self: View, categoryId: string, chatId: string, position: int) {.slot} = proc reorderCommunityChat*(self: View, categoryId: string, chatId: string, position: int) {.slot} =
self.delegate.reorderCommunityChat(categoryId, chatId, position) self.delegate.reorderCommunityChat(categoryId, chatId, position)

View File

@ -122,6 +122,9 @@ method communityImported*(self: AccessInterface, community: CommunityDto) {.base
method communityDataImported*(self: AccessInterface, community: CommunityDto) {.base.} = method communityDataImported*(self: AccessInterface, community: CommunityDto) {.base.} =
raise newException(ValueError, "No implementation available") 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.} = method communityInfoRequestFailed*(self: AccessInterface, communityId: string, errorMsg: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -25,6 +25,7 @@ type Category* = object
id*: string id*: string
name*: string name*: string
position*: int position*: int
categoryOpened*: bool
type type
Permission* = object Permission* = object
@ -217,6 +218,7 @@ proc toCategory*(jsonObj: JsonNode): Category =
discard jsonObj.getProp("id", result.id) discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("name", result.name) discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("position", result.position) discard jsonObj.getProp("position", result.position)
discard jsonObj.getProp("categoryOpened", result.categoryOpened)
proc toChatMember*(jsonObj: JsonNode, memberId: string): ChatMember = proc toChatMember*(jsonObj: JsonNode, memberId: string): ChatMember =
# Parse status-go "Member" type # Parse status-go "Member" type

View File

@ -11,12 +11,14 @@ const asyncLoadCommunitiesDataTask: Task = proc(argEncoded: string) {.gcsafe, ni
let responseCommunities = status_go.getAllCommunities() let responseCommunities = status_go.getAllCommunities()
let responseSettings = status_go.getCommunitiesSettings() let responseSettings = status_go.getCommunitiesSettings()
let responseNonApprovedRequestsToJoin = status_go.allNonApprovedCommunitiesRequestsToJoin() let responseNonApprovedRequestsToJoin = status_go.allNonApprovedCommunitiesRequestsToJoin()
let responseCollapsedCommunityCategories = status_go.collapsedCommunityCategories()
arg.finish(%* { arg.finish(%* {
"tags": responseTags, "tags": responseTags,
"communities": responseCommunities, "communities": responseCommunities,
"settings": responseSettings, "settings": responseSettings,
"nonAprrovedRequestsToJoin": responseNonApprovedRequestsToJoin, "nonAprrovedRequestsToJoin": responseNonApprovedRequestsToJoin,
"collapsedCommunityCategories": responseCollapsedCommunityCategories,
"error": "", "error": "",
}) })
except Exception as e: except Exception as e:

View File

@ -391,6 +391,11 @@ proc toCommunityMembershipRequestDto*(jsonObj: JsonNode): CommunityMembershipReq
discard jsonObj.getProp("communityId", result.communityId) discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("our", result.our) discard jsonObj.getProp("our", result.our)
proc toCategoryDto*(jsonObj: JsonNode): Category =
result = Category()
discard jsonObj.getProp("categoryId", result.id)
discard jsonObj.getProp("collapsed", result.categoryOpened)
proc toCommunityDto*(jsonObj: JsonNode): CommunityDto = proc toCommunityDto*(jsonObj: JsonNode): CommunityDto =
result = CommunityDto() result = CommunityDto()
discard jsonObj.getProp("id", result.id) discard jsonObj.getProp("id", result.id)
@ -493,9 +498,18 @@ proc toCommunitySettingsDto*(jsonObj: JsonNode): CommunitySettingsDto =
discard jsonObj.getProp("communityId", result.id) discard jsonObj.getProp("communityId", result.id)
discard jsonObj.getProp("historyArchiveSupportEnabled", result.historyArchiveSupportEnabled) discard jsonObj.getProp("historyArchiveSupportEnabled", result.historyArchiveSupportEnabled)
proc parseCommunities*(response: JsonNode): seq[CommunityDto] = proc parseCommunities*(response: JsonNode, categories: seq[Category]): seq[CommunityDto] =
result = map(response["result"].getElems(), var categoryMap = initTable[string, bool]()
proc(x: JsonNode): CommunityDto = x.toCommunityDto()) for category in categories:
categoryMap[category.id] = true
result = newSeq[CommunityDto]()
for communityNode in response["result"].getElems():
var community = communityNode.toCommunityDto()
for category in community.categories.mitems:
if categoryMap.hasKey(category.id):
category.categoryOpened = true
result.add(community)
proc parseKnownCuratedCommunities(jsonCommunities: JsonNode): seq[CommunityDto] = proc parseKnownCuratedCommunities(jsonCommunities: JsonNode): seq[CommunityDto] =
for _, communityJson in jsonCommunities.pairs(): for _, communityJson in jsonCommunities.pairs():

View File

@ -72,6 +72,11 @@ type
categoryId*: string categoryId*: string
position*: int position*: int
CommunityCategoryCollapsedArgs* = ref object of Args
communityId*: string
categoryId*: string
collapsed*: bool
CommunityCategoryArgs* = ref object of Args CommunityCategoryArgs* = ref object of Args
communityId*: string communityId*: string
category*: Category category*: Category
@ -190,6 +195,7 @@ const SIGNAL_COMMUNITY_CATEGORY_EDITED* = "communityCategoryEdited"
const SIGNAL_COMMUNITY_CATEGORY_NAME_EDITED* = "communityCategoryNameEdited" const SIGNAL_COMMUNITY_CATEGORY_NAME_EDITED* = "communityCategoryNameEdited"
const SIGNAL_COMMUNITY_CATEGORY_DELETED* = "communityCategoryDeleted" const SIGNAL_COMMUNITY_CATEGORY_DELETED* = "communityCategoryDeleted"
const SIGNAL_COMMUNITY_CATEGORY_REORDERED* = "communityCategoryReordered" const SIGNAL_COMMUNITY_CATEGORY_REORDERED* = "communityCategoryReordered"
const SIGNAL_COMMUNITY_CATEGORY_COLLAPSED_TOGGLED* = "communityCategoryCollapsedToggled"
const SIGNAL_COMMUNITY_CHANNEL_CATEGORY_CHANGED* = "communityChannelCategoryChanged" const SIGNAL_COMMUNITY_CHANNEL_CATEGORY_CHANGED* = "communityChannelCategoryChanged"
const SIGNAL_COMMUNITY_MEMBER_APPROVED* = "communityMemberApproved" const SIGNAL_COMMUNITY_MEMBER_APPROVED* = "communityMemberApproved"
const SIGNAL_COMMUNITY_MEMBER_STATUS_CHANGED* = "communityMemberStatusChanged" const SIGNAL_COMMUNITY_MEMBER_STATUS_CHANGED* = "communityMemberStatusChanged"
@ -813,8 +819,15 @@ QtObject:
toUgly(resultTags, responseObj["tags"]["result"]) toUgly(resultTags, responseObj["tags"]["result"])
self.communityTags = resultTags self.communityTags = resultTags
# Categories
var categories: seq[Category]
let collapsedCommunityCategories = responseObj["collapsedCommunityCategories"]
if collapsedCommunityCategories{"result"}.kind != JNull:
for jsonCategory in collapsedCommunityCategories["result"]:
categories.add(jsonCategory.toCategoryDto())
# All communities # All communities
let communities = parseCommunities(responseObj["communities"]) let communities = parseCommunities(responseObj["communities"], categories)
for community in communities: for community in communities:
self.communities[community.id] = community self.communities[community.id] = community
@ -1464,6 +1477,20 @@ QtObject:
except Exception as e: except Exception as e:
error "Error creating community category", msg = e.msg, communityId, name error "Error creating community category", msg = e.msg, communityId, name
proc toggleCollapsedCommunityCategory*(self: Service, communityId: string, categoryId: string, collapsed: bool) =
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))
except Exception as e:
error "Error toggling collapsed community category ", msg = e.msg, communityId, collapsed
proc editCommunityCategory*( proc editCommunityCategory*(
self: Service, self: Service,
communityId: string, communityId: string,

View File

@ -408,6 +408,17 @@ proc editCommunityCategory*(
"chatIds": channels "chatIds": channels
}]) }])
proc toggleCollapsedCommunityCategory*(communityId: string, categoryId: string, collapsed: bool): RpcResponse[JsonNode] =
result = callPrivateRPC("toggleCollapsedCommunityCategory".prefix, %*[
{
"communityId": communityId,
"categoryId": categoryId,
"collapsed": collapsed
}])
proc collapsedCommunityCategories*(): RpcResponse[JsonNode] =
result = callPrivateRPC("collapsedCommunityCategories".prefix, %*[])
proc deleteCommunityCategory*( proc deleteCommunityCategory*(
communityId: string, communityId: string,
categoryId: string categoryId: string

View File

@ -32,6 +32,7 @@ Item {
signal categoryReordered(string categoryId, int to) signal categoryReordered(string categoryId, int to)
signal chatItemReordered(string categoryId, string chatId, int to) signal chatItemReordered(string categoryId, string chatId, int to)
signal categoryAddButtonClicked(string id) signal categoryAddButtonClicked(string id)
signal toggleCollapsedCommunityCategory(string categoryId, bool collapsed)
StatusListView { StatusListView {
id: statusChatListItems id: statusChatListItems
@ -146,10 +147,12 @@ Item {
highlighted = true; highlighted = true;
categoryPopupMenuSlot.item.popup() categoryPopupMenuSlot.item.popup()
} else if (mouse.button === Qt.LeftButton) { } else if (mouse.button === Qt.LeftButton) {
root.model.sourceModel.changeCategoryOpened(model.categoryId, !statusChatListCategoryItem.opened) root.toggleCollapsedCommunityCategory(model.categoryId, !statusChatListCategoryItem.opened)
} }
} }
onToggleButtonClicked: root.model.sourceModel.changeCategoryOpened(model.categoryId, !statusChatListCategoryItem.opened) onToggleButtonClicked: {
root.toggleCollapsedCommunityCategory(model.categoryId, !statusChatListCategoryItem.opened)
}
onMenuButtonClicked: { onMenuButtonClicked: {
statusChatListCategoryItem.setupPopup() statusChatListCategoryItem.setupPopup()
highlighted = true highlighted = true

View File

@ -29,6 +29,7 @@ Item {
signal chatItemReordered(string categoryId, string chatId, int to) signal chatItemReordered(string categoryId, string chatId, int to)
signal chatListCategoryReordered(string categoryId, int to) signal chatListCategoryReordered(string categoryId, int to)
signal categoryAddButtonClicked(string id) signal categoryAddButtonClicked(string id)
signal toggleCollapsedCommunityCategory(string categoryId, bool collapsed)
MouseArea { MouseArea {
id: sensor id: sensor
@ -53,6 +54,7 @@ Item {
draggableItems: root.draggableItems draggableItems: root.draggableItems
showCategoryActionButtons: root.showCategoryActionButtons showCategoryActionButtons: root.showCategoryActionButtons
onCategoryAddButtonClicked: root.categoryAddButtonClicked(id) onCategoryAddButtonClicked: root.categoryAddButtonClicked(id)
onToggleCollapsedCommunityCategory: root.toggleCollapsedCommunityCategory(categoryId, collapsed)
model: SortFilterProxyModel { model: SortFilterProxyModel {
sourceModel: root.model sourceModel: root.model

View File

@ -392,6 +392,10 @@ QtObject {
chatCommunitySectionModule.reorderCommunityCategories(categoryId, to) chatCommunitySectionModule.reorderCommunityCategories(categoryId, to)
} }
function toggleCollapsedCommunityCategory(categoryId, collapsed) {
chatCommunitySectionModule.toggleCollapsedCommunityCategory(categoryId, collapsed)
}
function reorderCommunityChat(categoryId, chatId, to) { function reorderCommunityChat(categoryId, chatId, to) {
chatCommunitySectionModule.reorderCommunityChat(categoryId, chatId, to) chatCommunitySectionModule.reorderCommunityChat(categoryId, chatId, to)
} }

View File

@ -200,6 +200,8 @@ Item {
categoryId: id categoryId: id
}) })
onToggleCollapsedCommunityCategory: root.store.toggleCollapsedCommunityCategory(categoryId, collapsed)
popupMenu: StatusMenu { popupMenu: StatusMenu {
hideDisabledItems: false hideDisabledItems: false
StatusAction { StatusAction {