feat(@desktop/chat): Add requests sections to members tab of the community management

Add tabs: "Pending requests", "Rejected"
Add getting declined requests from status-go

Issue #6279
This commit is contained in:
Michal Iskierko 2022-08-04 09:49:41 +02:00 committed by Michał Iskierko
parent 7ef4a2d257
commit 346af7c245
12 changed files with 266 additions and 62 deletions

View File

@ -73,6 +73,19 @@ method viewDidLoad*(self: Module) =
self.delegate.communitiesModuleDidLoad() self.delegate.communitiesModuleDidLoad()
proc createMemberItem(self: Module, memberId, requestId: string): MemberItem =
let contactDetails = self.controller.getContactDetails(memberId)
result = initMemberItem(
pubKey = memberId,
displayName = contactDetails.displayName,
ensName = contactDetails.details.name,
localNickname = contactDetails.details.localNickname,
alias = contactDetails.details.alias,
icon = contactDetails.icon,
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(memberId).statusType),
isContact = contactDetails.details.isContact,
requestToJoinId = requestId)
method getCommunityItem(self: Module, c: CommunityDto): SectionItem = method getCommunityItem(self: Module, c: CommunityDto): SectionItem =
return initItem( return initItem(
c.id, c.id,
@ -100,31 +113,14 @@ method getCommunityItem(self: Module, c: CommunityDto): SectionItem =
c.permissions.ensOnly, c.permissions.ensOnly,
c.muted, c.muted,
c.members.map(proc(member: Member): MemberItem = c.members.map(proc(member: Member): MemberItem =
let contactDetails = self.controller.getContactDetails(member.id) result = self.createMemberItem(member.id, "")),
result = initMemberItem(
pubKey = member.id,
displayName = contactDetails.displayName,
ensName = contactDetails.details.name,
localNickname = contactDetails.details.localNickname,
alias = contactDetails.details.alias,
icon = contactDetails.icon,
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(member.id).statusType),
isContact = contactDetails.details.isContact,
)),
historyArchiveSupportEnabled = c.settings.historyArchiveSupportEnabled, historyArchiveSupportEnabled = c.settings.historyArchiveSupportEnabled,
bannedMembers = c.bannedMembersIds.map(proc(bannedMemberId: string): MemberItem = bannedMembers = c.bannedMembersIds.map(proc(bannedMemberId: string): MemberItem =
let contactDetails = self.controller.getContactDetails(bannedMemberId) result = self.createMemberItem(bannedMemberId, "")),
result = initMemberItem( pendingMemberRequests = c.pendingRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
pubKey = bannedMemberId, result = self.createMemberItem(requestDto.publicKey, requestDto.id)),
displayName = contactDetails.displayName, declinedMemberRequests = c.declinedRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
ensName = contactDetails.details.name, result = self.createMemberItem(requestDto.publicKey, requestDto.id)),
localNickname = contactDetails.details.localNickname,
alias = contactDetails.details.alias,
icon = contactDetails.icon,
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(bannedMemberId).statusType),
isContact = contactDetails.details.added, # FIXME
)
),
) )
method getCuratedCommunityItem(self: Module, c: CuratedCommunity): CuratedCommunityItem = method getCuratedCommunityItem(self: Module, c: CuratedCommunity): CuratedCommunityItem =

View File

