13291 hide channels (#13876)

* feat(@desktop/communities): Hide channels if the user is not permitted to view and hideIfPermissionsNotMet is set

Extend chats model with channel permissions info and hideIfPermissionsNotMet.
Visibility of chat item is based on: member roles, channel permissions, hideIfPermissionsNotMet.
If all channels from category are hidden, category item is also hidden.
If all chats in community are hidden, infomration label is displayed.

Issue #13291

* chore(@desktop): Upgrade status-go

Issue #13291
This commit is contained in:
Michał Iskierko 2024-03-18 18:33:07 +01:00 committed by GitHub
parent 958274259f
commit 9ed38bddb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 299 additions and 49 deletions

View File

@ -24,6 +24,7 @@ QtObject:
active: bool
blocked: bool
canPostReactions: bool
hideIfPermissionsNotMet: bool
proc delete*(self: ChatDetails) =
self.QObject.delete
@ -50,6 +51,7 @@ QtObject:
isContact: bool = false,
blocked: bool = false,
canPostReactions: bool = true,
hideIfPermissionsNotMet: bool
) =
self.id = id
self.`type` = `type`
@ -70,6 +72,7 @@ QtObject:
self.active = false
self.blocked = blocked
self.canPostReactions = canPostReactions
self.hideIfPermissionsNotMet = hideIfPermissionsNotMet
proc getId(self: ChatDetails): string {.slot.} =
return self.id
@ -255,3 +258,14 @@ QtObject:
proc setCanPostReactions*(self: ChatDetails, value: bool) =
self.canPostReactions = value
self.canPostReactionsChanged()
proc hideIfPermissionsNotMetChanged(self: ChatDetails) {.signal.}
proc getHideIfPermissionsNotMet(self: ChatDetails): bool {.slot.} =
return self.hideIfPermissionsNotMet
QtProperty[bool] hideIfPermissionsNotMet:
read = getHideIfPermissionsNotMet
notify = hideIfPermissionsNotMetChanged
proc setHideIfPermissionsNotMet*(self: ChatDetails, value: bool) =
self.hideIfPermissionsNotMet = value
self.hideIfPermissionsNotMetChanged()

View File

@ -95,7 +95,7 @@ method load*(self: Module, chatItem: chat_item.Item) =
self.controller.isUsersListAvailable(), chatName, chatImage,
chatItem.color, chatItem.description, chatItem.emoji, chatItem.hasUnreadMessages, chatItem.notificationsCount,
chatItem.highlight, chatItem.muted, chatItem.position, isUntrustworthy = trustStatus == TrustStatus.Untrustworthy,
isContact, chatItem.blocked, chatItem.canPostReactions)
isContact, chatItem.blocked, chatItem.canPostReactions, chatItem.hideIfPermissionsNotMet)
self.inputAreaModule.load()
self.messagesModule.load()

View File

@ -40,10 +40,10 @@ QtObject:
proc load*(self: View, id: string, `type`: int, belongsToCommunity, isUsersListAvailable: bool,
name, icon: string, color, description, emoji: string, hasUnreadMessages: bool,
notificationsCount: int, highlight, muted: bool, position: int, isUntrustworthy: bool,
isContact: bool, blocked: bool, canPostReactions: bool) =
isContact: bool, blocked: bool, canPostReactions: bool, hideIfPermissionsNotMet: bool) =
self.chatDetails.setChatDetails(id, `type`, belongsToCommunity, isUsersListAvailable, name,
icon, color, description, emoji, hasUnreadMessages, notificationsCount, highlight, muted, position,
isUntrustworthy, isContact, blocked, canPostReactions)
isUntrustworthy, isContact, blocked, canPostReactions, hideIfPermissionsNotMet)
self.delegate.viewDidLoad()
self.chatDetailsChanged()

View File

