feat: owner and token master permissions (#11942)

This commit is contained in:
Mykhailo Prakhov 2023-08-22 20:09:34 +02:00 committed by GitHub
parent 8941b218d5
commit 3f5df7e3ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 175 additions and 48 deletions

View File

@ -563,11 +563,12 @@ method amIChatAdmin*(self: Module): bool =
let chatDto = self.controller.getChatDetails() let chatDto = self.controller.getChatDetails()
for member in chatDto.members: for member in chatDto.members:
if (member.id == singletonInstance.userProfile.getPubKey()): if (member.id == singletonInstance.userProfile.getPubKey()):
return member.role == MemberRole.Owner or member.role == MemberRole.Admin return member.role == MemberRole.Owner or member.role == MemberRole.Admin or member.role == MemberRole.TokenMaster
return false return false
else: else:
let communityDto = self.controller.getCommunityDetails() let communityDto = self.controller.getCommunityDetails()
return communityDto.memberRole == MemberRole.Owner or communityDto.memberRole == MemberRole.Admin return communityDto.memberRole == MemberRole.Owner or
communityDto.memberRole == MemberRole.Admin or communityDto.memberRole == MemberRole.TokenMaster
method pinMessageAllowedForMembers*(self: Module): bool = method pinMessageAllowedForMembers*(self: Module): bool =
if(self.controller.belongsToCommunity()): if(self.controller.belongsToCommunity()):
@ -737,7 +738,8 @@ method markMessagesAsRead*(self: Module, messages: seq[string]) =
self.view.model().markAsSeen(messages) self.view.model().markAsSeen(messages)
method updateCommunityDetails*(self: Module, community: CommunityDto) = method updateCommunityDetails*(self: Module, community: CommunityDto) =
self.view.setAmIChatAdmin(community.memberRole == MemberRole.Owner or community.memberRole == MemberRole.Admin) self.view.setAmIChatAdmin(community.memberRole == MemberRole.Owner or
community.memberRole == MemberRole.Admin or community.memberRole == MemberRole.TokenMaster)
self.view.setIsPinMessageAllowedForMembers(community.adminSettings.pinMessageAllMembersEnabled) self.view.setIsPinMessageAllowedForMembers(community.adminSettings.pinMessageAllMembersEnabled)
proc setChatDetails(self: Module, chatDetails: ChatDto) = proc setChatDetails(self: Module, chatDetails: ChatDto) =

View File

@ -396,11 +396,12 @@ method amIChatAdmin*(self: Module): bool =
let chatDto = self.controller.getChatDetails() let chatDto = self.controller.getChatDetails()
for member in chatDto.members: for member in chatDto.members:
if member.id == singletonInstance.userProfile.getPubKey(): if member.id == singletonInstance.userProfile.getPubKey():
return member.role == MemberRole.Owner or member.role == MemberRole.Admin return member.role == MemberRole.Owner or member.role == MemberRole.Admin or member.role == MemberRole.TokenMaster
return false return false
else: else:
let communityDto = self.controller.getCommunityDetails() let communityDto = self.controller.getCommunityDetails()
return communityDto.memberRole == MemberRole.Owner or communityDto.memberRole == MemberRole.Admin return communityDto.memberRole == MemberRole.Owner or
communityDto.memberRole == MemberRole.Admin or communityDto.memberRole == MemberRole.TokenMaster
method onUpdateViewOnlyPermissionsSatisfied*(self: Module, value: bool) = method onUpdateViewOnlyPermissionsSatisfied*(self: Module, value: bool) =
self.view.setViewOnlyPermissionsSatisfied(value) self.view.setViewOnlyPermissionsSatisfied(value)

View File

@ -271,12 +271,6 @@ proc rebuildCommunityTokenPermissionsModel(self: Module) =
let tokenPermissionItem = buildTokenPermissionItem(tokenPermission, chats) let tokenPermissionItem = buildTokenPermissionItem(tokenPermission, chats)
tokenPermissionsItems.add(tokenPermissionItem) tokenPermissionsItems.add(tokenPermissionItem)
let memberPermissions = filter(tokenPermissionsItems, tokenPermissionsItem =>
tokenPermissionsItem.getType() == TokenPermissionType.BecomeMember.int)
let adminPermissions = filter(tokenPermissionsItems, tokenPermissionsItem =>
tokenPermissionsItem.getType() == TokenPermissionType.BecomeAdmin.int)
self.view.tokenPermissionsModel().setItems(tokenPermissionsItems) self.view.tokenPermissionsModel().setItems(tokenPermissionsItems)
self.reevaluateRequiresTokenPermissionToJoin() self.reevaluateRequiresTokenPermissionToJoin()

View File

@ -375,6 +375,8 @@ proc init*(self: Controller) =
self.getRemainingSupply(communityToken.chainId, communityToken.address), self.getRemainingSupply(communityToken.chainId, communityToken.address),
self.getRemoteDestructedAmount(communityToken.chainId, communityToken.address)) self.getRemoteDestructedAmount(communityToken.chainId, communityToken.address))
self.delegate.onRemoteDestructed(communityToken.communityId, communityToken.chainId, communityToken.address, args.remoteDestructAddresses) self.delegate.onRemoteDestructed(communityToken.communityId, communityToken.chainId, communityToken.address, args.remoteDestructAddresses)
if args.status == ContractTransactionStatus.Completed:
self.delegate.onRequestReevaluateMembersPermissionsIfRequired(communityToken.communityId, communityToken.chainId, communityToken.address)
self.events.on(SIGNAL_AIRDROP_STATUS) do(e: Args): self.events.on(SIGNAL_AIRDROP_STATUS) do(e: Args):
let args = AirdropArgs(e) let args = AirdropArgs(e)
@ -383,6 +385,8 @@ proc init*(self: Controller) =
communityToken.address, communityToken.supply, communityToken.address, communityToken.supply,
self.getRemainingSupply(communityToken.chainId, communityToken.address), self.getRemainingSupply(communityToken.chainId, communityToken.address),
self.getRemoteDestructedAmount(communityToken.chainId, communityToken.address)) self.getRemoteDestructedAmount(communityToken.chainId, communityToken.address))
if args.status == ContractTransactionStatus.Completed:
self.delegate.onRequestReevaluateMembersPermissionsIfRequired(communityToken.communityId, communityToken.chainId, communityToken.address)
self.events.on(SIGNAL_COMMUNITY_TOKEN_OWNERS_FETCHED) do(e: Args): self.events.on(SIGNAL_COMMUNITY_TOKEN_OWNERS_FETCHED) do(e: Args):
let args = CommunityTokenOwnersArgs(e) let args = CommunityTokenOwnersArgs(e)
@ -543,3 +547,6 @@ proc getColorId*(self: Controller, pubkey: string): int =
proc asyncGetRevealedAccountsForAllMembers*(self: Controller, communityId: string) = proc asyncGetRevealedAccountsForAllMembers*(self: Controller, communityId: string) =
self.communityService.asyncGetRevealedAccountsForAllMembers(communityId) self.communityService.asyncGetRevealedAccountsForAllMembers(communityId)
proc asyncReevaluateCommunityMembersPermissions*(self: Controller, communityId: string) =
self.communityService.asyncReevaluateCommunityMembersPermissions(communityId)

