refactor(Communities) replace `CommunityProfilePopup` with `StatusModal`
This commit refactors the `CommunityProfilePopup` to use `StatusModal`. Since it's made of various popup content components, it also updates the memberlist, the overview and the invite friends view, so it doesn't break the UI along the way. Closes: #2885, #2887, #2888
This commit is contained in:
parent
c0da840a87
commit
1a9d6d178c
|
@ -1 +1 @@
|
|||
Subproject commit 7136968b3ad50d6d222849d53c793ecf82566786
|
||||
Subproject commit 58e8f1cd23e87572d57a886e65a31a27462cfb9c
|
|
@ -272,6 +272,7 @@ Item {
|
|||
|
||||
CommunityProfilePopup {
|
||||
id: communityProfilePopup
|
||||
anchors.centerIn: parent
|
||||
communityId: chatsModel.communities.activeCommunity.id
|
||||
name: chatsModel.communities.activeCommunity.name
|
||||
description: chatsModel.communities.activeCommunity.description
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtGraphicalEffects 1.13
|
||||
import QtQuick.Controls.Universal 2.12
|
||||
import "../../../../imports"
|
||||
import "../../../../shared"
|
||||
import "../../../../shared/status"
|
||||
import "../ContactsColumn"
|
||||
|
||||
ModalPopup {
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import "../../../../imports"
|
||||
|
||||
StatusModal {
|
||||
property string communityId: chatsModel.communities.activeCommunity.id
|
||||
property string name: chatsModel.communities.activeCommunity.name
|
||||
property string description: chatsModel.communities.activeCommunity.description
|
||||
|
@ -18,136 +15,37 @@ ModalPopup {
|
|||
property string communityColor: chatsModel.communities.activeCommunity.communityColor
|
||||
property int nbMembers: chatsModel.communities.activeCommunity.nbMembers
|
||||
property bool isAdmin: chatsModel.communities.activeCommunity.isAdmin
|
||||
height: stack.currentItem.height + modalHeader.height + modalFooter.height + Style.current.padding * 3
|
||||
id: popup
|
||||
|
||||
onClosed: {
|
||||
while (stack.depth > 1) {
|
||||
stack.pop()
|
||||
while (contentComponent.depth > 1) {
|
||||
contentComponent.pop()
|
||||
}
|
||||
}
|
||||
|
||||
header: Item {
|
||||
id: modalHeader
|
||||
height: childrenRect.height
|
||||
width: parent.width
|
||||
header.title: contentComponent.currentItem.headerTitle
|
||||
header.subTitle: contentComponent.currentItem.headerSubtitle || ""
|
||||
header.image.source: contentComponent.currentItem.headerImageSource || ""
|
||||
|
||||
property string title: stack.currentItem.headerTitle
|
||||
property string description: stack.currentItem.headerDescription
|
||||
property string imageSource: stack.currentItem.headerImageSource
|
||||
property bool useLetterIdenticon: !!stack.currentItem.useLetterIdenticon
|
||||
|
||||
Loader {
|
||||
id: communityImg
|
||||
sourceComponent: !modalHeader.useLetterIdenticon ? commmunityImgCmp : letterIdenticonCmp
|
||||
active: !!modalHeader.imageSource || modalHeader.useLetterIdenticon
|
||||
}
|
||||
|
||||
Component {
|
||||
id: commmunityImgCmp
|
||||
RoundedImage {
|
||||
source: modalHeader.imageSource
|
||||
width: 40
|
||||
height: 40
|
||||
visible: !!modalHeader.imageSource
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: letterIdenticonCmp
|
||||
StatusLetterIdenticon {
|
||||
width: 40
|
||||
height: 40
|
||||
chatName: popup.name
|
||||
color: popup.communityColor || Style.current.blue
|
||||
}
|
||||
}
|
||||
|
||||
StyledTextEdit {
|
||||
id: communityName
|
||||
text: textMetrics.elidedText
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 2
|
||||
anchors.left: communityImg.active ? communityImg.right : parent.left
|
||||
anchors.leftMargin: communityImg.active ? Style.current.smallPadding : 0
|
||||
anchors.right: parent.right
|
||||
/* Because of ModalPopup's close button we must set rightMargin,
|
||||
cause we don't want overlap it.
|
||||
This should be generally fixed in ModalPopup file. */
|
||||
anchors.rightMargin: 40
|
||||
font.bold: true
|
||||
font.pixelSize: 17
|
||||
readOnly: true
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: textMetrics
|
||||
font: communityName.font
|
||||
text: modalHeader.title
|
||||
elideWidth: communityName.width
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: headerDescription
|
||||
text: modalHeader.description
|
||||
anchors.left: communityName.left
|
||||
anchors.top: communityName.bottom
|
||||
anchors.topMargin: 2
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Thin
|
||||
color: Style.current.secondaryText
|
||||
}
|
||||
|
||||
Separator {
|
||||
anchors.top: headerDescription.bottom
|
||||
anchors.topMargin: modalHeader.description === "" ? 0 : Style.current.padding
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: -Style.current.padding
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
}
|
||||
}
|
||||
|
||||
StackView {
|
||||
content: StackView {
|
||||
id: stack
|
||||
initialItem: profileOverview
|
||||
width: parent.width
|
||||
|
||||
anchors.centerIn: parent
|
||||
width: popup.width
|
||||
height: currentItem.implicitHeight || currentItem.height
|
||||
|
||||
pushEnter: Transition { enabled: false }
|
||||
pushExit: Transition { enabled: false }
|
||||
popEnter: Transition { enabled: false }
|
||||
popExit: Transition { enabled: false }
|
||||
|
||||
Component {
|
||||
id: inviteFriendsView
|
||||
CommunityProfilePopupInviteFriendsView {
|
||||
headerTitle: qsTr("Invite friends")
|
||||
contactListSearch.chatKey.text: ""
|
||||
contactListSearch.pubKey: ""
|
||||
contactListSearch.pubKeys: []
|
||||
contactListSearch.ensUsername: ""
|
||||
contactListSearch.existingContacts.visible: profileModel.contacts.list.hasAddedContacts()
|
||||
contactListSearch.noContactsRect.visible: !contactListSearch.existingContacts.visible
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: membersList
|
||||
CommunityProfilePopupMembersList {
|
||||
headerTitle: qsTr("Members")
|
||||
headerDescription: popup.nbMembers.toString()
|
||||
members: chatsModel.communities.activeCommunity.members
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: profileOverview
|
||||
CommunityProfilePopupOverview {
|
||||
property bool useLetterIdenticon: !!!popup.source
|
||||
width: stack.width
|
||||
|
||||
headerTitle: chatsModel.communities.activeCommunity.name
|
||||
headerDescription: {
|
||||
headerSubtitle: {
|
||||
switch(access) {
|
||||
//% "Public community"
|
||||
case Constants.communityChatPublicAccess: return qsTrId("public-community");
|
||||
|
@ -161,37 +59,69 @@ ModalPopup {
|
|||
}
|
||||
headerImageSource: chatsModel.communities.activeCommunity.thumbnailImage
|
||||
description: chatsModel.communities.activeCommunity.description
|
||||
|
||||
onMembersListButtonClicked: popup.contentComponent.push(membersList)
|
||||
onNotificationsButtonClicked: {
|
||||
chatsModel.communities.setCommunityMuted(chatsModel.communities.activeCommunity.id, checked)
|
||||
}
|
||||
onEditButtonClicked: openPopup(editCommunityPopup)
|
||||
onTransferOwnershipButtonClicked: openPopup(transferOwnershipPopup, {privateKey: chatsModel.communities.exportComumnity()})
|
||||
onLeaveButtonClicked: chatsModel.communities.leaveCommunity(communityId)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: membersList
|
||||
CommunityProfilePopupMembersList {
|
||||
width: stack.width
|
||||
headerTitle: qsTr("Members")
|
||||
headerSubtitle: popup.nbMembers.toString()
|
||||
members: chatsModel.communities.activeCommunity.members
|
||||
onInviteButtonClicked: popup.contentComponent.push(inviteFriendsView)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: inviteFriendsView
|
||||
CommunityProfilePopupInviteFriendsView {
|
||||
width: stack.width
|
||||
headerTitle: qsTr("Invite friends")
|
||||
|
||||
contactListSearch.chatKey.text: ""
|
||||
contactListSearch.pubKey: ""
|
||||
contactListSearch.pubKeys: []
|
||||
contactListSearch.ensUsername: ""
|
||||
contactListSearch.existingContacts.visible: profileModel.contacts.list.hasAddedContacts()
|
||||
contactListSearch.noContactsRect.visible: !contactListSearch.existingContacts.visible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: Item {
|
||||
id: modalFooter
|
||||
visible: stack.depth > 1
|
||||
width: parent.width
|
||||
height: modalFooter.visible ? btnBack.height : 0
|
||||
leftButtons: [
|
||||
StatusRoundButton {
|
||||
id: btnBack
|
||||
anchors.left: parent.left
|
||||
icon.name: "arrow-right"
|
||||
icon.width: 20
|
||||
icon.height: 16
|
||||
icon.width: 20
|
||||
rotation: 180
|
||||
type: globalSettings.theme === Universal.Dark ? "secondary" : "primary"
|
||||
visible: contentComponent.depth > 1
|
||||
height: !visible ? 0 : implicitHeight
|
||||
onClicked: {
|
||||
stack.pop()
|
||||
contentComponent.pop()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
text: qsTr("Invite")
|
||||
anchors.right: parent.right
|
||||
enabled: stack.currentItem.contactListSearch !== undefined && stack.currentItem.contactListSearch.pubKeys.length > 0
|
||||
visible: popup.contentComponent.depth > 2
|
||||
height: !visible ? 0 : implicitHeight
|
||||
enabled: popup.contentComponent.currentItem.contactListSearch !== undefined && popup.contentComponent.currentItem.contactListSearch.pubKeys.length > 0
|
||||
onClicked: {
|
||||
stack.currentItem.sendInvites(stack.currentItem.contactListSearch.pubKeys)
|
||||
stack.pop()
|
||||
popup.contentComponent.currentItem.sendInvites(popup.contentComponent.currentItem.contactListSearch.pubKeys)
|
||||
popup.contentComponent.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -7,17 +7,16 @@ import "../../../../imports"
|
|||
import "../../../../shared"
|
||||
import "../../../../shared/status"
|
||||
|
||||
Item {
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
property string headerTitle: ""
|
||||
property string headerDescription: ""
|
||||
property string headerImageSource: ""
|
||||
|
||||
property alias contactListSearch: contactFieldAndList
|
||||
|
||||
height: 400
|
||||
|
||||
function sendInvites(pubKeys) {
|
||||
const error = chatsModel.communities.inviteUsersToCommunityById(popup.communityId, JSON.stringify(pubKeys))
|
||||
if (error) {
|
||||
|
@ -28,31 +27,32 @@ Item {
|
|||
contactFieldAndList.successMessage = qsTr("Invite successfully sent")
|
||||
}
|
||||
|
||||
TextWithLabel {
|
||||
id: shareCommunity
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
//% "Share community"
|
||||
label: qsTrId("share-community")
|
||||
text: `${Constants.communityLinkPrefix}${communityId.substring(0, 4)}...${communityId.substring(communityId.length -2)}`
|
||||
textToCopy: Constants.communityLinkPrefix + communityId
|
||||
StatusModalDivider {
|
||||
bottomPadding: 8
|
||||
}
|
||||
|
||||
Separator {
|
||||
id: sep
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: shareCommunity.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
anchors.rightMargin: -Style.current.padding
|
||||
StatusDescriptionListItem {
|
||||
title: qsTr("Share community")
|
||||
subTitle: `${Constants.communityLinkPrefix}${communityId.substring(0, 4)}...${communityId.substring(communityId.length -2)}`
|
||||
tooltip.text: qsTr("Copy to clipboard")
|
||||
icon.name: "copy"
|
||||
iconButton.onClicked: {
|
||||
let link = `${Constants.communityLinkPrefix}${communityId}`
|
||||
chatsModel.copyToClipboard(link)
|
||||
tooltip.visible = !tooltip.visible
|
||||
}
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
bottomPadding: 16
|
||||
}
|
||||
|
||||
ContactsListAndSearch {
|
||||
id: contactFieldAndList
|
||||
anchors.top: sep.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 32
|
||||
showCheckbox: true
|
||||
hideCommunityMembers: true
|
||||
}
|
||||
|
|
|
@ -1,206 +1,205 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Controls.Universal 2.12
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import "../../../../imports"
|
||||
import "../../../../shared"
|
||||
import "../../../../shared/status"
|
||||
import "./"
|
||||
import "../components"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
height: childrenRect.height
|
||||
implicitWidth: 480
|
||||
|
||||
property string headerTitle: ""
|
||||
property string headerDescription: ""
|
||||
property string headerSubtitle: ""
|
||||
property string headerImageSource: ""
|
||||
property alias members: memberList.model
|
||||
height: 450
|
||||
|
||||
CommunityPopupButton {
|
||||
id: inviteBtn
|
||||
visible: isAdmin
|
||||
//% "Invite People"
|
||||
label: qsTrId("invite-people")
|
||||
width: parent.width
|
||||
type: globalSettings.theme === Universal.Dark ? "secondary" : "primary"
|
||||
iconName: "invite"
|
||||
onClicked: stack.push(inviteFriendsView)
|
||||
height: visible ? 64 : 0
|
||||
}
|
||||
signal inviteButtonClicked()
|
||||
|
||||
Separator {
|
||||
id: sep
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: inviteBtn.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
anchors.rightMargin: -Style.current.padding
|
||||
visible: inviteBtn.visible
|
||||
}
|
||||
Column {
|
||||
|
||||
StatusSettingsLineButton {
|
||||
id: membershipRequestsBtn
|
||||
text: qsTr("Membership requests")
|
||||
badgeText: chatsModel.communities.activeCommunity.communityMembershipRequests.nbRequests.toString()
|
||||
visible: chatsModel.communities.activeCommunity.communityMembershipRequests.nbRequests > 0
|
||||
badgeSize: 22
|
||||
badgeRadius: badgeSize / 2
|
||||
isBadge: true
|
||||
height: 64
|
||||
anchors.top: sep.bottom
|
||||
anchors.topMargin: visible ? Style.current.smallPadding : 0
|
||||
anchors.leftMargin: 0
|
||||
anchors.rightMargin: 0
|
||||
onClicked: membershipRequestPopup.open()
|
||||
}
|
||||
id: memberSearchAndInviteButton
|
||||
|
||||
Separator {
|
||||
id: sep2
|
||||
visible: membershipRequestsBtn.visible
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: membershipRequestsBtn.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
anchors.rightMargin: -Style.current.padding
|
||||
}
|
||||
StatusModalDivider {}
|
||||
|
||||
ListView {
|
||||
id: memberList
|
||||
anchors.top: sep2.visible ? sep2.bottom : sep.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottomMargin: Style.current.bigPadding
|
||||
spacing: 4
|
||||
clip: true
|
||||
delegate: Rectangle {
|
||||
id: contactRow
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 64
|
||||
radius: Style.current.radius
|
||||
color: isHovered ? Style.current.backgroundHover : Style.current.transparent
|
||||
height: 76
|
||||
|
||||
property bool isHovered: false
|
||||
property string nickname: appMain.getUserNickname(model.pubKey)
|
||||
|
||||
StatusImageIdenticon {
|
||||
id: identicon
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: model.identicon
|
||||
Input {
|
||||
id: memberSearch
|
||||
width: parent.width - 32
|
||||
anchors.centerIn: parent
|
||||
placeholderText: qsTr("Member name")
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: txtUsername
|
||||
text: !model.userName.endsWith(".eth") && !!contactRow.nickname ?
|
||||
contactRow.nickname : Utils.removeStatusEns(model.userName)
|
||||
anchors.left: identicon.right
|
||||
anchors.leftMargin: Style.current.smallPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
StatusListItem {
|
||||
id: inviteButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: isAdmin
|
||||
title: qsTr("Invite People")
|
||||
icon.name: "share-ios"
|
||||
type: StatusListItem.Type.Secondary
|
||||
sensor.onClicked: root.inviteButtonClicked()
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
visible: inviteButton.visible && memberRequestsButton.visible
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
}
|
||||
|
||||
StatusContactRequestsIndicatorListItem {
|
||||
|
||||
id: memberRequestsButton
|
||||
|
||||
property int nbRequests: chatsModel.communities.activeCommunity.communityMembershipRequests.nbRequests
|
||||
width: parent.width - 32
|
||||
visible: isAdmin && nbRequests > 0
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
title: qsTr("Membership requests")
|
||||
requestsCount: nbRequests
|
||||
sensor.onClicked: membershipRequestPopup.open()
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
topPadding: !memberRequestsButton.visible && !inviteButton.visible ? 0 : 8
|
||||
bottomPadding: 8
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
width: parent.width
|
||||
height: 300
|
||||
anchors.top: memberSearchAndInviteButton.bottom
|
||||
|
||||
contentHeight: Math.max(300, memberListColumn.height)
|
||||
clip: true
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 300
|
||||
visible: memberList.count === 0
|
||||
|
||||
StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Community members will appear here")
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
StyledText {
|
||||
text: " (" + qsTr("You") + ")"
|
||||
visible: !moreActionsBtn.visible
|
||||
anchors.left: txtUsername.right
|
||||
anchors.leftMargin: Style.current.smallPadding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.smallPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Style.current.secondaryText
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 300
|
||||
visible: !!memberSearch.text && !!memberList.count && !memberListColumn.height
|
||||
|
||||
StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("No contacts found")
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: contactRow.isHovered = true
|
||||
onExited: contactRow.isHovered = false
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: openProfilePopup(model.userName, model.pubKey, model.identicon, '', contactRow.nickname)
|
||||
}
|
||||
Column {
|
||||
id: memberListColumn
|
||||
width: parent.width
|
||||
visible: memberList.count > 0 || height > 0
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
StatusContextMenuButton {
|
||||
id: moreActionsBtn
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: model.pubKey.toLowerCase() !== profileModel.profile.pubKey.toLowerCase()
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: contextMenu.popup(-contextMenu.width + moreActionsBtn.width, moreActionsBtn.height + 4)
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onExited: {
|
||||
contactRow.isHovered = false
|
||||
moreActionsBtn.highlighted = false
|
||||
Repeater {
|
||||
id: memberList
|
||||
delegate: StatusListItem {
|
||||
|
||||
id: memberItem
|
||||
|
||||
property string nickname: appMain.getUserNickname(model.pubKey)
|
||||
property string profileImage: appMain.getProfileImage(model.pubKey)
|
||||
|
||||
visible: !!!memberSearch.text ||
|
||||
model.userName.toLowerCase().includes(memberSearch.text.toLowerCase()) ||
|
||||
nickname.toLowerCase().includes(memberSearch.text.toLowerCase())
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
image.isIdenticon: !profileImage
|
||||
image.source: profileImage || model.identicon
|
||||
|
||||
title: {
|
||||
if (menuButton.visible) {
|
||||
return !model.userName.endsWith(".eth") && !!nickname ?
|
||||
nickname : Utils.removeStatusEns(model.userName)
|
||||
}
|
||||
return qsTr("You")
|
||||
}
|
||||
onEntered: {
|
||||
contactRow.isHovered = true
|
||||
moreActionsBtn.highlighted = true
|
||||
}
|
||||
PopupMenu {
|
||||
id: contextMenu
|
||||
Action {
|
||||
icon.source: "../../../img/communities/menu/view-profile.svg"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
//% "View Profile"
|
||||
text: qsTrId("view-profile")
|
||||
onTriggered: openProfilePopup(model.userName, model.pubKey, model.identicon, '', contactRow.nickname)
|
||||
|
||||
components: [
|
||||
StatusFlatRoundButton {
|
||||
id: menuButton
|
||||
width: 32
|
||||
height: 32
|
||||
visible: model.pubKey.toLowerCase() !== profileModel.profile.pubKey.toLowerCase()
|
||||
icon.name: "more"
|
||||
type: StatusFlatRoundButton.Type.Secondary
|
||||
onClicked: {
|
||||
highlighted = true
|
||||
communityMemberContextMenu.popup(-communityMemberContextMenu.width+menuButton.width, menuButton.height + 4)
|
||||
}
|
||||
|
||||
StatusPopupMenu {
|
||||
|
||||
id: communityMemberContextMenu
|
||||
|
||||
onClosed: {
|
||||
menuButton.highlighted = false
|
||||
}
|
||||
|
||||
StatusMenuItem {
|
||||
text: qsTr("View Profile")
|
||||
icon.name: "channel"
|
||||
onTriggered: openProfilePopup(model.userName, model.pubKey, memberItem.image.source, '', memberItem.nickname)
|
||||
}
|
||||
|
||||
StatusMenuSeparator {
|
||||
visible: chatsModel.communities.activeCommunity.admin
|
||||
}
|
||||
|
||||
StatusMenuItem {
|
||||
text: qsTr("Kick")
|
||||
icon.name: "arrow-right"
|
||||
iconRotation: 180
|
||||
type: StatusMenuItem.Type.Danger
|
||||
enabled: chatsModel.communities.activeCommunity.admin
|
||||
onTriggered: chatsModel.communities.removeUserFromCommunity(model.pubKey)
|
||||
}
|
||||
|
||||
StatusMenuItem {
|
||||
text: qsTr("Ban")
|
||||
icon.name: "cancel"
|
||||
type: StatusMenuItem.Type.Danger
|
||||
enabled: chatsModel.communities.activeCommunity.admin
|
||||
onTriggered: chatsModel.communities.banUserFromCommunity(model.pubKey, chatsModel.communities.activeCommunity.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Action { */
|
||||
/* icon.source: "../../../img/communities/menu/roles.svg" */
|
||||
/* icon.width: 16 */
|
||||
/* icon.height: 16 */
|
||||
/* //% "Roles" */
|
||||
/* text: qsTrId("roles") */
|
||||
/* onTriggered: console.log("TODO") */
|
||||
/* } */
|
||||
Separator {
|
||||
height: 10
|
||||
visible: chatsModel.communities.activeCommunity.admin
|
||||
}
|
||||
Action {
|
||||
property string type: "danger"
|
||||
icon.source: "../../../img/communities/menu/kick.svg"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
icon.color: Style.current.red
|
||||
//% "Kick"
|
||||
text: qsTrId("kick")
|
||||
enabled: chatsModel.communities.activeCommunity.admin
|
||||
onTriggered: chatsModel.communities.removeUserFromCommunity(model.pubKey)
|
||||
}
|
||||
Action {
|
||||
property string type: "danger"
|
||||
icon.source: "../../../img/communities/menu/ban.svg"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
icon.color: Style.current.red
|
||||
//% "Ban"
|
||||
text: qsTrId("ban")
|
||||
enabled: chatsModel.communities.activeCommunity.admin
|
||||
onTriggered: chatsModel.communities.banUserFromCommunity(model.pubKey, chatsModel.communities.activeCommunity.id)
|
||||
}
|
||||
/* Separator {} */
|
||||
/* Action { */
|
||||
/* icon.source: "../../../img/communities/menu/transfer-ownership.svg" */
|
||||
/* icon.width: 16 */
|
||||
/* icon.height: 16 */
|
||||
/* icon.color: Style.current.red */
|
||||
/* //% "Transfer ownership" */
|
||||
/* text: qsTrId("transfer-ownership") */
|
||||
/* onTriggered: console.log("TODO") */
|
||||
/* } */
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
anchors.top: scrollView.bottom
|
||||
topPadding: 8
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,236 +1,166 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtGraphicalEffects 1.13
|
||||
import QtQuick.Controls.Universal 2.12
|
||||
import "../../../../imports"
|
||||
import "../../../../shared"
|
||||
import "../../../../shared/status"
|
||||
import "../ContactsColumn"
|
||||
|
||||
Item {
|
||||
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 "../../../../imports"
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
property string headerTitle: ""
|
||||
property string headerDescription: ""
|
||||
property string headerSubtitle: ""
|
||||
property string headerImageSource: ""
|
||||
property string description: ""
|
||||
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
signal membersListButtonClicked()
|
||||
signal notificationsButtonClicked(bool checked)
|
||||
signal editButtonClicked()
|
||||
signal transferOwnershipButtonClicked()
|
||||
signal leaveButtonClicked()
|
||||
|
||||
StyledText {
|
||||
id: descriptionText
|
||||
text: root.description
|
||||
wrapMode: Text.Wrap
|
||||
StatusModalDivider {
|
||||
bottomPadding: 8
|
||||
}
|
||||
|
||||
Item {
|
||||
height: 46
|
||||
width: parent.width
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
||||
Separator {
|
||||
id: sep1
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: descriptionText.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
anchors.rightMargin: -Style.current.padding
|
||||
}
|
||||
|
||||
TextWithLabel {
|
||||
id: shareCommunity
|
||||
anchors.top: sep1.bottom
|
||||
anchors.topMargin: Style.current.bigPadding
|
||||
//% "Share community"
|
||||
label: qsTrId("share-community")
|
||||
text: `${Constants.communityLinkPrefix}${communityId.substring(0, 4)}...${communityId.substring(communityId.length -2)}`
|
||||
textToCopy: Constants.communityLinkPrefix + communityId
|
||||
}
|
||||
|
||||
Separator {
|
||||
id: sep2
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: shareCommunity.bottom
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
anchors.rightMargin: -Style.current.padding
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.top: sep2.bottom
|
||||
anchors.topMargin: Style.current.halfPadding
|
||||
width: parent.width
|
||||
|
||||
Loader {
|
||||
width: parent.width
|
||||
sourceComponent: Component {
|
||||
CommunityPopupButton {
|
||||
id: memberBtn
|
||||
label: qsTr("Members")
|
||||
iconName: "members"
|
||||
txtColor: Style.current.textColor
|
||||
onClicked: stack.push(membersList)
|
||||
type: globalSettings.theme === Universal.Dark ? "secondary" : "primary"
|
||||
|
||||
Item {
|
||||
property int nbRequests: chatsModel.communities.activeCommunity.communityMembershipRequests.nbRequests
|
||||
|
||||
id: memberBlock
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: childrenRect.width
|
||||
height: memberBtn.height
|
||||
|
||||
StyledText {
|
||||
id: nbMemberText
|
||||
text: nbMembers.toString()
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
padding: 0
|
||||
font.pixelSize: 15
|
||||
color: Style.current.secondaryText
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: badge
|
||||
visible: memberBlock.nbRequests > 0
|
||||
anchors.left: nbMemberText.right
|
||||
anchors.leftMargin: visible ? Style.current.halfPadding : 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Style.current.blue
|
||||
width: visible ? 22 : 0
|
||||
height: 22
|
||||
radius: width / 2
|
||||
Text {
|
||||
font.pixelSize: 12
|
||||
color: Style.current.white
|
||||
anchors.centerIn: parent
|
||||
text: memberBlock.nbRequests
|
||||
}
|
||||
}
|
||||
|
||||
SVGImage {
|
||||
id: caret
|
||||
anchors.left: badge.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: "../../../img/caret.svg"
|
||||
width: 13
|
||||
height: 7
|
||||
rotation: -90
|
||||
ColorOverlay {
|
||||
anchors.fill: parent
|
||||
source: parent
|
||||
color: Style.current.secondaryText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add this back when roles exist
|
||||
// Loader {
|
||||
// active: isAdmin
|
||||
// width: parent.width
|
||||
// sourceComponent: CommunityPopupButton {
|
||||
// label: qsTr("Roles")
|
||||
// iconName: "roles"
|
||||
// width: parent.width
|
||||
// onClicked: console.log("TODO:")
|
||||
// txtColor: Style.current.textColor
|
||||
// SVGImage {
|
||||
// anchors.verticalCenter: parent.verticalCenter
|
||||
// anchors.right: parent.right
|
||||
// anchors.rightMargin: Style.current.padding
|
||||
// source: "../../../img/caret.svg"
|
||||
// width: 13
|
||||
// height: 7
|
||||
// rotation: -90
|
||||
// ColorOverlay {
|
||||
// anchors.fill: parent
|
||||
// source: parent
|
||||
// color: Style.current.secondaryText
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
CommunityPopupButton {
|
||||
id: notificationsBtn
|
||||
//% "Notifications"
|
||||
label: qsTrId("notifications")
|
||||
iconName: "notifications"
|
||||
width: parent.width
|
||||
txtColor: Style.current.textColor
|
||||
type: globalSettings.theme === Universal.Dark ? "secondary" : "primary"
|
||||
onClicked: function(){
|
||||
notificationSwitch.clicked()
|
||||
}
|
||||
StatusSwitch {
|
||||
id: notificationSwitch
|
||||
checked: !chatsModel.communities.activeCommunity.muted
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Style.current.padding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: function () {
|
||||
chatsModel.communities.setCommunityMuted(chatsModel.communities.activeCommunity.id, notificationSwitch.checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: spacer1
|
||||
width: parent.width
|
||||
height: Style.current.halfPadding
|
||||
}
|
||||
|
||||
Separator {
|
||||
StatusBaseText {
|
||||
id: communityDescription
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: -Style.current.padding
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
}
|
||||
|
||||
Item {
|
||||
id: spacer2
|
||||
width: parent.width
|
||||
height: Style.current.halfPadding
|
||||
}
|
||||
|
||||
Loader {
|
||||
// TODO: once Edit is vailable in the app, put back isAdmin
|
||||
active: isAdmin
|
||||
width: parent.width
|
||||
sourceComponent: CommunityPopupButton {
|
||||
//% "Edit community"
|
||||
label: qsTrId("edit-community")
|
||||
iconName: "edit"
|
||||
type: globalSettings.theme === Universal.Dark ? "secondary" : "primary"
|
||||
onClicked: openPopup(editCommunityPopup)
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: isAdmin
|
||||
width: parent.width
|
||||
sourceComponent: CommunityPopupButton {
|
||||
label: qsTr("Transfer ownership")
|
||||
iconName: "../transfer"
|
||||
type: globalSettings.theme === Universal.Dark ? "secondary" : "primary"
|
||||
onClicked: openPopup(transferOwnershipPopup, {privateKey: chatsModel.communities.exportComumnity()})
|
||||
}
|
||||
}
|
||||
|
||||
CommunityPopupButton {
|
||||
//% "Leave community"
|
||||
label: qsTrId("leave-community")
|
||||
iconName: "leave"
|
||||
type: "warn"
|
||||
txtColor: Style.current.red
|
||||
onClicked: chatsModel.communities.leaveCommunity(communityId)
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
text: root.description
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
}
|
||||
|
||||
StatusDescriptionListItem {
|
||||
title: qsTr("Share community")
|
||||
subTitle: `${Constants.communityLinkPrefix}${communityId.substring(0, 4)}...${communityId.substring(communityId.length -2)}`
|
||||
tooltip.text: qsTr("Copy to clipboard")
|
||||
icon.name: "copy"
|
||||
iconButton.onClicked: {
|
||||
let link = `${Constants.communityLinkPrefix}${communityId}`
|
||||
chatsModel.copyToClipboard(link)
|
||||
tooltip.visible = !tooltip.visible
|
||||
}
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
id: membersListItem
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
property int nbRequests: chatsModel.communities.activeCommunity.communityMembershipRequests.nbRequests
|
||||
|
||||
title: qsTr("Members")
|
||||
icon.name: "group-chat"
|
||||
label: nbMembers.toString()
|
||||
sensor.onClicked: root.membersListButtonClicked()
|
||||
|
||||
components: [
|
||||
StatusBadge {
|
||||
visible: !!membersListItem.nbRequests
|
||||
value: membersListItem.nbRequests
|
||||
},
|
||||
StatusIcon {
|
||||
icon: "chevron-down"
|
||||
rotation: 270
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
title: qsTr("Notifications")
|
||||
icon.name: "notification"
|
||||
components: [
|
||||
StatusSwitch {
|
||||
checked: !chatsModel.communities.activeCommunity.muted
|
||||
onClicked: root.notificationsButtonClicked(checked)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: isAdmin
|
||||
title: qsTr("Edit community")
|
||||
icon.name: "edit"
|
||||
type: StatusListItem.Type.Secondary
|
||||
sensor.onClicked: root.editButtonClicked()
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: isAdmin
|
||||
title: qsTr("Transfer ownership")
|
||||
icon.name: "exchange"
|
||||
type: StatusListItem.Type.Secondary
|
||||
sensor.onClicked: root.transferOwnershipButtonClicked()
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
title: qsTr("Leave community")
|
||||
icon.name: "arrow-right"
|
||||
icon.height: 16
|
||||
icon.width: 20
|
||||
icon.rotation: 180
|
||||
type: StatusListItem.Type.Secondary
|
||||
sensor.onClicked: root.leaveButtonClicked()
|
||||
}
|
||||
|
||||
/* // TODO add this back when roles exist */
|
||||
/* // Loader { */
|
||||
/* // active: isAdmin */
|
||||
/* // width: parent.width */
|
||||
/* // sourceComponent: CommunityPopupButton { */
|
||||
/* // label: qsTr("Roles") */
|
||||
/* // iconName: "roles" */
|
||||
/* // width: parent.width */
|
||||
/* // onClicked: console.log("TODO:") */
|
||||
/* // txtColor: Style.current.textColor */
|
||||
/* // SVGImage { */
|
||||
/* // anchors.verticalCenter: parent.verticalCenter */
|
||||
/* // anchors.right: parent.right */
|
||||
/* // anchors.rightMargin: Style.current.padding */
|
||||
/* // source: "../../../img/caret.svg" */
|
||||
/* // width: 13 */
|
||||
/* // height: 7 */
|
||||
/* // rotation: -90 */
|
||||
/* // ColorOverlay { */
|
||||
/* // anchors.fill: parent */
|
||||
/* // source: parent */
|
||||
/* // color: Style.current.secondaryText */
|
||||
/* // } */
|
||||
/* // } */
|
||||
/* // } */
|
||||
/* // } */
|
||||
}
|
||||
|
|
|
@ -492,6 +492,7 @@ StatusAppLayout {
|
|||
Component {
|
||||
id: inviteFriendsToCommunityPopup
|
||||
InviteFriendsToCommunityPopup {
|
||||
anchors.centerIn: parent
|
||||
onClosed: {
|
||||
destroy()
|
||||
}
|
||||
|
@ -501,6 +502,7 @@ StatusAppLayout {
|
|||
Component {
|
||||
id: communityMembersPopup
|
||||
CommunityMembersPopup {
|
||||
anchors.centerIn: parent
|
||||
onClosed: {
|
||||
destroy()
|
||||
}
|
||||
|
@ -510,6 +512,7 @@ StatusAppLayout {
|
|||
Component {
|
||||
id: editCommunityPopup
|
||||
CreateCommunityPopup {
|
||||
anchors.centerIn: parent
|
||||
isEdit: true
|
||||
onClosed: {
|
||||
destroy()
|
||||
|
|
Loading…
Reference in New Issue