@ -259,13 +259,40 @@ proc createChannelGroupItem[T](self: Module[T], c: ChannelGroupDto): SectionItem
alias = contactDetails.details.alias, alias = contactDetails.details.alias,
icon = contactDetails.icon, icon = contactDetails.icon,
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(bannedMemberId).statusType), onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(bannedMemberId).statusType),
isContact = contactDetails.details.added # FIXME isContact = contactDetails.details.isContact
) )
) ),
if (isCommunity): communityDetails.pendingRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
let contactDetails = self.controller.getContactDetails(requestDto.publicKey)
result = initMemberItem(
pubKey = requestDto.publicKey,
displayName = contactDetails.displayName,
ensName = contactDetails.details.name,
localNickname = contactDetails.details.localNickname,
alias = contactDetails.details.alias,
icon = contactDetails.icon,
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(requestDto.publicKey).statusType),
isContact = contactDetails.details.isContact,
requestToJoinId = requestDto.id
)
) else: @[],
if (isCommunity): communityDetails.declinedRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
let contactDetails = self.controller.getContactDetails(requestDto.publicKey)
result = initMemberItem(
pubKey = requestDto.publicKey,
displayName = contactDetails.displayName,
ensName = contactDetails.details.name,
localNickname = contactDetails.details.localNickname,
alias = contactDetails.details.alias,
icon = contactDetails.icon,
onlineStatus = toOnlineStatus(self.controller.getStatusForContactWithId(requestDto.publicKey).statusType),
isContact = contactDetails.details.isContact,
requestToJoinId = requestDto.id
)
) else: @[]
) )
method load*[T]( method load*[T](
self: Module[T], self: Module[T],
events: EventEmitter, events: EventEmitter,

View File

@ -19,11 +19,15 @@ QtObject:
proc membersChanged*(self: ActiveSection) {.signal.} proc membersChanged*(self: ActiveSection) {.signal.}
proc bannedMembersChanged*(self: ActiveSection) {.signal.} proc bannedMembersChanged*(self: ActiveSection) {.signal.}
proc pendingRequestsToJoinChanged*(self: ActiveSection) {.signal.} proc pendingRequestsToJoinChanged*(self: ActiveSection) {.signal.}
proc pendingMemberRequestsChanged*(self: ActiveSection) {.signal.}
proc declinedMemberRequestsChanged*(self: ActiveSection) {.signal.}
proc setActiveSectionData*(self: ActiveSection, item: SectionItem) = proc setActiveSectionData*(self: ActiveSection, item: SectionItem) =
self.item = item self.item = item
self.membersChanged() self.membersChanged()
self.bannedMembersChanged() self.bannedMembersChanged()
self.pendingMemberRequestsChanged()
self.declinedMemberRequestsChanged()
self.pendingRequestsToJoinChanged() self.pendingRequestsToJoinChanged()
proc getId*(self: ActiveSection): string {.slot.} = proc getId*(self: ActiveSection): string {.slot.} =
@ -185,6 +189,27 @@ QtObject:
read = bannedMembers read = bannedMembers
notify = bannedMembersChanged notify = bannedMembersChanged
proc pendingMemberRequests(self: ActiveSection): QVariant {.slot.} =
if (self.item.id == ""):
# FIXME (Jo) I don't know why but the Item is sometimes empty and doing anything here crashes the app
return newQVariant("")
return newQVariant(self.item.pendingMemberRequests)
QtProperty[QVariant] pendingMemberRequests:
read = pendingMemberRequests
notify = pendingMemberRequestsChanged
proc declinedMemberRequests(self: ActiveSection): QVariant {.slot.} =
if (self.item.id == ""):
# FIXME (Jo) I don't know why but the Item is sometimes empty and doing anything here crashes the app
return newQVariant("")
return newQVariant(self.item.declinedMemberRequests)
QtProperty[QVariant] declinedMemberRequests:
read = declinedMemberRequests
notify = declinedMemberRequestsChanged
proc hasMember(self: ActiveSection, pubkey: string): bool {.slot.} = proc hasMember(self: ActiveSection, pubkey: string): bool {.slot.} =
return self.item.hasMember(pubkey) return self.item.hasMember(pubkey)

View File

@ -7,6 +7,7 @@ type
MemberItem* = ref object of UserItem MemberItem* = ref object of UserItem
isAdmin: bool isAdmin: bool
joined: bool joined: bool
requestToJoinId: string
# FIXME: remove defaults # FIXME: remove defaults
proc initMemberItem*( proc initMemberItem*(
@ -28,10 +29,12 @@ proc initMemberItem*(
outgoingVerificationStatus: VerificationRequestStatus = VerificationRequestStatus.None, outgoingVerificationStatus: VerificationRequestStatus = VerificationRequestStatus.None,
isAdmin: bool = false, isAdmin: bool = false,
joined: bool = false, joined: bool = false,
requestToJoinId: string = "",
): MemberItem = ): MemberItem =
result = MemberItem() result = MemberItem()
result.isAdmin = isAdmin result.isAdmin = isAdmin
result.joined = joined result.joined = joined
result.requestToJoinId = requestToJoinId
result.UserItem.setup( result.UserItem.setup(
pubKey = pubKey, pubKey = pubKey,
displayName = displayName, displayName = displayName,
@ -70,7 +73,8 @@ proc `$`*(self: MemberItem): string =
incomingVerificationStatus: {$self.incomingVerificationStatus.int}, incomingVerificationStatus: {$self.incomingVerificationStatus.int},
outgoingVerificationStatus: {$self.outgoingVerificationStatus.int}, outgoingVerificationStatus: {$self.outgoingVerificationStatus.int},
isAdmin: {self.isAdmin}, isAdmin: {self.isAdmin},
joined: {self.joined} joined: {self.joined},
requestToJoinId: {self.requestToJoinId}
]""" ]"""
proc isAdmin*(self: MemberItem): bool {.inline.} = proc isAdmin*(self: MemberItem): bool {.inline.} =
@ -84,3 +88,9 @@ proc joined*(self: MemberItem): bool {.inline.} =
proc `joined=`*(self: MemberItem, value: bool) {.inline.} = proc `joined=`*(self: MemberItem, value: bool) {.inline.} =
self.joined = value self.joined = value
proc requestToJoinId*(self: MemberItem): string {.inline.} =
self.requestToJoinId
proc `requestToJoinId=`*(self: MemberItem, value: string) {.inline.} =
self.requestToJoinId = value

View File

@ -25,6 +25,7 @@ type
OutgoingVerificationStatus OutgoingVerificationStatus
IsAdmin IsAdmin
Joined Joined
RequestToJoinId
QtObject: QtObject:
type type
@ -86,6 +87,7 @@ QtObject:
ModelRole.OutgoingVerificationStatus.int: "outgoingVerificationStatus", ModelRole.OutgoingVerificationStatus.int: "outgoingVerificationStatus",
ModelRole.IsAdmin.int: "isAdmin", ModelRole.IsAdmin.int: "isAdmin",
ModelRole.Joined.int: "joined", ModelRole.Joined.int: "joined",
ModelRole.RequestToJoinId.int: "requestToJoinId",
}.toTable }.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant = method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -135,6 +137,8 @@ QtObject:
result = newQVariant(item.isAdmin) result = newQVariant(item.isAdmin)
of ModelRole.Joined: of ModelRole.Joined:
result = newQVariant(item.joined) result = newQVariant(item.joined)
of ModelRole.RequestToJoinId:
result = newQVariant(item.requestToJoinId)
proc addItem*(self: Model, item: MemberItem) = proc addItem*(self: Model, item: MemberItem) =
# we need to maintain online contact on top, that means # we need to maintain online contact on top, that means

View File

@ -43,6 +43,8 @@ type
historyArchiveSupportEnabled: bool historyArchiveSupportEnabled: bool
pinMessageAllMembersEnabled: bool pinMessageAllMembersEnabled: bool
bannedMembersModel: member_model.Model bannedMembersModel: member_model.Model
pendingMemberRequestsModel: member_model.Model
declinedMemberRequestsModel: member_model.Model
proc initItem*( proc initItem*(
id: string, id: string,
@ -74,6 +76,8 @@ proc initItem*(
historyArchiveSupportEnabled = false, historyArchiveSupportEnabled = false,
pinMessageAllMembersEnabled = false, pinMessageAllMembersEnabled = false,
bannedMembers: seq[MemberItem] = @[], bannedMembers: seq[MemberItem] = @[],
pendingMemberRequests: seq[MemberItem] = @[],
declinedMemberRequests: seq[MemberItem] = @[],
): SectionItem = ): SectionItem =
result.id = id result.id = id
result.sectionType = sectionType result.sectionType = sectionType
@ -107,6 +111,10 @@ proc initItem*(
result.pinMessageAllMembersEnabled = pinMessageAllMembersEnabled result.pinMessageAllMembersEnabled = pinMessageAllMembersEnabled
result.bannedMembersModel = newModel() result.bannedMembersModel = newModel()
result.bannedMembersModel.setItems(bannedMembers) result.bannedMembersModel.setItems(bannedMembers)
result.pendingMemberRequestsModel = newModel()
result.pendingMemberRequestsModel.setItems(pendingMemberRequests)
result.declinedMemberRequestsModel = newModel()
result.declinedMemberRequestsModel.setItems(declinedMemberRequests)
proc isEmpty*(self: SectionItem): bool = proc isEmpty*(self: SectionItem): bool =
return self.id.len == 0 return self.id.len == 0
@ -141,6 +149,8 @@ proc `$`*(self: SectionItem): string =
historyArchiveSupportEnabled:{self.historyArchiveSupportEnabled}, historyArchiveSupportEnabled:{self.historyArchiveSupportEnabled},
pinMessageAllMembersEnabled:{self.pinMessageAllMembersEnabled}, pinMessageAllMembersEnabled:{self.pinMessageAllMembersEnabled},
bannedMembers:{self.bannedMembersModel}, bannedMembers:{self.bannedMembersModel},
pendingMemberRequests:{self.pendingMemberRequestsModel},
declinedMemberRequests:{self.declinedMemberRequestsModel},
]""" ]"""
proc id*(self: SectionItem): string {.inline.} = proc id*(self: SectionItem): string {.inline.} =
@ -256,6 +266,12 @@ proc updateMember*(
proc bannedMembers*(self: SectionItem): member_model.Model {.inline.} = proc bannedMembers*(self: SectionItem): member_model.Model {.inline.} =
self.bannedMembersModel self.bannedMembersModel
proc pendingMemberRequests*(self: SectionItem): member_model.Model {.inline.} =
self.pendingMemberRequestsModel
proc declinedMemberRequests*(self: SectionItem): member_model.Model {.inline.} =
self.declinedMemberRequestsModel
proc pendingRequestsToJoin*(self: SectionItem): PendingRequestModel {.inline.} = proc pendingRequestsToJoin*(self: SectionItem): PendingRequestModel {.inline.} =
self.pendingRequestsToJoinModel self.pendingRequestsToJoinModel

View File

@ -7,6 +7,11 @@ include ../../../common/json_utils
import ../../chat/dto/chat import ../../chat/dto/chat
type RequestToJoinType* {.pure.}= enum
Pending = 0,
Declined = 1,
Accepted = 2
type Member* = object type Member* = object
id*: string id*: string
roles*: seq[int] roles*: seq[int]
@ -64,6 +69,7 @@ type CommunityDto* = object
settings*: CommunitySettingsDto settings*: CommunitySettingsDto
adminSettings*: CommunityAdminSettingsDto adminSettings*: CommunityAdminSettingsDto
bannedMembersIds*: seq[string] bannedMembersIds*: seq[string]
declinedRequestsToJoin*: seq[CommunityMembershipRequestDto]
type CuratedCommunity* = object type CuratedCommunity* = object
available*: bool available*: bool

View File

@ -122,6 +122,7 @@ QtObject:
proc handleCommunityUpdates(self: Service, communities: seq[CommunityDto], updatedChats: seq[ChatDto]) proc handleCommunityUpdates(self: Service, communities: seq[CommunityDto], updatedChats: seq[ChatDto])
proc handleCommunitiesSettingsUpdates(self: Service, communitiesSettings: seq[CommunitySettingsDto]) proc handleCommunitiesSettingsUpdates(self: Service, communitiesSettings: seq[CommunitySettingsDto])
proc pendingRequestsToJoinForCommunity*(self: Service, communityId: string): seq[CommunityMembershipRequestDto] proc pendingRequestsToJoinForCommunity*(self: Service, communityId: string): seq[CommunityMembershipRequestDto]
proc declinedRequestsToJoinForCommunity*(self: Service, communityId: string): seq[CommunityMembershipRequestDto]
proc delete*(self: Service) = proc delete*(self: Service) =
discard discard
@ -210,6 +211,7 @@ QtObject:
# Community data we get from the signals and responses don't contgain the pending requests # Community data we get from the signals and responses don't contgain the pending requests
# therefore, we must keep the old one # therefore, we must keep the old one
community.pendingRequestsToJoin = self.joinedCommunities[community.id].pendingRequestsToJoin community.pendingRequestsToJoin = self.joinedCommunities[community.id].pendingRequestsToJoin
community.declinedRequestsToJoin = self.joinedCommunities[community.id].declinedRequestsToJoin
# Update the joinded community list with the new data # Update the joinded community list with the new data
self.joinedCommunities[community.id] = community self.joinedCommunities[community.id] = community
@ -343,6 +345,7 @@ QtObject:
self.joinedCommunities[community.id] = community self.joinedCommunities[community.id] = community
if (community.admin): if (community.admin):
self.joinedCommunities[community.id].pendingRequestsToJoin = self.pendingRequestsToJoinForCommunity(community.id) self.joinedCommunities[community.id].pendingRequestsToJoin = self.pendingRequestsToJoinForCommunity(community.id)
self.joinedCommunities[community.id].declinedRequestsToJoin = self.declinedRequestsToJoinForCommunity(community.id)
let allCommunities = self.loadAllCommunities() let allCommunities = self.loadAllCommunities()
for community in allCommunities: for community in allCommunities:
@ -579,6 +582,17 @@ QtObject:
except Exception as e: except Exception as e:
error "Error fetching community requests", msg = e.msg error "Error fetching community requests", msg = e.msg
proc declinedRequestsToJoinForCommunity*(self: Service, communityId: string): seq[CommunityMembershipRequestDto] =
try:
let response = status_go.declinedRequestsToJoinForCommunity(communityId)
result = @[]
if response.result.kind != JNull:
for jsonCommunityReqest in response.result:
result.add(jsonCommunityReqest.toCommunityMembershipRequestDto())
except Exception as e:
error "Error fetching community declined requests", msg = e.msg
proc leaveCommunity*(self: Service, communityId: string) = proc leaveCommunity*(self: Service, communityId: string) =
try: try:
let response = status_go.leaveCommunity(communityId) let response = status_go.leaveCommunity(communityId)
@ -1026,7 +1040,7 @@ QtObject:
except Exception as e: except Exception as e:
error "Error exporting community", msg = e.msg error "Error exporting community", msg = e.msg
proc getPendingRequestIndex*(self: Service, communityId: string, requestId: string): int = proc getPendingRequestIndex(self: Service, communityId: string, requestId: string): int =
let community = self.joinedCommunities[communityId] let community = self.joinedCommunities[communityId]
var i = 0 var i = 0
for pendingRequest in community.pendingRequestsToJoin: for pendingRequest in community.pendingRequestsToJoin:
@ -1035,15 +1049,43 @@ QtObject:
i.inc() i.inc()
return -1 return -1
proc removeMembershipRequestFromCommunityAndGetMemberPubkey*(self: Service, communityId: string, requestId: string): string = proc getDeclinedRequestIndex(self: Service, communityId: string, requestId: string): int =
let index = self.getPendingRequestIndex(communityId, requestId) let community = self.joinedCommunities[communityId]
var i = 0
for declinedRequest in community.declinedRequestsToJoin:
if (declinedRequest.id == requestId):
return i
i.inc()
return -1
if (index == -1): proc removeMembershipRequestFromCommunityAndGetMemberPubkey*(self: Service, communityId: string, requestId: string): string =
let indexPending = self.getPendingRequestIndex(communityId, requestId)
let indexDeclined = self.getDeclinedRequestIndex(communityId, requestId)
if (indexPending == -1 and indexDeclined == -1):
raise newException(RpcException, fmt"Community request not found: {requestId}") raise newException(RpcException, fmt"Community request not found: {requestId}")
var community = self.joinedCommunities[communityId] var community = self.joinedCommunities[communityId]
result = community.pendingRequestsToJoin[index].publicKey
community.pendingRequestsToJoin.delete(index) if (indexPending != -1):
result = community.pendingRequestsToJoin[indexPending].publicKey
community.pendingRequestsToJoin.delete(indexPending)
elif (indexDeclined != -1):
result = community.declinedRequestsToJoin[indexDeclined].publicKey
community.declinedRequestsToJoin.delete(indexDeclined)
self.joinedCommunities[communityId] = community
proc moveRequestToDeclined*(self: Service, communityId: string, requestId: string) =
let indexPending = self.getPendingRequestIndex(communityId, requestId)
if (indexPending == -1):
raise newException(RpcException, fmt"Community request not found: {requestId}")
var community = self.joinedCommunities[communityId]
if (indexPending != -1):
let itemToMove = community.pendingRequestsToJoin[indexPending]
community.declinedRequestsToJoin.add(itemToMove)
community.pendingRequestsToJoin.delete(indexPending)
self.joinedCommunities[communityId] = community self.joinedCommunities[communityId] = community
@ -1065,7 +1107,7 @@ QtObject:
try: try:
discard status_go.declineRequestToJoinCommunity(requestId) discard status_go.declineRequestToJoinCommunity(requestId)
discard self.removeMembershipRequestFromCommunityAndGetMemberPubkey(communityId, requestId) self.moveRequestToDeclined(communityId, requestId)
self.events.emit(SIGNAL_COMMUNITY_EDITED, CommunityArgs(community: self.joinedCommunities[communityId])) self.events.emit(SIGNAL_COMMUNITY_EDITED, CommunityArgs(community: self.joinedCommunities[communityId]))
except Exception as e: except Exception as e:

View File

@ -43,6 +43,9 @@ proc myPendingRequestsToJoin*(): RpcResponse[JsonNode] {.raises: [Exception].} =
proc pendingRequestsToJoinForCommunity*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} = proc pendingRequestsToJoinForCommunity*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("pendingRequestsToJoinForCommunity".prefix, %*[communityId]) result = callPrivateRPC("pendingRequestsToJoinForCommunity".prefix, %*[communityId])
proc declinedRequestsToJoinForCommunity*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("declinedRequestsToJoinForCommunity".prefix, %*[communityId])
proc leaveCommunity*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} = proc leaveCommunity*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("leaveCommunity".prefix, %*[communityId]) result = callPrivateRPC("leaveCommunity".prefix, %*[communityId])

View File

@ -18,16 +18,19 @@ SettingsPageLayout {
property var membersModel property var membersModel
property var bannedMembersModel property var bannedMembersModel
property var pendingMemberRequestsModel
property var declinedMemberRequestsModel
property string communityName property string communityName
property bool editable: true property bool editable: true
property int pendingRequests
signal membershipRequestsClicked() signal membershipRequestsClicked()
signal userProfileClicked(string id) signal userProfileClicked(string id)
signal kickUserClicked(string id) signal kickUserClicked(string id)
signal banUserClicked(string id) signal banUserClicked(string id)
signal unbanUserClicked(string id) signal unbanUserClicked(string id)
signal acceptRequestToJoin(string id)
signal declineRequestToJoin(string id)
title: qsTr("Members") title: qsTr("Members")
@ -45,21 +48,19 @@ SettingsPageLayout {
text: qsTr("All Members") text: qsTr("All Members")
} }
// TODO will be added in next phase StatusTabButton {
// StatusTabButton { id: pendingRequestsBtn
// id: pendingRequestsBtn width: implicitWidth
// width: implicitWidth text: qsTr("Pending Requests")
// text: qsTr("Pending Requests") enabled: pendingMemberRequestsModel.count > 0
// enabled: false }
// }
// Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections. StatusTabButton {
// StatusTabButton { id: declinedRequestsBtn
// id: rejectedRequestsBtn width: implicitWidth
// width: implicitWidth text: qsTr("Rejected")
// enabled: root.contactsStore.receivedButRejectedContactRequestsModel.count > 0 || enabled: declinedMemberRequestsModel.count > 0
// root.contactsStore.sentButRejectedContactRequestsModel.count > 0 }
// btnText: qsTr("Rejected Requests")
// }
StatusTabButton { StatusTabButton {
id: bannedBtn id: bannedBtn
@ -105,6 +106,45 @@ SettingsPageLayout {
} }
} }
CommunityMembersTabPanel {
model: root.pendingMemberRequestsModel
placeholderText: {
if (root.pendingMemberRequestsModel.count === 0) {
return qsTr("No pending requests to search")
} else {
return qsTr("Search %1's %2 pending request%3").arg(root.communityName)
.arg(root.pendingMemberRequestsModel.count)
.arg(root.pendingMemberRequestsModel.count > 1 ? "s" : "")
}
}
panelType: CommunityMembersTabPanel.TabType.PendingRequests
Layout.fillWidth: true
Layout.fillHeight: true
onAcceptRequestToJoin: root.acceptRequestToJoin(id)
onDeclineRequestToJoin: root.declineRequestToJoin(id)
}
CommunityMembersTabPanel {
model: root.declinedMemberRequestsModel
placeholderText: {
if (root.declinedMemberRequestsModel.count === 0) {
return qsTr("No rejected members to search")
} else {
return qsTr("Search %1's %2 rejected member%3").arg(root.communityName)
.arg(root.declinedMemberRequestsModel.count)
.arg(root.declinedMemberRequestsModel.count > 1 ? "s" : "")
}
}
panelType: CommunityMembersTabPanel.TabType.DeclinedRequests
Layout.fillWidth: true
Layout.fillHeight: true
onAcceptRequestToJoin: root.acceptRequestToJoin(id)
}
CommunityMembersTabPanel { CommunityMembersTabPanel {
model: root.bannedMembersModel model: root.bannedMembersModel
placeholderText: { placeholderText: {

View File

@ -24,9 +24,14 @@ Item {
signal banUserClicked(string id, string name) signal banUserClicked(string id, string name)
signal unbanUserClicked(string id) signal unbanUserClicked(string id)
signal acceptRequestToJoin(string id)
signal declineRequestToJoin(string id)
enum TabType { enum TabType {
AllMembers, AllMembers,
BannedMembers BannedMembers,
PendingRequests,
DeclinedRequests
} }
property int panelType: CommunityMembersTabPanel.TabType.AllMembers property int panelType: CommunityMembersTabPanel.TabType.AllMembers
@ -62,16 +67,18 @@ Item {
id: memberItem id: memberItem
readonly property bool itsMe: model.pubKey.toLowerCase() === userProfile.pubKey.toLowerCase() readonly property bool itsMe: model.pubKey.toLowerCase() === userProfile.pubKey.toLowerCase()
readonly property bool showButton: !memberItem.itsMe && !model.isAdmin readonly property bool isHovered: memberItem.sensor.containsMouse
&& memberItem.sensor.containsMouse readonly property bool canBeBanned: !memberItem.itsMe && !model.isAdmin
statusListItemComponentsSlot.spacing: 16 statusListItemComponentsSlot.spacing: 16
rightPadding: 80 statusListItemTitleArea.anchors.rightMargin: 0
statusListItemSubTitle.elide: Text.ElideRight
rightPadding: 75
leftPadding: 12 leftPadding: 12
components: [ components: [
StatusButton { StatusButton {
visible: (root.panelType === CommunityMembersTabPanel.TabType.AllMembers) && showButton visible: (root.panelType === CommunityMembersTabPanel.TabType.AllMembers) && isHovered && canBeBanned
text: qsTr("Kick") text: qsTr("Kick")
type: StatusBaseButton.Type.Danger type: StatusBaseButton.Type.Danger
size: StatusBaseButton.Size.Small size: StatusBaseButton.Size.Small
@ -79,7 +86,7 @@ Item {
}, },
StatusButton { StatusButton {
visible: (root.panelType === CommunityMembersTabPanel.TabType.AllMembers) && showButton visible: (root.panelType === CommunityMembersTabPanel.TabType.AllMembers) && isHovered && canBeBanned
text: qsTr("Ban") text: qsTr("Ban")
type: StatusBaseButton.Type.Danger type: StatusBaseButton.Type.Danger
size: StatusBaseButton.Size.Small size: StatusBaseButton.Size.Small
@ -87,12 +94,40 @@ Item {
}, },
StatusButton { StatusButton {
visible: (root.panelType === CommunityMembersTabPanel.TabType.BannedMembers) && showButton visible: (root.panelType === CommunityMembersTabPanel.TabType.BannedMembers) && isHovered && canBeBanned
text: qsTr("Unban") text: qsTr("Unban")
type: StatusBaseButton.Type.Normal type: StatusBaseButton.Type.Normal
size: StatusBaseButton.Size.Small size: StatusBaseButton.Size.Large
onClicked: root.unbanUserClicked(model.pubKey) onClicked: root.unbanUserClicked(model.pubKey)
width: 95 width: 95
height: 44
},
StatusButton {
visible: (root.panelType === CommunityMembersTabPanel.TabType.PendingRequests ||
root.panelType === CommunityMembersTabPanel.TabType.DeclinedRequests) && isHovered
text: qsTr("Accept")
type: StatusBaseButton.Type.Normal
size: StatusBaseButton.Size.Large
icon.name: "checkmark-circle"
icon.color: Theme.palette.successColor1
normalColor: Theme.palette.successColor2
hoverColor: Theme.palette.successColor3
textColor: Theme.palette.successColor1
onClicked: root.acceptRequestToJoin(model.requestToJoinId)
width: 124
height: 44
},
StatusButton {
visible: (root.panelType === CommunityMembersTabPanel.TabType.PendingRequests) && isHovered
text: qsTr("Reject")
type: StatusBaseButton.Type.Danger
icon.name: "close-circle"
icon.color: Style.current.danger
onClicked: root.declineRequestToJoin(model.requestToJoinId)
width: 118
height: 44
} }
] ]

View File

@ -185,17 +185,17 @@ StatusAppTwoPanelLayout {
CommunityMembersSettingsPanel { CommunityMembersSettingsPanel {
membersModel: root.community.members membersModel: root.community.members
bannedMembersModel: root.community.bannedMembers bannedMembersModel: root.community.bannedMembers
pendingMemberRequestsModel: root.community.pendingMemberRequests
declinedMemberRequestsModel: root.community.declinedMemberRequests
editable: root.community.amISectionAdmin editable: root.community.amISectionAdmin
pendingRequests: root.community.pendingRequestsToJoin ? root.community.pendingRequestsToJoin.count : 0
communityName: root.community.name communityName: root.community.name
onUserProfileClicked: Global.openProfilePopup(id) onUserProfileClicked: Global.openProfilePopup(id)
onKickUserClicked: root.rootStore.removeUserFromCommunity(id) onKickUserClicked: root.rootStore.removeUserFromCommunity(id)
onBanUserClicked: root.rootStore.banUserFromCommunity(id) onBanUserClicked: root.rootStore.banUserFromCommunity(id)
onUnbanUserClicked: root.rootStore.unbanUserFromCommunity(id) onUnbanUserClicked: root.rootStore.unbanUserFromCommunity(id)
onMembershipRequestsClicked: Global.openPopup(root.membershipRequestPopup, { onAcceptRequestToJoin: root.rootStore.acceptRequestToJoinCommunity(id)
communitySectionModule: root.chatCommunitySectionModule onDeclineRequestToJoin: root.rootStore.declineRequestToJoinCommunity(id)
})
} }
CommunityPermissionsSettingsPanel {} CommunityPermissionsSettingsPanel {}