View File

@ -315,6 +315,9 @@ method onBurnStateChanged*(self: AccessInterface, communityId: string, chainId:
method onRemoteDestructed*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, addresses: seq[string]) {.base.} = method onRemoteDestructed*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string, addresses: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method onRequestReevaluateMembersPermissionsIfRequired*(self: AccessInterface, communityId: string, chainId: int, contractAddress: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onAcceptRequestToJoinFailed*(self: AccessInterface, communityId: string, memberKey: string, requestId: string) {.base.} = method onAcceptRequestToJoinFailed*(self: AccessInterface, communityId: string, memberKey: string, requestId: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -264,8 +264,7 @@ proc createChannelGroupItem[T](self: Module[T], channelGroup: ChannelGroupDto):
) )
# Get community members' revealed accounts # Get community members' revealed accounts
# We will update the model later when we finish loading the accounts # We will update the model later when we finish loading the accounts
# TODO add TokenMaster here too when it's available if communityDetails.memberRole == MemberRole.Owner or communityDetails.memberRole == MemberRole.TokenMaster:
if communityDetails.memberRole == MemberRole.Owner:
self.controller.asyncGetRevealedAccountsForAllMembers(channelGroup.id) self.controller.asyncGetRevealedAccountsForAllMembers(channelGroup.id)
let unviewedCount = channelGroup.unviewedMessagesCount let unviewedCount = channelGroup.unviewedMessagesCount
@ -1106,6 +1105,16 @@ method onRemoteDestructed*[T](self: Module[T], communityId: string, chainId: int
if item.id != "": if item.id != "":
item.updateRemoteDestructedAddresses(chainId, contractAddress, addresses) item.updateRemoteDestructedAddresses(chainId, contractAddress, addresses)
method onRequestReevaluateMembersPermissionsIfRequired*[T](self: Module[T], communityId: string, chainId: int, contractAddress: string) =
let communityDto = self.controller.getCommunityById(communityId)
for _, tokenPermission in communityDto.tokenPermissions.pairs:
for tokenCriteria in tokenPermission.tokenCriteria:
if tokenCriteria.contractAddresses.hasKey(chainId):
let actualAddress = tokenCriteria.contractAddresses[chainId]
if actualAddress == contractAddress:
self.controller.asyncReevaluateCommunityMembersPermissions(communityId)
return
method onAcceptRequestToJoinLoading*[T](self: Module[T], communityId: string, memberKey: string) = method onAcceptRequestToJoinLoading*[T](self: Module[T], communityId: string, memberKey: string) =
let item = self.view.model().getItemById(communityId) let item = self.view.model().getItemById(communityId)
if item.id != "": if item.id != "":

View File

@ -53,6 +53,7 @@ type MemberRole* {.pure} = enum
ManageUsers ManageUsers
ModerateContent ModerateContent
Admin Admin
TokenMaster
type MembershipRequestState* {.pure} = enum type MembershipRequestState* {.pure} = enum
None = 0, None = 0,

View File

@ -246,6 +246,8 @@ proc toChannelMember*(jsonObj: JsonNode, memberId: string, joined: bool): ChatMe
result.role = MemberRole.ManageUsers result.role = MemberRole.ManageUsers
elif roles.contains(MemberRole.ModerateContent.int): elif roles.contains(MemberRole.ModerateContent.int):
result.role = MemberRole.ModerateContent result.role = MemberRole.ModerateContent
elif roles.contains(MemberRole.TokenMaster.int):
result.role = MemberRole.TokenMaster
result.joined = joined result.joined = joined

View File

@ -205,3 +205,22 @@ const asyncGetRevealedAccountsForAllMembersTask: Task = proc(argEncoded: string)
"communityId": arg.communityId, "communityId": arg.communityId,
"error": e.msg, "error": e.msg,
}) })
type
AsyncReevaluateCommunityMembersPermissionsArg = ref object of QObjectTaskArg
communityId: string
const asyncReevaluateCommunityMembersPermissionsTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncReevaluateCommunityMembersPermissionsArg](argEncoded)
try:
let response = status_go.reevaluateCommunityMembersPermissions(arg.communityId)
arg.finish(%* {
"communityId": arg.communityId,
"response": response,
"error": "",
})
except Exception as e:
arg.finish(%* {
"communityId": arg.communityId,
"error": e.msg,
})

