202 lines
8.5 KiB
QML
202 lines
8.5 KiB
QML
import QtQuick 2.14
|
|
import QtQuick.Layouts 1.14
|
|
import QtQuick.Controls 2.14
|
|
|
|
import StatusQ.Core 0.1
|
|
import StatusQ.Core.Theme 0.1
|
|
import StatusQ.Controls 0.1
|
|
import StatusQ.Components 0.1
|
|
import StatusQ.Popups 0.1
|
|
|
|
import utils 1.0
|
|
import shared.views.chat 1.0
|
|
import shared.controls.chat 1.0
|
|
import shared.controls 1.0
|
|
|
|
import AppLayouts.Communities.layouts 1.0
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property string placeholderText
|
|
property var model
|
|
property var rootStore
|
|
|
|
signal kickUserClicked(string id, string name)
|
|
signal banUserClicked(string id, string name)
|
|
signal unbanUserClicked(string id)
|
|
|
|
signal acceptRequestToJoin(string id)
|
|
signal declineRequestToJoin(string id)
|
|
|
|
enum TabType {
|
|
AllMembers,
|
|
BannedMembers,
|
|
PendingRequests,
|
|
DeclinedRequests
|
|
}
|
|
|
|
property int panelType: MembersTabPanel.TabType.AllMembers
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
spacing: 30
|
|
|
|
StatusInput {
|
|
id: memberSearch
|
|
Layout.preferredWidth: 400
|
|
Layout.leftMargin: 12
|
|
maximumHeight: 36
|
|
topPadding: 0
|
|
bottomPadding: 0
|
|
rightPadding: 0
|
|
placeholderText: root.placeholderText
|
|
input.asset.name: "search"
|
|
enabled: !!model && model.count > 0
|
|
}
|
|
|
|
ListView {
|
|
id: membersList
|
|
objectName: "CommunityMembersTabPanel_MembersListViews"
|
|
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
|
|
model: root.model
|
|
clip: true
|
|
spacing: 15
|
|
|
|
delegate: StatusMemberListItem {
|
|
id: memberItem
|
|
|
|
readonly property bool itsMe: model.pubKey.toLowerCase() === userProfile.pubKey.toLowerCase()
|
|
readonly property bool isHovered: memberItem.sensor.containsMouse
|
|
readonly property bool canBeBanned: !memberItem.itsMe && (model.memberRole !== Constants.memberRole.owner && model.memberRole !== Constants.memberRole.admin)
|
|
|
|
statusListItemComponentsSlot.spacing: 16
|
|
statusListItemTitleArea.anchors.rightMargin: 0
|
|
statusListItemSubTitle.elide: Text.ElideRight
|
|
rightPadding: 75
|
|
leftPadding: 12
|
|
|
|
components: [
|
|
StatusButton {
|
|
objectName: "MemberListIten_KickButton"
|
|
visible: (root.panelType === MembersTabPanel.TabType.AllMembers) && isHovered && canBeBanned
|
|
text: qsTr("Kick")
|
|
type: StatusBaseButton.Type.Danger
|
|
size: StatusBaseButton.Size.Small
|
|
onClicked: root.kickUserClicked(model.pubKey, model.displayName)
|
|
},
|
|
|
|
StatusButton {
|
|
visible: (root.panelType === MembersTabPanel.TabType.AllMembers) && isHovered && canBeBanned
|
|
text: qsTr("Ban")
|
|
type: StatusBaseButton.Type.Danger
|
|
size: StatusBaseButton.Size.Small
|
|
onClicked: root.banUserClicked(model.pubKey, model.displayName)
|
|
},
|
|
|
|
StatusButton {
|
|
visible: (root.panelType === MembersTabPanel.TabType.BannedMembers) && isHovered && canBeBanned
|
|
text: qsTr("Unban")
|
|
onClicked: root.unbanUserClicked(model.pubKey)
|
|
},
|
|
|
|
DisabledTooltipButton {
|
|
id: acceptButton
|
|
visible: ((root.panelType === MembersTabPanel.TabType.PendingRequests ||
|
|
root.panelType === MembersTabPanel.TabType.DeclinedRequests) && isHovered) ||
|
|
model.membershipRequestState === Constants.CommunityMembershipRequestState.AcceptedPending
|
|
//TODO: Only the current user can reject a pending request, so we should check that here
|
|
|
|
tooltipText: qsTr("Waiting for owner node to come online")
|
|
interactive: model.membershipRequestState !== Constants.CommunityMembershipRequestState.AcceptedPending
|
|
buttonComponent: StatusButton {
|
|
text: model.membershipRequestState == Constants.CommunityMembershipRequestState.AcceptedPending ? qsTr("Accept pending") : qsTr("Accept")
|
|
icon.name: "checkmark-circle"
|
|
icon.color: enabled ? Theme.palette.successColor1 : disabledTextColor
|
|
normalColor: Theme.palette.successColor2
|
|
hoverColor: Theme.palette.successColor3
|
|
textColor: Theme.palette.successColor1
|
|
loading: model.requestToJoinLoading
|
|
enabled: acceptButton.interactive
|
|
onClicked: root.acceptRequestToJoin(model.requestToJoinId)
|
|
}
|
|
},
|
|
|
|
DisabledTooltipButton {
|
|
id: rejectButton
|
|
//using opacity instead of visible to avoid the acceptButton jumping around
|
|
opacity: ((root.panelType === MembersTabPanel.TabType.PendingRequests) && isHovered) ||
|
|
model.membershipRequestState === Constants.CommunityMembershipRequestState.RejectedPending
|
|
//TODO: Only the current user can reject a pending request, so we should check that here
|
|
|
|
tooltipText: qsTr("Waiting for owner node to come online")
|
|
interactive: model.membershipRequestState !== Constants.CommunityMembershipRequestState.RejectedPending
|
|
buttonComponent: StatusButton {
|
|
text: model.membershipRequestState == Constants.CommunityMembershipRequestState.RejectedPending ? qsTr("Reject pending") : qsTr("Reject")
|
|
type: StatusBaseButton.Type.Danger
|
|
icon.name: "close-circle"
|
|
icon.color: enabled ? Style.current.danger : disabledTextColor
|
|
enabled: rejectButton.interactive
|
|
onClicked: root.declineRequestToJoin(model.requestToJoinId)
|
|
}
|
|
}
|
|
]
|
|
|
|
width: membersList.width
|
|
visible: memberSearch.text === "" || title.toLowerCase().includes(memberSearch.text.toLowerCase())
|
|
height: visible ? implicitHeight : 0
|
|
color: "transparent"
|
|
|
|
pubKey: model.isEnsVerified ? "" : Utils.getElidedCompressedPk(model.pubKey)
|
|
nickName: model.localNickname
|
|
userName: ProfileUtils.displayName("", model.ensName, model.displayName, model.alias)
|
|
status: model.onlineStatus
|
|
asset.color: Utils.colorForColorId(model.colorId)
|
|
asset.name: model.icon
|
|
asset.isImage: !!model.icon
|
|
asset.isLetterIdenticon: !model.icon
|
|
asset.width: 40
|
|
asset.height: 40
|
|
ringSettings.ringSpecModel: model.colorHash
|
|
statusListItemIcon.badge.visible: (root.panelType === MembersTabPanel.TabType.AllMembers)
|
|
|
|
onClicked: {
|
|
if(mouse.button === Qt.RightButton) {
|
|
Global.openMenu(memberContextMenuComponent, this, {
|
|
selectedUserPublicKey: model.pubKey,
|
|
selectedUserDisplayName: userName,
|
|
selectedUserIcon: asset.name,
|
|
})
|
|
} else {
|
|
Global.openProfilePopup(model.pubKey)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: memberContextMenuComponent
|
|
|
|
ProfileContextMenu {
|
|
id: memberContextMenuView
|
|
store: root.rootStore
|
|
myPublicKey: userProfile.pubKey
|
|
|
|
onOpenProfileClicked: {
|
|
Global.openProfilePopup(publicKey, null)
|
|
}
|
|
onCreateOneToOneChat: {
|
|
Global.changeAppSectionBySectionType(Constants.appSection.chat)
|
|
root.rootStore.chatCommunitySectionModule.createOneToOneChat(communityId, chatId, ensName)
|
|
}
|
|
onClosed: {
|
|
destroy()
|
|
}
|
|
}
|
|
}
|
|
}
|