@ -566,9 +566,10 @@ proc createCommunityChannel*(
color: string,
categoryId: string,
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool,
) =
self.communityService.createCommunityChannel(self.sectionId, name, description, emoji, color,
categoryId, viewersCanPostReactions)
categoryId, viewersCanPostReactions, hideIfPermissionsNotMet)
proc editCommunityChannel*(
self: Controller,
@ -580,6 +581,7 @@ proc editCommunityChannel*(
categoryId: string,
position: int,
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool,
) =
self.communityService.editCommunityChannel(
self.sectionId,
@ -590,8 +592,8 @@ proc editCommunityChannel*(
color,
categoryId,
position,
viewersCanPostReactions
)
viewersCanPostReactions,
hideIfPermissionsNotMet)
proc createCommunityCategory*(self: Controller, name: string, channels: seq[string]) =
self.communityService.createCommunityCategory(self.sectionId, name, channels)

View File

@ -266,11 +266,11 @@ method declineRequestToJoinCommunity*(self: AccessInterface, requestId: string,
raise newException(ValueError, "No implementation available")
method createCommunityChannel*(self: AccessInterface, name: string, description: string,
emoji: string, color: string, categoryId: string, viewersCanPostReactions: bool) {.base.} =
emoji: string, color: string, categoryId: string, viewersCanPostReactions: bool, hideIfPermissionsNotMet: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method editCommunityChannel*(self: AccessInterface, channelId, name, description, emoji, color,
categoryId: string, position: int, viewersCanPostReactions: bool) {.base.} =
categoryId: string, position: int, viewersCanPostReactions: bool, hideIfPermissionsNotMet: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method leaveCommunity*(self: AccessInterface) {.base.} =

View File

@ -37,6 +37,9 @@ type
requiresPermissions: bool
canPostReactions: bool
viewersCanPostReactions: bool
hideIfPermissionsNotMet: bool
viewOnlyPermissionsSatisfied: bool
viewAndPostPermissionsSatisfied: bool
proc initItem*(
id,
@ -67,6 +70,9 @@ proc initItem*(
requiresPermissions = false,
canPostReactions = true,
viewersCanPostReactions = true,
hideIfPermissionsNotMet: bool,
viewOnlyPermissionsSatisfied: bool,
viewAndPostPermissionsSatisfied: bool
): Item =
result = Item()
result.id = id
@ -98,6 +104,9 @@ proc initItem*(
result.requiresPermissions = requiresPermissions
result.canPostReactions = canPostReactions
result.viewersCanPostReactions = viewersCanPostReactions
result.hideIfPermissionsNotMet = hideIfPermissionsNotMet
result.viewOnlyPermissionsSatisfied = viewOnlyPermissionsSatisfied
result.viewAndPostPermissionsSatisfied = viewAndPostPermissionsSatisfied
proc `$`*(self: Item): string =
result = fmt"""chat_section/Item(
@ -128,6 +137,9 @@ proc `$`*(self: Item): string =
requiresPermissions: {$self.requiresPermissions},
canPostReactions: {$self.canPostReactions},
viewersCanPostReactions: {$self.viewersCanPostReactions},
hideIfPermissionsNotMet: {$self.hideIfPermissionsNotMet},
viewOnlyPermissionsSatisfied: {$self.viewOnlyPermissionsSatisfied},
viewAndPostPermissionsSatisfied: {$self.viewAndPostPermissionsSatisfied}
]"""
proc toJsonNode*(self: Item): JsonNode =
@ -159,6 +171,9 @@ proc toJsonNode*(self: Item): JsonNode =
"requiresPermissions": self.requiresPermissions,
"canPostReactions": self.canPostReactions,
"viewersCanPostReactions": self.viewersCanPostReactions,
"hideIfPermissionsNotMet": self.hideIfPermissionsNotMet,
"viewOnlyPermissionsSatisfied": self.viewOnlyPermissionsSatisfied,
"viewAndPostPermissionsSatisfied": self.viewAndPostPermissionsSatisfied
}
proc delete*(self: Item) =
@ -257,6 +272,24 @@ proc categoryId*(self: Item): string =
proc `categoryId=`*(self: var Item, value: string) =
self.categoryId = value
proc hideIfPermissionsNotMet*(self: Item): bool =
self.hideIfPermissionsNotMet
proc `hideIfPermissionsNotMet=`*(self: var Item, value: bool) =
self.hideIfPermissionsNotMet = value
proc viewAndPostPermissionsSatisfied*(self: Item): bool =
self.viewAndPostPermissionsSatisfied
proc `viewAndPostPermissionsSatisfied=`*(self: var Item, value: bool) =
self.viewAndPostPermissionsSatisfied = value
proc viewOnlyPermissionsSatisfied*(self: Item): bool =
self.viewOnlyPermissionsSatisfied
proc `viewOnlyPermissionsSatisfied=`*(self: var Item, value: bool) =
self.viewOnlyPermissionsSatisfied = value
proc categoryPosition*(self: Item): int =
self.categoryPosition
@ -322,3 +355,6 @@ proc viewersCanPostReactions*(self: Item): bool =
proc `viewersCanPostReactions=`*(self: Item, value: bool) =
self.viewersCanPostReactions = value
proc hideBecausePermissionsAreNotMet*(self: Item): bool =
self.hideIfPermissionsNotMet and not self.viewOnlyPermissionsSatisfied and not self.viewAndPostPermissionsSatisfied

View File

@ -37,6 +37,11 @@ type
RequiresPermissions
CanPostReactions
ViewersCanPostReactions
HideIfPermissionsNotMet
ViewOnlyPermissionsSatisfied
ViewAndPostPermissionsSatisfied
ShouldBeHiddenBecausePermissionsAreNotMet #this is a complex role which depends on other roles
#(MemberRole , HideIfPermissionsNotMet, ViewOnlyPermissionsSatisfied, ViewAndPostPermissionsSatisfied)
QtObject:
type
@ -78,6 +83,28 @@ QtObject:
proc items*(self: Model): seq[Item] =
return self.items
proc categoryShouldBeHiddenBecauseNotPermitted(self: Model, categoryId: string): bool =
for i in 0 ..< self.items.len:
if not self.items[i].isCategory and self.items[i].categoryId == categoryId:
if not self.items[i].hideBecausePermissionsAreNotMet():
return false
return true
proc itemShouldBeHiddenBecauseNotPermitted*(self: Model, item: Item): bool =
let isRegularUser = item.memberRole != MemberRole.Owner and item.memberRole != MemberRole.Admin and item.memberRole != MemberRole.TokenMaster
if not isRegularUser:
return false
if item.isCategory:
return self.categoryShouldBeHiddenBecauseNotPermitted(item.id)
else:
return item.hideBecausePermissionsAreNotMet()
proc firstNotHiddenItemId*(self: Model): string =
for i in 0 ..< self.items.len:
if not self.items[i].isCategory and not self.itemShouldBeHiddenBecauseNotPermitted(self.items[i]):
return self.items[i].id
return ""
method roleNames(self: Model): Table[int, string] =
{
ModelRole.Id.int:"itemId",
@ -98,6 +125,9 @@ QtObject:
ModelRole.Active.int:"active",
ModelRole.Position.int:"position",
ModelRole.CategoryId.int:"categoryId",
ModelRole.HideIfPermissionsNotMet.int:"hideIfPermissionsNotMet",
ModelRole.ViewOnlyPermissionsSatisfied.int:"viewOnlyPermissionsSatisfied",
ModelRole.ViewAndPostPermissionsSatisfied.int:"viewAndPostPermissionsSatisfied",
ModelRole.CategoryPosition.int:"categoryPosition",
ModelRole.Highlight.int:"highlight",
ModelRole.CategoryOpened.int:"categoryOpened",
@ -109,6 +139,7 @@ QtObject:
ModelRole.RequiresPermissions.int:"requiresPermissions",
ModelRole.CanPostReactions.int:"canPostReactions",
ModelRole.ViewersCanPostReactions.int:"viewersCanPostReactions",
ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet.int:"shouldBeHiddenBecausePermissionsAreNotMet"
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -180,6 +211,14 @@ QtObject:
result = newQVariant(item.canPostReactions)
of ModelRole.ViewersCanPostReactions:
result = newQVariant(item.viewersCanPostReactions)
of ModelRole.HideIfPermissionsNotMet:
result = newQVariant(item.hideIfPermissionsNotMet)
of ModelRole.ViewAndPostPermissionsSatisfied:
result = newQVariant(item.viewAndPostPermissionsSatisfied)
of ModelRole.ViewOnlyPermissionsSatisfied:
result = newQVariant(item.viewOnlyPermissionsSatisfied)
of ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet:
return newQVariant(self.itemShouldBeHiddenBecauseNotPermitted(item))
proc getItemIdxById(items: seq[Item], id: string): int =
var idx = 0
@ -235,6 +274,20 @@ QtObject:
defer: index.delete
self.dataChanged(index, index, @[ModelRole.CategoryOpened.int])
# This function only refreshes ShouldBeHiddenBecausePermissionsAreNotMet.
# Then itemShouldBeHiddenBecauseNotPermitted() is used in data() to determined whether category is hidden or not.
proc updateHiddenFlagForCategory(self: Model, id: string) =
if id == "":
return
let index = self.getItemIdxById(id)
if index == -1:
return
if not self.items[index].isCategory:
return
let modelIndex = self.createIndex(index, 0, nil)
defer: modelIndex.delete
self.dataChanged(modelIndex, modelIndex, @[ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet.int])
proc removeItemByIndex(self: Model, idx: int) =
if idx == -1:
return
@ -295,6 +348,11 @@ QtObject:
else:
self.dataChanged(index, index, @[ModelRole.Active.int])
proc activeItem*(self: Model): Item =
for i in 0 ..< self.items.len:
if self.items[i].active:
return self.items[i]
proc setItemLocked*(self: Model, id: string, locked: bool) =
let index = self.getItemIdxById(id)
if index == -1:
@ -304,6 +362,28 @@ QtObject:
defer: modelIndex.delete
self.dataChanged(modelIndex, modelIndex, @[ModelRole.Locked.int])
proc setViewOnlyPermissionsSatisfied*(self: Model, id: string, satisfied: bool) =
let index = self.getItemIdxById(id)
if index == -1:
return
self.items[index].viewOnlyPermissionsSatisfied = satisfied
let modelIndex = self.createIndex(index, 0, nil)
defer: modelIndex.delete
# refresh also ShouldBeHiddenBecausePermissionsAreNotMet because it depends on ViewOnlyPermissionsSatisfied
self.dataChanged(modelIndex, modelIndex, @[ModelRole.ViewOnlyPermissionsSatisfied.int, ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet.int])
self.updateHiddenFlagForCategory(self.items[index].categoryId)
proc setViewAndPostPermissionsSatisfied*(self: Model, id: string, satisfied: bool) =
let index = self.getItemIdxById(id)
if index == -1:
return
self.items[index].viewAndPostPermissionsSatisfied = satisfied
let modelIndex = self.createIndex(index, 0, nil)
defer: modelIndex.delete
# refresh also ShouldBeHiddenBecausePermissionsAreNotMet because it depends on ViewAndPostPermissionsSatisfied
self.dataChanged(modelIndex, modelIndex, @[ModelRole.ViewAndPostPermissionsSatisfied.int, ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet.int])
self.updateHiddenFlagForCategory(self.items[index].categoryId)
proc setItemPermissionsRequired*(self: Model, id: string, value: bool) =
let index = self.getItemIdxById(id)
if index == -1:
@ -356,6 +436,12 @@ QtObject:
self.items[i].muted = muted
self.dataChanged(index, index, @[ModelRole.Muted.int])
proc allChannelsAreHiddenBecauseNotPermitted*(self: Model): bool =
for i in 0 ..< self.items.len:
if not self.items[i].isCategory and not self.itemShouldBeHiddenBecauseNotPermitted(self.items[i]):
return false
return true
proc changeBlockedOnItemById*(self: Model, id: string, blocked: bool) =
let index = self.getItemIdxById(id)
if index == -1:
@ -385,7 +471,7 @@ QtObject:
ModelRole.TrustStatus.int,
])
proc updateItemDetailsById*(self: Model, id, name, description, emoji, color: string) =
proc updateItemDetailsById*(self: Model, id, name, description, emoji, color: string, hideIfPermissionsNotMet: bool) =
let index = self.getItemIdxById(id)
if index == -1:
return
@ -393,6 +479,7 @@ QtObject:
self.items[index].description = description
self.items[index].emoji = emoji
self.items[index].color = color
self.items[index].hideIfPermissionsNotMet = hideIfPermissionsNotMet
let modelIndex = self.createIndex(index, 0, nil)
defer: modelIndex.delete
self.dataChanged(modelIndex, modelIndex, @[
@ -400,7 +487,11 @@ QtObject:
ModelRole.Description.int,
ModelRole.Emoji.int,
ModelRole.Color.int,
ModelRole.HideIfPermissionsNotMet.int,
# refresh also ShouldBeHiddenBecausePermissionsAreNotMet because it depends on HideIfPermissionsNotMet
ModelRole.ShouldBeHiddenBecausePermissionsAreNotMet.int
])
self.updateHiddenFlagForCategory(self.items[index].categoryId)
proc updateNameColorIconOnItemById*(self: Model, id, name, color, icon: string) =
let index = self.getItemIdxById(id)

View File

@ -186,6 +186,9 @@ proc addCategoryItem(self: Module, category: Category, memberRole: MemberRole, c
position = -1, # Set position as -1, so that the Category Item is on top of its Channels
category.id,
category.position,
hideIfPermissionsNotMet = false,
viewOnlyPermissionsSatisfied = true,
viewAndPostPermissionsSatisfied = true
)
if insertIntoModel:
self.view.chatsModel().appendItem(result)
@ -463,6 +466,16 @@ proc updateChatLocked(self: Module, chatId: string) =
let locked = self.controller.checkChatIsLocked(communityId, chatId)
self.view.chatsModel().setItemLocked(chatId, locked)
proc updateViewOnlyPermissionsSatisfied(self: Module, chatId: string, satisifed: bool) =
if not self.controller.isCommunity():
return
self.view.chatsModel().setViewOnlyPermissionsSatisfied(chatId, satisifed)
proc updateViewAndPostPermissionsSatisfied(self: Module, chatId: string, satisifed: bool) =
if not self.controller.isCommunity():
return
self.view.chatsModel().setViewAndPostPermissionsSatisfied(chatId, satisifed)
proc updateChatRequiresPermissions(self: Module, chatId: string) =
if not self.controller.isCommunity():
return
@ -514,7 +527,7 @@ method onActiveSectionChange*(self: Module, sectionId: string) =
method chatsModel*(self: Module): chats_model.Model =
return self.view.chatsModel()
proc addNewChat*(
proc addNewChat(
self: Module,
chatDto: ChatDto,
channelGroup: ChannelGroupDto,
@ -560,11 +573,15 @@ proc addNewChat*(
var memberRole = self.getUserMemberRole(chatDto.members)
if memberRole == MemberRole.None and len(chatDto.communityId) != 0:
memberRole = channelGroup.memberRole
if chatDto.chatType != ChatType.PrivateGroupChat:
memberRole = channelGroup.memberRole
if memberRole == MemberRole.None and len(chatDto.communityId) != 0:
memberRole = channelGroup.memberRole
if memberRole == MemberRole.None:
let community = communityService.getCommunityById(chatDto.communityId)
memberRole = community.memberRole
var categoryOpened = true
if chatDto.categoryId != "":
let categoryItem = self.view.chatsModel.getItemById(chatDto.categoryId)
@ -615,6 +632,9 @@ proc addNewChat*(
false,
canPostReactions = chatDto.canPostReactions,
viewersCanPostReactions = chatDto.viewersCanPostReactions,
hideIfPermissionsNotMet = chatDto.hideIfPermissionsNotMet,
viewOnlyPermissionsSatisfied = true, # will be updated in async call
viewAndPostPermissionsSatisfied = true # will be updated in async call
)
self.addSubmodule(
@ -720,11 +740,24 @@ method onCommunityChannelDeletedOrChatLeft*(self: Module, chatId: string) =
self.setFirstChannelAsActive()
proc refreshHiddenBecauseNotPermittedState(self: Module) =
self.view.refreshAllChannelsAreHiddenBecauseNotPermittedChanged()
let activeChatItem = self.view.chatsModel().activeItem()
if activeChatItem == nil:
return
let activeItemShouldBeHidden = self.view.chatsModel().itemShouldBeHiddenBecauseNotPermitted(activeChatItem)
if activeItemShouldBeHidden:
let firstNotHiddenItemId = self.view.chatsModel().firstNotHiddenItemId()
self.setActiveItem(firstNotHiddenItemId)
method onCommunityChannelEdited*(self: Module, chat: ChatDto) =
if(not self.chatContentModules.contains(chat.id)):
return
self.view.chatsModel().updateItemDetailsById(chat.id, chat.name, chat.description, chat.emoji, chat.color)
self.changeCanPostValues(chat.id, chat.canPostReactions, chat.viewersCanPostReactions)
self.view.chatsModel().updateItemDetailsById(chat.id, chat.name, chat.description, chat.emoji, chat.color, chat.hideIfPermissionsNotMet)
self.refreshHiddenBecauseNotPermittedState()
method switchToOrCreateOneToOneChat*(self: Module, chatId: string) =
# One To One chat is available only in the `Chat` section
@ -869,6 +902,9 @@ proc updateChannelPermissionViewData*(self: Module, chatId: string, viewOnlyPerm
self.chatContentModules[chatId].onUpdateViewOnlyPermissionsSatisfied(viewOnlyPermissions.satisfied)
self.chatContentModules[chatId].onUpdateViewAndPostPermissionsSatisfied(viewAndPostPermissions.satisfied)
self.chatContentModules[chatId].setPermissionsCheckOngoing(false)
self.updateViewOnlyPermissionsSatisfied(chatId, viewOnlyPermissions.satisfied)
self.updateViewAndPostPermissionsSatisfied(chatId, viewAndPostPermissions.satisfied)
self.refreshHiddenBecauseNotPermittedState()
method onCommunityCheckPermissionsToJoinResponse*(self: Module, checkPermissionsToJoinResponse: CheckPermissionsToJoinResponseDto) =
let community = self.controller.getMyCommunity()
@ -1093,13 +1129,13 @@ method onAcceptRequestToJoinFailedNoPermission*(self: Module, communityId: strin
let contact = self.controller.getContactById(memberKey)
self.view.emitOpenNoPermissionsToJoinPopupSignal(community.name, contact.displayName, community.id, requestId)
method createCommunityChannel*(self: Module, name, description, emoji, color, categoryId: string, viewersCanPostReactions: bool) =
self.controller.createCommunityChannel(name, description, emoji, color, categoryId, viewersCanPostReactions)
method createCommunityChannel*(self: Module, name, description, emoji, color, categoryId: string, viewersCanPostReactions: bool, hideIfPermissionsNotMet: bool) =
self.controller.createCommunityChannel(name, description, emoji, color, categoryId, viewersCanPostReactions, hideIfPermissionsNotMet)
method editCommunityChannel*(self: Module, channelId, name, description, emoji, color,
categoryId: string, position: int, viewersCanPostReactions: bool) =
categoryId: string, position: int, viewersCanPostReactions: bool, hideIfPermissionsNotMet: bool) =
self.controller.editCommunityChannel(channelId, name, description, emoji, color, categoryId,
position, viewersCanPostReactions)
position, viewersCanPostReactions, hideIfPermissionsNotMet)
method createCommunityCategory*(self: Module, name: string, channels: seq[string]) =
self.controller.createCommunityCategory(name, channels)
@ -1164,6 +1200,9 @@ method prepareEditCategoryModel*(self: Module, categoryId: string) =
active=false,
c.position,
categoryId="",
hideIfPermissionsNotMet=false,
viewOnlyPermissionsSatisfied = true,
viewAndPostPermissionsSatisfied = true
)
self.view.editCategoryChannelsModel().appendItem(chatItem)
let catChats = self.controller.getChats(communityId, categoryId)
@ -1186,6 +1225,9 @@ method prepareEditCategoryModel*(self: Module, categoryId: string) =
active=false,
c.position,
categoryId,
hideIfPermissionsNotMet=false,
viewOnlyPermissionsSatisfied = true,
viewAndPostPermissionsSatisfied = true
)
self.view.editCategoryChannelsModel().appendItem(chatItem, ignoreCategory = true)

View File

@ -31,6 +31,7 @@ QtObject:
permissionsCheckOngoing: bool
isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin: bool
shardingInProgress: bool
allChannelsAreHiddenBecauseNotPermitted: bool
proc delete*(self: View) =
self.model.delete
@ -269,9 +270,10 @@ QtObject:
emoji: string,
color: string,
categoryId: string,
viewersCanPostReactions: bool
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool,
) {.slot.} =
self.delegate.createCommunityChannel(name, description, emoji, color, categoryId, viewersCanPostReactions)
self.delegate.createCommunityChannel(name, description, emoji, color, categoryId, viewersCanPostReactions, hideIfPermissionsNotMet)
proc editCommunityChannel*(
self: View,
@ -283,6 +285,7 @@ QtObject:
categoryId: string,
position: int,
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool
) {.slot.} =
self.delegate.editCommunityChannel(
channelId,
@ -293,6 +296,7 @@ QtObject:
categoryId,
position,
viewersCanPostReactions,
hideIfPermissionsNotMet
)
proc leaveCommunity*(self: View) {.slot.} =
@ -490,3 +494,18 @@ QtObject:
self.setShardingInProgress(true)
self.delegate.setCommunityShard(shardIndex)
proc allChannelsAreHiddenBecauseNotPermittedChanged*(self: View) {.signal.}
proc getAllChannelsAreHiddenBecauseNotPermitted*(self: View): bool {.slot.} =
return self.allChannelsAreHiddenBecauseNotPermitted
QtProperty[bool] allChannelsAreHiddenBecauseNotPermitted:
read = getAllChannelsAreHiddenBecauseNotPermitted
notify = allChannelsAreHiddenBecauseNotPermittedChanged
proc refreshAllChannelsAreHiddenBecauseNotPermittedChanged*(self: View) =
let allAreHidden = self.model.allChannelsAreHiddenBecauseNotPermitted()
if (allAreHidden == self.allChannelsAreHiddenBecauseNotPermitted):
return
self.allChannelsAreHiddenBecauseNotPermitted = allAreHidden
self.allChannelsAreHiddenBecauseNotPermittedChanged()

View File

@ -89,6 +89,7 @@ type ChatDto* = object
categoryId*: string
highlight*: bool
permissions*: Permission
hideIfPermissionsNotMet*: bool
type ChannelGroupDto* = object
id*: string
@ -152,7 +153,8 @@ proc `$`*(self: ChatDto): string =
firstMessageTimestamp: {self.firstMessageTimestamp},
categoryId: {self.categoryId},
position: {self.position},
highlight: {self.highlight}
highlight: {self.highlight},
hideIfPermissionsNotMet: {self.hideIfPermissionsNotMet}
)"""
proc toCheckPermissionsResultDto*(jsonObj: JsonNode): CheckPermissionsResultDto =
@ -280,6 +282,7 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
# Communities have `categoryID` and chats have `categoryId`
# This should be fixed in status-go, but would be a breaking change
discard jsonObj.getProp("categoryID", result.categoryId)
discard jsonObj.getProp("hideIfPermissionsNotMet", result.hideIfPermissionsNotMet)
discard jsonObj.getProp("position", result.position)
discard jsonObj.getProp("communityId", result.communityId)
discard jsonObj.getProp("profile", result.profile)

View File

@ -637,7 +637,8 @@ QtObject:
)
if chat.name != prevChat.name or chat.description != prevChat.description or chat.color != prevChat.color or
chat.emoji != prevChat.emoji or chat.viewersCanPostReactions != prevChat.viewersCanPostReactions:
chat.emoji != prevChat.emoji or chat.viewersCanPostReactions != prevChat.viewersCanPostReactions or
chat.hideIfPermissionsNotMet != prevChat.hideIfPermissionsNotMet:
var updatedChat = chat
# TODO improve this in https://github.com/status-im/status-desktop/issues/12595
@ -1278,10 +1279,11 @@ QtObject:
color: string,
categoryId: string,
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool
) =
try:
let response = status_go.createCommunityChannel(communityId, name, description, emoji, color, categoryId,
viewersCanPostReactions)
viewersCanPostReactions, hideIfPermissionsNotMet)
if not response.error.isNil:
let error = Json.decode($response.error, RpcError)
@ -1318,6 +1320,7 @@ QtObject:
categoryId: string,
position: int,
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool
) =
try:
let response = status_go.editCommunityChannel(
@ -1329,7 +1332,8 @@ QtObject:
color,
categoryId,
position,
viewersCanPostReactions
viewersCanPostReactions,
hideIfPermissionsNotMet
)
if response.error != nil:
@ -2282,6 +2286,13 @@ QtObject:
else:
return community.declinedRequestsToJoin[indexDeclined].publicKey
proc checkChatIsLocked*(self: Service, communityId: string, chatId: string): bool =
if not self.communities.hasKey(communityId):
return false
let community = self.getCommunityById(communityId)
return community.channelPermissions.channels.hasKey(chatId) and not community.channelPermissions.channels[chatId].viewAndPostPermissions.satisfied
proc checkChatHasPermissions*(self: Service, communityId: string, chatId: string): bool =
let community = self.getCommunityById(communityId)
for id, tokenPermission in community.tokenPermissions:
@ -2291,13 +2302,6 @@ QtObject:
return true
return false
proc checkChatIsLocked*(self: Service, communityId: string, chatId: string): bool =
if not self.communities.hasKey(communityId):
return false
let community = self.getCommunityById(communityId)
return community.channelPermissions.channels.hasKey(chatId) and not community.channelPermissions.channels[chatId].viewAndPostPermissions.satisfied
proc shareCommunityUrlWithChatKey*(self: Service, communityId: string): string =
try:
let response = status_go.shareCommunityUrlWithChatKey(communityId)

View File

@ -304,6 +304,7 @@ proc createCommunityChannel*(
color: string,
categoryId: string,
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool
): RpcResponse[JsonNode] =
result = callPrivateRPC("createCommunityChat".prefix, %*[
communityId,
@ -319,6 +320,7 @@ proc createCommunityChannel*(
},
"category_id": categoryId,
"viewers_can_post_reactions": viewersCanPostReactions,
"hide_if_permissions_not_met": hideIfPermissionsNotMet
}])
proc editCommunityChannel*(
@ -331,6 +333,7 @@ proc editCommunityChannel*(
categoryId: string,
position: int,
viewersCanPostReactions: bool,
hideIfPermissionsNotMet: bool
): RpcResponse[JsonNode] =
result = callPrivateRPC("editCommunityChat".prefix, %*[
communityId,
@ -348,6 +351,7 @@ proc editCommunityChannel*(
"category_id": categoryId,
"position": position,
"viewers_can_post_reactions": viewersCanPostReactions,
"hide_if_permissions_not_met": hideIfPermissionsNotMet
}])
proc reorderCommunityCategories*(communityId: string, categoryId: string, position: int): RpcResponse[JsonNode] =

View File

@ -56,6 +56,12 @@ Item {
model: SortFilterProxyModel {
sourceModel: root.model
filters: [
ValueFilter {
roleName: "shouldBeHiddenBecausePermissionsAreNotMet"
value: false
}
]
sorters: [
RoleSorter {
roleName: "categoryPosition"

View File

@ -61,6 +61,8 @@ QtObject {
root.communitiesModuleInst.prepareTokenModelForCommunity(publicKey)
}
readonly property bool allChannelsAreHiddenBecauseNotPermitted: root.chatCommunitySectionModule.allChannelsAreHiddenBecauseNotPermitted
readonly property bool requirementsCheckPending: root.communitiesModuleInst.requirementsCheckPending
readonly property var permissionsModel: !!root.communitiesModuleInst.spectatedCommunityPermissionModel ?
@ -336,13 +338,13 @@ QtObject {
}
function createCommunityChannel(channelName, channelDescription, channelEmoji, channelColor,
categoryId, viewersCanPostReactions) {
categoryId, viewersCanPostReactions, hideIfPermissionsNotMet) {
chatCommunitySectionModule.createCommunityChannel(channelName, channelDescription,
channelEmoji.trim(), channelColor, categoryId, viewersCanPostReactions);
channelEmoji.trim(), channelColor, categoryId, viewersCanPostReactions, hideIfPermissionsNotMet);
}
function editCommunityChannel(chatId, newName, newDescription, newEmoji, newColor,
newCategory, channelPosition, viewOnlyCanAddReaction) {
newCategory, channelPosition, viewOnlyCanAddReaction, hideIfPermissionsNotMet) {
chatCommunitySectionModule.editCommunityChannel(
chatId,
newName,
@ -351,7 +353,8 @@ QtObject {
newColor,
newCategory,
channelPosition,
viewOnlyCanAddReaction
viewOnlyCanAddReaction,
hideIfPermissionsNotMet
)
}

View File

@ -34,7 +34,8 @@ Item {
string chatColor,
string chatCategoryId,
int channelPosition,
var deleteDialog)
var deleteDialog,
bool hideIfPermissionsNotMet)
function addRemoveGroupMember() {
root.state = d.stateMembersSelectorContent
@ -166,6 +167,7 @@ Item {
chatType = chatContentModule.chatDetails.type
chatMuted = chatContentModule.chatDetails.muted
channelPosition = chatContentModule.chatDetails.position
hideIfPermissionsNotMet = chatContentModule.chatDetails.hideIfPermissionsNotMet
}
onMuteChat: {
@ -229,7 +231,8 @@ Item {
root.displayEditChannelPopup(chatId, chatName, chatDescription,
chatEmoji, chatColor,
chatCategoryId, channelPosition,
contextMenu.deleteChatConfirmationDialog);
contextMenu.deleteChatConfirmationDialog,
hideIfPermissionsNotMet);
}
onAddRemoveGroupMember: {
root.addRemoveGroupMember()

View File

@ -12,9 +12,11 @@ import shared.views.chat 1.0
import shared.stores.send 1.0
import SortFilterProxyModel 0.2
import StatusQ.Core 0.1
import StatusQ.Layout 0.1
import StatusQ.Popups 0.1
import StatusQ.Controls 0.1
import QtQuick.Layouts 1.15
import "."
import "../panels"
@ -52,6 +54,7 @@ StatusSectionLayout {
property bool hasViewAndPostPermissions: false
property bool amIMember: false
property bool amISectionAdmin: false
readonly property bool allChannelsAreHiddenBecauseNotPermitted: rootStore.allChannelsAreHiddenBecauseNotPermitted
property bool isInvitationPending: false
@ -139,6 +142,7 @@ StatusSectionLayout {
hasUnseenNotifications: activityCenterStore.hasUnseenNotifications
headerContent: Loader {
visible: !root.allChannelsAreHiddenBecauseNotPermitted
id: headerContentLoader
sourceComponent: root.contentLocked ? joinCommunityHeaderPanelComponent : chatHeaderContentViewComponent
}
@ -152,7 +156,8 @@ StatusSectionLayout {
centerPanel: Loader {
anchors.fill: parent
sourceComponent: root.contentLocked ? joinCommunityCenterPanelComponent : chatColumnViewComponent
sourceComponent: root.allChannelsAreHiddenBecauseNotPermitted ? allChatsAreHiddenComponent :
(root.contentLocked ? joinCommunityCenterPanelComponent : chatColumnViewComponent)
}
showRightPanel: {
@ -201,7 +206,8 @@ StatusSectionLayout {
channelColor: chatColor,
categoryId: chatCategoryId,
channelPosition: channelPosition,
deleteChatConfirmationDialog: deleteDialog
deleteChatConfirmationDialog: deleteDialog,
hideIfPermissionsNotMet: hideIfPermissionsNotMet
});
}
}
@ -260,6 +266,18 @@ StatusSectionLayout {
}
}
Component {
id: allChatsAreHiddenComponent
StatusBaseText {
Layout.fillWidth: true
Layout.fillHeight: true
visible: root.allChannelsAreHiddenBecauseNotPermitted
text: qsTr("Sorry, you don't hodl the necessary tokens to view or post in any of <b>%1</b> channels").arg(sectionItemModel.name)
color: Theme.palette.dangerColor1
}
}
Component {
id: contactsColumnComponent
ContactsColumnView {

View File

@ -32,7 +32,7 @@ StatusStackModal {
property bool isEdit: false
property bool isDeleteable: false
property bool viewOnlyCanAddReaction
property bool hideIfPermissionsNotMet
property bool hideIfPermissionsNotMet: false
property string communityId: ""
property string chatId: "_newChannel"
@ -58,8 +58,8 @@ StatusStackModal {
readonly property int maxChannelDescLength: 140
// channel signals
signal createCommunityChannel(string chName, string chDescription, string chEmoji, string chColor, string chCategoryId, bool viewOnlyCanAddReaction)
signal editCommunityChannel(string chName, string chDescription, string chEmoji, string chColor, string chCategoryId, bool viewOnlyCanAddReaction)
signal createCommunityChannel(string chName, string chDescription, string chEmoji, string chColor, string chCategoryId, bool viewOnlyCanAddReaction, bool hideIfPermissionsNotMet)
signal editCommunityChannel(string chName, string chDescription, string chEmoji, string chColor, string chCategoryId, bool viewOnlyCanAddReaction, bool hideIfPermissionsNotMet)
signal deleteCommunityChannel()
// Permissions signals:
@ -187,14 +187,16 @@ StatusStackModal {
emoji,
colorPanel.color.toString().toUpperCase(),
root.categoryId,
d.viewOnlyCanAddReaction)
d.viewOnlyCanAddReaction,
d.hideIfPermissionsNotMet)
} else {
root.editCommunityChannel(StatusQUtils.Utils.filterXSS(nameInput.input.text),
StatusQUtils.Utils.filterXSS(descriptionTextArea.text),
emoji,
colorPanel.color.toString().toUpperCase(),
root.categoryId,
d.viewOnlyCanAddReaction)
d.viewOnlyCanAddReaction,
d.hideIfPermissionsNotMet)
}
if (d.channelEditModel.dirtyPermissions) {
@ -795,7 +797,6 @@ StatusStackModal {
Layout.rightMargin: Style.current.padding
leftSide: false
text: qsTr("Hide channel from members who don't have permissions to view the channel")
visible: false //TODO: Enable connect to the backend when it's ready https://github.com/status-im/status-desktop/issues/13291
checked: d.hideIfPermissionsNotMet
onToggled: {
d.hideIfPermissionsNotMet = checked;

View File

@ -332,6 +332,7 @@ Item {
channelPosition = obj.position
chatCategoryId = obj.categoryId
viewersCanPostReactions = obj.viewersCanPostReactions
hideIfPermissionsNotMet = obj.hideIfPermissionsNotMet
} catch (e) {
console.error("error parsing chat item json object, id: ", id, " error: ", e)
close()
@ -387,7 +388,8 @@ Item {
chatId: chatContextMenuView.chatId,
channelPosition: channelPosition,
viewOnlyCanAddReaction: viewersCanPostReactions,
deleteChatConfirmationDialog: deleteChatConfirmationDialog
deleteChatConfirmationDialog: deleteChatConfirmationDialog,
hideIfPermissionsNotMet: hideIfPermissionsNotMet
});
}
}
@ -628,9 +630,9 @@ Item {
property var deleteChatConfirmationDialog
onCreateCommunityChannel: function (chName, chDescription, chEmoji, chColor,
chCategoryId) {
chCategoryId, hideIfPermissionsNotMet) {
root.store.createCommunityChannel(chName, chDescription, chEmoji, chColor,
chCategoryId, viewOnlyCanAddReaction)
chCategoryId, viewOnlyCanAddReaction, hideIfPermissionsNotMet)
chatId = root.store.currentChatContentModule().chatDetails.id
}
onEditCommunityChannel: {
@ -641,7 +643,8 @@ Item {
chColor,
chCategoryId,
channelPosition,
viewOnlyCanAddReaction);
viewOnlyCanAddReaction,
hideIfPermissionsNotMet);
}
onAddPermissions: function (permissions) {

View File

@ -29,6 +29,7 @@ StatusMenu {
property bool viewersCanPostReactions: true
property bool showDebugOptions: false
property alias deleteChatConfirmationDialog: deleteChatConfirmationDialogComponent
property bool hideIfPermissionsNotMet: false
signal displayProfilePopup(string publicKey)
signal displayEditChannelPopup(string chatId)

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit b0a0f078c43b38e555d2683ef56b58e412928e13
Subproject commit b9d9938209471c67092e95e4f5d1ebace3070a46