View File

@ -56,6 +56,8 @@ type TokenPermissionType* {.pure.}= enum
BecomeMember = 2, BecomeMember = 2,
View = 3, View = 3,
ViewAndPost = 4, ViewAndPost = 4,
BecomeTokenMaster = 5,
BecomeTokenOwner = 6
type TokenType* {.pure.}= enum type TokenType* {.pure.}= enum
Unknown = 0, Unknown = 0,

View File

@ -677,7 +677,8 @@ QtObject:
let communities = parseCommunities(responseObj["communities"]) let communities = parseCommunities(responseObj["communities"])
for community in communities: for community in communities:
self.communities[community.id] = community self.communities[community.id] = community
if community.memberRole == MemberRole.Owner or community.memberRole == MemberRole.Admin: if community.memberRole == MemberRole.Owner or
community.memberRole == MemberRole.Admin or community.memberRole == MemberRole.TokenMaster:
self.communities[community.id].pendingRequestsToJoin = self.allPendingRequestsToJoinForCommunity(community.id) self.communities[community.id].pendingRequestsToJoin = self.allPendingRequestsToJoinForCommunity(community.id)
self.communities[community.id].declinedRequestsToJoin = self.declinedRequestsToJoinForCommunity(community.id) self.communities[community.id].declinedRequestsToJoin = self.declinedRequestsToJoinForCommunity(community.id)
self.communities[community.id].canceledRequestsToJoin = self.canceledRequestsToJoinForCommunity(community.id) self.communities[community.id].canceledRequestsToJoin = self.canceledRequestsToJoinForCommunity(community.id)
@ -2079,3 +2080,22 @@ QtObject:
)) ))
except Exception as e: except Exception as e:
error "error while getting the community members' revealed addressesses", msg = e.msg error "error while getting the community members' revealed addressesses", msg = e.msg
proc asyncReevaluateCommunityMembersPermissions*(self: Service, communityId: string) =
let arg = AsyncGetRevealedAccountsForAllMembersArg(
tptr: cast[ByteAddress](asyncReevaluateCommunityMembersPermissionsTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onAsyncReevaluateCommunityMembersPermissionsCompleted",
communityId: communityId,
)
self.threadpool.start(arg)
proc onAsyncReevaluateCommunityMembersPermissionsCompleted*(self: Service, response: string) {.slot.} =
try:
let rpcResponseObj = response.parseJson
if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "":
raise newException(RpcException, rpcResponseObj["error"].getStr)
except Exception as e:
error "error while reevaluating community members permissions", msg = e.msg

View File

@ -593,7 +593,11 @@ QtObject:
proc contractOwnerName*(self: Service, contractOwnerAddress: string): string = proc contractOwnerName*(self: Service, contractOwnerAddress: string): string =
try: try:
return self.walletAccountService.getAccountByAddress(contractOwnerAddress).name let res = self.walletAccountService.getAccountByAddress(contractOwnerAddress)
if res == nil:
error "getAccountByAddress result is nil"
return ""
return res.name
except RpcException: except RpcException:
error "Error getting contract owner name", message = getCurrentExceptionMsg() error "Error getting contract owner name", message = getCurrentExceptionMsg()

View File

@ -78,6 +78,13 @@ proc checkPermissionsToJoinCommunity*(communityId: string, addresses: seq[string
"addresses": addresses "addresses": addresses
}]) }])
proc reevaluateCommunityMembersPermissions*(
communityId: string,
): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("reevaluateCommunityMembersPermissions".prefix, %*[{
"communityId": communityId
}])
proc checkCommunityChannelPermissions*(communityId: string, chatId: string): RpcResponse[JsonNode] {.raises: [Exception].} = proc checkCommunityChannelPermissions*(communityId: string, chatId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("checkCommunityChannelPermissions".prefix, %*[{ result = callPrivateRPC("checkCommunityChannelPermissions".prefix, %*[{
"communityId": communityId, "communityId": communityId,

View File

@ -55,7 +55,8 @@ StackLayout {
accessType: communityData.access accessType: communityData.access
joinCommunity: true joinCommunity: true
amISectionAdmin: communityData.memberRole === Constants.memberRole.owner || amISectionAdmin: communityData.memberRole === Constants.memberRole.owner ||
communityData.memberRole === Constants.memberRole.admin communityData.memberRole === Constants.memberRole.admin ||
communityData.memberRole === Constants.memberRole.tokenMaster
communityItemsModel: root.rootStore.communityItemsModel communityItemsModel: root.rootStore.communityItemsModel
requirementsMet: root.permissionsStore.allTokenRequirementsMet requirementsMet: root.permissionsStore.allTokenRequirementsMet
requirementsCheckPending: root.rootStore.permissionsCheckOngoing requirementsCheckPending: root.rootStore.permissionsCheckOngoing
@ -114,7 +115,8 @@ StackLayout {
sectionItemModel: root.sectionItemModel sectionItemModel: root.sectionItemModel
amIMember: chatItem.amIMember amIMember: chatItem.amIMember
amISectionAdmin: root.sectionItemModel.memberRole === Constants.memberRole.owner || amISectionAdmin: root.sectionItemModel.memberRole === Constants.memberRole.owner ||
root.sectionItemModel.memberRole === Constants.memberRole.admin root.sectionItemModel.memberRole === Constants.memberRole.admin ||
root.sectionItemModel.memberRole === Constants.memberRole.tokenMaster
hasViewOnlyPermissions: root.permissionsStore.viewOnlyPermissionsModel.count > 0 hasViewOnlyPermissions: root.permissionsStore.viewOnlyPermissionsModel.count > 0
hasViewAndPostPermissions: root.permissionsStore.viewAndPostPermissionsModel.count > 0 hasViewAndPostPermissions: root.permissionsStore.viewAndPostPermissionsModel.count > 0
viewOnlyPermissionsModel: root.permissionsStore.viewOnlyPermissionsModel viewOnlyPermissionsModel: root.permissionsStore.viewOnlyPermissionsModel

View File

@ -154,7 +154,9 @@ Item {
currentFleet = root.chatSectionModule.getCurrentFleet() currentFleet = root.chatSectionModule.getCurrentFleet()
isCommunityChat = root.chatSectionModule.isCommunity() isCommunityChat = root.chatSectionModule.isCommunity()
amIChatAdmin = obj.memberRole === Constants.memberRole.owner || obj.memberRole === Constants.memberRole.admin amIChatAdmin = obj.memberRole === Constants.memberRole.owner ||
obj.memberRole === Constants.memberRole.admin ||
obj.memberRole === Constants.memberRole.tokenMaster
chatId = obj.itemId chatId = obj.itemId
chatName = obj.name chatName = obj.name
chatDescription = obj.description chatDescription = obj.description

View File

@ -152,15 +152,60 @@ Control{
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
StatusListItemTag { ListModel {
height: d.flowRowHeight id: tokenOwnerModel
title: PermissionTypes.getName(root.permissionType)
asset.name: PermissionTypes.getIcon(root.permissionType) ListElement { permissionType: PermissionTypes.Type.Owner }
asset.isImage: false ListElement { permissionType: PermissionTypes.Type.TokenMaster }
asset.bgColor: "transparent" ListElement { permissionType: PermissionTypes.Type.Admin }
closeButtonVisible: false }
titleText.color: Theme.palette.primaryColor1
titleText.font.pixelSize: d.tagTextPixelSize ListModel {
id: tokenMasterModel
ListElement { permissionType: PermissionTypes.Type.TokenMaster }
ListElement { permissionType: PermissionTypes.Type.Admin }
}
ListModel {
id: regularRoleModel
ListElement { permissionType: PermissionTypes.Type.None }
}
Repeater {
id: rolesRepeater
model: {
if (root.permissionType === PermissionTypes.Type.Owner)
return tokenOwnerModel
if (root.permissionType === PermissionTypes.Type.TokenMaster)
return tokenMasterModel
return regularRoleModel
}
Flow {
spacing: 6
StatusListItemTag {
height: d.flowRowHeight
title: PermissionTypes.getName(model.permissionType === PermissionTypes.Type.None
? root.permissionType : model.permissionType)
asset.name: PermissionTypes.getIcon(root.permissionType)
asset.isImage: false
asset.bgColor: "transparent"
closeButtonVisible: false
titleText.color: Theme.palette.primaryColor1
titleText.font.pixelSize: d.tagTextPixelSize
}
StatusBaseText {
height: d.flowRowHeight
visible: model.index < rolesRepeater.model.count - 1
font.pixelSize: d.itemTextPixelSize
text: qsTr("and")
verticalAlignment: Text.AlignVCenter
}
}
} }
StatusBaseText { StatusBaseText {

View File

@ -6,7 +6,7 @@ import StatusQ.Core.Theme 0.1
QtObject { QtObject {
enum Type { enum Type {
None, Admin, Member, Read, ViewAndPost, Moderator None, Admin, Member, Read, ViewAndPost, TokenMaster, Owner
} }
enum State { enum State {
@ -16,15 +16,17 @@ QtObject {
function getName(type) { function getName(type) {
switch (type) { switch (type) {
case PermissionTypes.Type.Admin: case PermissionTypes.Type.Admin:
return qsTr("Become admin") return qsTr("Become an admin")
case PermissionTypes.Type.Member: case PermissionTypes.Type.Member:
return qsTr("Become member") return qsTr("Become member")
case PermissionTypes.Type.Read: case PermissionTypes.Type.Read:
return qsTr("View only") return qsTr("View only")
case PermissionTypes.Type.ViewAndPost: case PermissionTypes.Type.ViewAndPost:
return qsTr("View and post") return qsTr("View and post")
case PermissionTypes.Type.Moderator: case PermissionTypes.Type.TokenMaster:
return qsTr("Moderate") return qsTr("Admin community tokens")
case PermissionTypes.Type.Owner:
return qsTr("Admin TokenMaster tokens")
} }
return "" return ""
@ -40,7 +42,9 @@ QtObject {
return "edit" return "edit"
case PermissionTypes.Type.Read: case PermissionTypes.Type.Read:
return "show" return "show"
case PermissionTypes.Type.Moderator: case PermissionTypes.Type.TokenMaster:
return "arbitrator"
case PermissionTypes.Type.Owner:
return "arbitrator" return "arbitrator"
} }
@ -58,8 +62,6 @@ QtObject {
return `${generalInfo}<br><br>${warningStyled} ${warningExplanation}` return `${generalInfo}<br><br>${warningStyled} ${warningExplanation}`
case PermissionTypes.Type.Member: case PermissionTypes.Type.Member:
return qsTr("Anyone who meets the requirements will be allowed to join your community") return qsTr("Anyone who meets the requirements will be allowed to join your community")
case PermissionTypes.Type.Moderator:
return qsTr("Members who meet the requirements will be allowed to read, write, ban members and pin messages in the selected channels")
case PermissionTypes.Type.ViewAndPost: case PermissionTypes.Type.ViewAndPost:
return qsTr("Members who meet the requirements will be allowed to read and write in the selected channels") return qsTr("Members who meet the requirements will be allowed to read and write in the selected channels")
case PermissionTypes.Type.Read: case PermissionTypes.Type.Read:
@ -70,8 +72,8 @@ QtObject {
} }
function isCommunityPermission(permissionType) { function isCommunityPermission(permissionType) {
return permissionType === PermissionTypes.Type.Admin return permissionType === PermissionTypes.Type.Admin || permissionType === PermissionTypes.Type.Member ||
|| permissionType === PermissionTypes.Type.Member permissionType === PermissionTypes.Type.TokenMaster || permissionType === PermissionTypes.Type.Owner
} }
function getPermissionsCountLimit(permissionType) { function getPermissionsCountLimit(permissionType) {

View File

@ -482,8 +482,6 @@ Rectangle {
return qsTr("View only") return qsTr("View only")
case PermissionTypes.Type.ViewAndPost: case PermissionTypes.Type.ViewAndPost:
return qsTr("View & post") return qsTr("View & post")
case PermissionTypes.Type.Moderator:
return qsTr("Moderate")
default: default:
return "???" return "???"
} }

View File

@ -41,7 +41,8 @@ Item {
readonly property bool isSectionAdmin: readonly property bool isSectionAdmin:
communityData.memberRole === Constants.memberRole.owner || communityData.memberRole === Constants.memberRole.owner ||
communityData.memberRole === Constants.memberRole.admin communityData.memberRole === Constants.memberRole.admin ||
communityData.memberRole === Constants.memberRole.tokenMaster
signal infoButtonClicked signal infoButtonClicked
signal manageButtonClicked signal manageButtonClicked

View File

@ -38,7 +38,7 @@ StatusSectionLayout {
required property var walletAccountsModel // name, address, emoji, color required property var walletAccountsModel // name, address, emoji, color
readonly property bool isOwner: community.memberRole === Constants.memberRole.owner readonly property bool isOwner: community.memberRole === Constants.memberRole.owner
readonly property bool isAdmin: isOwner || community.memberRole === Constants.memberRole.admin readonly property bool isAdmin: community.memberRole === Constants.memberRole.admin
readonly property bool isTokenMasterOwner: community.memberRole === Constants.memberRole.tokenMaster readonly property bool isTokenMasterOwner: community.memberRole === Constants.memberRole.tokenMaster
readonly property bool isControlNode: community.isControlNode readonly property bool isControlNode: community.isControlNode
@ -248,7 +248,7 @@ StatusSectionLayout {
bannedMembersModel: root.community.bannedMembers bannedMembersModel: root.community.bannedMembers
pendingMemberRequestsModel: root.community.pendingMemberRequests pendingMemberRequestsModel: root.community.pendingMemberRequests
declinedMemberRequestsModel: root.community.declinedMemberRequests declinedMemberRequestsModel: root.community.declinedMemberRequests
editable: root.isAdmin editable: root.isAdmin || root.isOwner || root.isTokenMasterOwner
memberRole: community.memberRole memberRole: community.memberRole
communityName: root.community.name communityName: root.community.name
@ -304,7 +304,7 @@ StatusSectionLayout {
readonly property int sectionKey: Constants.CommunitySettingsSections.MintTokens readonly property int sectionKey: Constants.CommunitySettingsSections.MintTokens
readonly property string sectionName: qsTr("Tokens") readonly property string sectionName: qsTr("Tokens")
readonly property string sectionIcon: "token" readonly property string sectionIcon: "token"
readonly property bool sectionEnabled: root.isOwner readonly property bool sectionEnabled: true
readonly property CommunityTokensStore communityTokensStore: readonly property CommunityTokensStore communityTokensStore:
rootStore.communityTokensStore rootStore.communityTokensStore
@ -418,13 +418,13 @@ StatusSectionLayout {
readonly property int sectionKey: Constants.CommunitySettingsSections.Airdrops readonly property int sectionKey: Constants.CommunitySettingsSections.Airdrops
readonly property string sectionName: qsTr("Airdrops") readonly property string sectionName: qsTr("Airdrops")
readonly property string sectionIcon: "airdrop" readonly property string sectionIcon: "airdrop"
readonly property bool sectionEnabled: root.isOwner readonly property bool sectionEnabled: true
communityDetails: d.communityDetails communityDetails: d.communityDetails
// Profile type // Profile type
isOwner: root.isOwner isOwner: root.isOwner
isTokenMasterOwner: false // TODO: Backend isTokenMasterOwner: root.isTokenMasterOwner
isAdmin: root.isAdmin isAdmin: root.isAdmin
// Owner and TMaster properties // Owner and TMaster properties
@ -540,6 +540,7 @@ StatusSectionLayout {
readonly property string color: root.community.color readonly property string color: root.community.color
readonly property bool owner: root.community.memberRole === Constants.memberRole.owner readonly property bool owner: root.community.memberRole === Constants.memberRole.owner
readonly property bool admin: root.community.memberRole === Constants.memberRole.admin readonly property bool admin: root.community.memberRole === Constants.memberRole.admin
readonly property bool tokenMaster: root.community.memberRole === Constants.memberRole.tokenMaster
} }
function goTo(section: int, subSection: int) { function goTo(section: int, subSection: int) {

View File

@ -98,7 +98,10 @@ StatusScrollView {
? channelsSelectionModel : communityItemModel ? channelsSelectionModel : communityItemModel
isPrivate: model.isPrivate isPrivate: model.isPrivate
showButtons: root.communityDetails.owner || (root.communityDetails.admin && model.permissionType !== PermissionTypes.Type.Admin) showButtons: (model.permissionType !== PermissionTypes.Type.TokenMaster &&
model.permissionType !== PermissionTypes.Type.Owner) &&
(root.communityDetails.owner ||
((root.communityDetails.admin || root.communityDetails.tokenMaster) && model.permissionType !== PermissionTypes.Type.Admin))
onEditClicked: root.editPermissionRequested(model.index) onEditClicked: root.editPermissionRequested(model.index)
onDuplicateClicked: root.duplicatePermissionRequested(model.index) onDuplicateClicked: root.duplicatePermissionRequested(model.index)

View File

@ -5,7 +5,8 @@ import utils 1.0
ShowcaseDelegate { ShowcaseDelegate {
title: !!showcaseObj && !!showcaseObj.name ? showcaseObj.name : "" title: !!showcaseObj && !!showcaseObj.name ? showcaseObj.name : ""
secondaryTitle: !!showcaseObj && (showcaseObj.memberRole === Constants.memberRole.owner || secondaryTitle: !!showcaseObj && (showcaseObj.memberRole === Constants.memberRole.owner ||
showcaseObj.memberRole === Constants.memberRole.admin) ? qsTr("Admin") : qsTr("Member") showcaseObj.memberRole === Constants.memberRole.admin ||
showcaseObj.memberRole === Constants.memberRole.tokenMaster) ? qsTr("Admin") : qsTr("Member")
hasImage: !!showcaseObj && !!showcaseObj.image hasImage: !!showcaseObj && !!showcaseObj.image
icon.name: !!showcaseObj ? showcaseObj.name : "" icon.name: !!showcaseObj ? showcaseObj.name : ""

View File

@ -113,7 +113,8 @@ Control {
components: [ components: [
StatusIcon { StatusIcon {
visible: model.memberRole === Constants.memberRole.owner || visible: model.memberRole === Constants.memberRole.owner ||
model.memberRole === Constants.memberRole.admin model.memberRole === Constants.memberRole.admin ||
model.memberRole === Constants.memberRole.tokenMaster
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
icon: "crown" icon: "crown"
color: Theme.palette.directColor1 color: Theme.palette.directColor1

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 524c21834b7249da97c1c3bc712763a1d37b786d Subproject commit 86d969727f7b5ff79f39e2246272cbf858cc752e