refactor(Communities): replace `CommunityMembersPopup` with `CommunityProfilePopup`

When right-clicking a community from the navbar and selecting "View community", Status Desktop
opens `CommunityMembersPopup` which looks like it was either never really finished or more of an
intermediate solution until a proper community profile popup was created.

That's why this commit replaces it with a `CommunityProfilePopup` instead.
In fact, this lead to changes in `CommunityProfilePopup` where the `activeCommunity` dependency
is entirely removed, which allows us to use this popup in various places given that it's hydrated
with proper data.

Because we're no longer relying on `activeCommunity` inside that popup, all of its children and
connected popups needed that same refactor as well, hence this PR introduces a few more changes.

Closes #2890
This commit is contained in:
Pascal Precht 2021-07-16 14:36:27 +02:00 committed by Iuri Matias
parent 9eb752885d
commit 4dab6f9239
8 changed files with 79 additions and 280 deletions

View File

@ -37,8 +37,11 @@ Item {
qsTrId("-1-members").arg(chatsModel.communities.activeCommunity.nbMembers) qsTrId("-1-members").arg(chatsModel.communities.activeCommunity.nbMembers)
chatInfoButton.image.source: chatsModel.communities.activeCommunity.thumbnailImage chatInfoButton.image.source: chatsModel.communities.activeCommunity.thumbnailImage
chatInfoButton.icon.color: chatsModel.communities.activeCommunity.communityColor chatInfoButton.icon.color: chatsModel.communities.activeCommunity.communityColor
chatInfoButton.onClicked: communityProfilePopup.open()
menuButton.visible: chatsModel.communities.activeCommunity.admin && chatsModel.communities.activeCommunity.canManageUsers menuButton.visible: chatsModel.communities.activeCommunity.admin && chatsModel.communities.activeCommunity.canManageUsers
chatInfoButton.onClicked: openPopup(communityProfilePopup, {
community: chatsModel.communities.activeCommunity
})
popupMenu: StatusPopupMenu { popupMenu: StatusPopupMenu {
StatusMenuItem { StatusMenuItem {
//% "Create channel" //% "Create channel"
@ -276,24 +279,6 @@ Item {
} }
} }
Component {
id: transferOwnershipPopup
TransferOwnershipPopup {}
}
CommunityProfilePopup {
id: communityProfilePopup
anchors.centerIn: parent
communityId: chatsModel.communities.activeCommunity.id
name: chatsModel.communities.activeCommunity.name
description: chatsModel.communities.activeCommunity.description
access: chatsModel.communities.activeCommunity.access
nbMembers: chatsModel.communities.activeCommunity.nbMembers
isAdmin: chatsModel.communities.activeCommunity.admin
source: chatsModel.communities.activeCommunity.thumbnailImage
communityColor: chatsModel.communities.activeCommunity.communityColor
}
Component { Component {
id: deleteCategoryConfirmationDialogComponent id: deleteCategoryConfirmationDialogComponent
ConfirmationDialog { ConfirmationDialog {

View File

@ -68,5 +68,15 @@ Rectangle {
openPopup(transferOwnershipPopup, {privateKey: chatsModel.communities.exportComumnity()}) openPopup(transferOwnershipPopup, {privateKey: chatsModel.communities.exportComumnity()})
} }
} }
Component {
id: transferOwnershipPopup
TransferOwnershipPopup {
anchors.centerIn: parent
onClosed: {
destroy()
}
}
}
} }

View File

@ -1,203 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import "../../../../imports"
import "../../../../shared"
import "../../../../shared/status"
import "./"
import "../components"
ModalPopup {
id: popup
property QtObject community: chatsModel.communities.activeCommunity
header: Item {
height: childrenRect.height
width: parent.width
StyledText {
id: groupName
//% "Members"
text: qsTrId("members-title")
anchors.top: parent.top
anchors.topMargin: 2
anchors.left: parent.left
font.bold: true
font.pixelSize: 14
wrapMode: Text.WordWrap
}
StyledText {
id: nbMembersText
text: community.nbMembers.toString()
width: 160
anchors.left: parent.left
anchors.top: groupName.bottom
anchors.topMargin: 2
font.pixelSize: 14
color: Style.current.secondaryText
}
Separator {
anchors.top: nbMembersText.bottom
anchors.topMargin: Style.current.padding
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
}
}
CommunityPopupButton {
id: inviteBtn
//% "Invite People"
label: qsTrId("invite-people")
width: parent.width
iconName: "invite"
onClicked: openPopup(inviteFriendsToCommunityPopup)
}
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
}
MembershipRequestsButton {
id: membershipRequestsBtn
anchors.top: sep.bottom
anchors.topMargin: visible ? Style.current.smallPadding : 0
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: -Style.current.padding
anchors.rightMargin: -Style.current.padding
}
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
}
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.halfPadding
spacing: 4
Layout.fillWidth: true
Layout.fillHeight: true
model: community.members
clip: true
delegate: Item {
id: contactRow
width: parent.width
height: identicon.height
property string nickname: appMain.getUserNickname(model.pubKey)
StatusImageIdenticon {
id: identicon
anchors.left: parent.left
source: model.identicon
}
StyledText {
text: !model.userName.endsWith(".eth") && !!contactRow.nickname ?
contactRow.nickname : Utils.removeStatusEns(model.userName)
anchors.left: identicon.right
anchors.leftMargin: Style.current.smallPadding
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 13
}
StyledText {
id: moreActionsBtn
text: "..."
font.letterSpacing: 0.5
font.bold: true
lineHeight: 1.4
font.pixelSize: 25
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
anchors.verticalCenter: parent.verticalCenter
MouseArea {
anchors.fill: parent
onClicked: contextMenu.popup(-contextMenu.width / 2 + moreActionsBtn.width / 2, moreActionsBtn.height)
cursorShape: Qt.PointingHandCursor
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)
}
Action {
icon.source: "../../../img/communities/menu/roles.svg"
icon.width: 16
icon.height: 16
//% "Roles"
text: qsTrId("roles")
enabled: chatsModel.communities.activeCommunity.admin
onTriggered: console.log("TODO")
}
Separator {
visible: chatsModel.communities.activeCommunity.admin
}
Action {
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 {
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: console.log("TODO")
}
Separator {
visible: chatsModel.communities.activeCommunity.admin
}
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")
enabled: chatsModel.communities.activeCommunity.admin
onTriggered: console.log("TODO")
}
}
}
}
}
}
}

View File

@ -7,14 +7,9 @@ import StatusQ.Popups 0.1
import "../../../../imports" import "../../../../imports"
StatusModal { StatusModal {
property string communityId: chatsModel.communities.activeCommunity.id
property string name: chatsModel.communities.activeCommunity.name property var community
property string description: chatsModel.communities.activeCommunity.description
property int access: chatsModel.communities.activeCommunity.access
property string source: chatsModel.communities.activeCommunity.source
property string communityColor: chatsModel.communities.activeCommunity.communityColor
property int nbMembers: chatsModel.communities.activeCommunity.nbMembers
property bool isAdmin: chatsModel.communities.activeCommunity.isAdmin
id: popup id: popup
onClosed: { onClosed: {
@ -44,9 +39,9 @@ StatusModal {
CommunityProfilePopupOverview { CommunityProfilePopupOverview {
width: stack.width width: stack.width
headerTitle: chatsModel.communities.activeCommunity.name headerTitle: popup.community.name
headerSubtitle: { headerSubtitle: {
switch(access) { switch(popup.community.access) {
//% "Public community" //% "Public community"
case Constants.communityChatPublicAccess: return qsTrId("public-community"); case Constants.communityChatPublicAccess: return qsTrId("public-community");
//% "Invitation only community" //% "Invitation only community"
@ -57,16 +52,28 @@ StatusModal {
default: return qsTrId("unknown-community"); default: return qsTrId("unknown-community");
} }
} }
headerImageSource: chatsModel.communities.activeCommunity.thumbnailImage headerImageSource: popup.community.thumbnailImage
description: chatsModel.communities.activeCommunity.description community: popup.community
onMembersListButtonClicked: popup.contentComponent.push(membersList) onMembersListButtonClicked: popup.contentComponent.push(membersList)
onNotificationsButtonClicked: { onNotificationsButtonClicked: {
chatsModel.communities.setCommunityMuted(chatsModel.communities.activeCommunity.id, checked) chatsModel.communities.setCommunityMuted(popup.community.id, checked)
} }
onEditButtonClicked: openPopup(editCommunityPopup) onEditButtonClicked: openPopup(editCommunityPopup, {
community: popup.community
})
onTransferOwnershipButtonClicked: openPopup(transferOwnershipPopup, {privateKey: chatsModel.communities.exportComumnity()}) onTransferOwnershipButtonClicked: openPopup(transferOwnershipPopup, {privateKey: chatsModel.communities.exportComumnity()})
onLeaveButtonClicked: chatsModel.communities.leaveCommunity(communityId) onLeaveButtonClicked: chatsModel.communities.leaveCommunity(popup.community.id)
}
}
Component {
id: transferOwnershipPopup
TransferOwnershipPopup {
anchors.centerIn: parent
onClosed: {
destroy()
}
} }
} }
@ -74,10 +81,9 @@ StatusModal {
id: membersList id: membersList
CommunityProfilePopupMembersList { CommunityProfilePopupMembersList {
width: stack.width width: stack.width
//% "Members" headerTitle: qsTr("Members")
headerTitle: qsTrId("members-label") headerSubtitle: popup.community.nbMembers.toString()
headerSubtitle: popup.nbMembers.toString() community: popup.community
members: chatsModel.communities.activeCommunity.members
onInviteButtonClicked: popup.contentComponent.push(inviteFriendsView) onInviteButtonClicked: popup.contentComponent.push(inviteFriendsView)
} }
} }
@ -86,8 +92,8 @@ StatusModal {
id: inviteFriendsView id: inviteFriendsView
CommunityProfilePopupInviteFriendsView { CommunityProfilePopupInviteFriendsView {
width: stack.width width: stack.width
//% "Invite friends" headerTitle: qsTr("Invite friends")
headerTitle: qsTrId("invite-friends") community: popup.community
contactListSearch.chatKey.text: "" contactListSearch.chatKey.text: ""
contactListSearch.pubKey: "" contactListSearch.pubKey: ""

View File

@ -15,10 +15,11 @@ Column {
property string headerTitle: "" property string headerTitle: ""
property var community
property alias contactListSearch: contactFieldAndList property alias contactListSearch: contactFieldAndList
function sendInvites(pubKeys) { function sendInvites(pubKeys) {
const error = chatsModel.communities.inviteUsersToCommunityById(popup.communityId, JSON.stringify(pubKeys)) const error = chatsModel.communities.inviteUsersToCommunityById(root.community.id, JSON.stringify(pubKeys))
if (error) { if (error) {
console.error('Error inviting', error) console.error('Error inviting', error)
contactFieldAndList.validationError = error contactFieldAndList.validationError = error
@ -29,14 +30,12 @@ Column {
} }
StatusDescriptionListItem { StatusDescriptionListItem {
//% "Share community" title: qsTr("Share community")
title: qsTrId("share-community") subTitle: `${Constants.communityLinkPrefix}${root.community.id.substring(0, 4)}...${root.community.id.substring(root.community.id.length -2)}`
subTitle: `${Constants.communityLinkPrefix}${communityId.substring(0, 4)}...${communityId.substring(communityId.length -2)}` tooltip.text: qsTr("Copy to clipboard")
//% "Copy to clipboard"
tooltip.text: qsTrId("copy-to-clipboard")
icon.name: "copy" icon.name: "copy"
iconButton.onClicked: { iconButton.onClicked: {
let link = `${Constants.communityLinkPrefix}${communityId}` let link = `${Constants.communityLinkPrefix}${root.community.id}`
chatsModel.copyToClipboard(link) chatsModel.copyToClipboard(link)
tooltip.visible = !tooltip.visible tooltip.visible = !tooltip.visible
} }

View File

@ -20,6 +20,7 @@ Item {
property string headerSubtitle: "" property string headerSubtitle: ""
property string headerImageSource: "" property string headerImageSource: ""
property alias members: memberList.model property alias members: memberList.model
property var community
signal inviteButtonClicked() signal inviteButtonClicked()
@ -43,9 +44,8 @@ Item {
StatusListItem { StatusListItem {
id: inviteButton id: inviteButton
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: isAdmin visible: root.community.admin || root.community.isAdmin
//% "Invite People" title: qsTr("Invite People")
title: qsTrId("invite-people")
icon.name: "share-ios" icon.name: "share-ios"
type: StatusListItem.Type.Secondary type: StatusListItem.Type.Secondary
sensor.onClicked: root.inviteButtonClicked() sensor.onClicked: root.inviteButtonClicked()
@ -61,9 +61,9 @@ Item {
id: memberRequestsButton id: memberRequestsButton
property int nbRequests: chatsModel.communities.activeCommunity.communityMembershipRequests.nbRequests property int nbRequests: root.community.communityMembershipRequests.nbRequests
width: parent.width - 32 width: parent.width - 32
visible: isAdmin && nbRequests > 0 visible: (root.community.isAdmin || root.community.admin) && nbRequests > 0
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
//% "Membership requests" //% "Membership requests"
@ -124,6 +124,7 @@ Item {
Repeater { Repeater {
id: memberList id: memberList
model: root.community.members
delegate: StatusListItem { delegate: StatusListItem {
id: memberItem id: memberItem
@ -177,7 +178,7 @@ Item {
} }
StatusMenuSeparator { StatusMenuSeparator {
visible: chatsModel.communities.activeCommunity.admin visible: root.community.admin
} }
StatusMenuItem { StatusMenuItem {
@ -186,7 +187,7 @@ Item {
icon.name: "arrow-right" icon.name: "arrow-right"
iconRotation: 180 iconRotation: 180
type: StatusMenuItem.Type.Danger type: StatusMenuItem.Type.Danger
enabled: chatsModel.communities.activeCommunity.admin enabled: root.community.admin
onTriggered: chatsModel.communities.removeUserFromCommunity(model.pubKey) onTriggered: chatsModel.communities.removeUserFromCommunity(model.pubKey)
} }
@ -195,8 +196,8 @@ Item {
text: qsTrId("ban") text: qsTrId("ban")
icon.name: "cancel" icon.name: "cancel"
type: StatusMenuItem.Type.Danger type: StatusMenuItem.Type.Danger
enabled: chatsModel.communities.activeCommunity.admin enabled: root.community.admin
onTriggered: chatsModel.communities.banUserFromCommunity(model.pubKey, chatsModel.communities.activeCommunity.id) onTriggered: chatsModel.communities.banUserFromCommunity(model.pubKey, root.community.id)
} }
} }
} }

View File

@ -15,7 +15,7 @@ Column {
property string headerTitle: "" property string headerTitle: ""
property string headerSubtitle: "" property string headerSubtitle: ""
property string headerImageSource: "" property string headerImageSource: ""
property string description: "" property var community
signal membersListButtonClicked() signal membersListButtonClicked()
signal notificationsButtonClicked(bool checked) signal notificationsButtonClicked(bool checked)
@ -33,7 +33,7 @@ Column {
anchors.right: parent.right anchors.right: parent.right
anchors.leftMargin: 16 anchors.leftMargin: 16
anchors.rightMargin: 16 anchors.rightMargin: 16
text: root.description text: root.community.description
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.directColor1 color: Theme.palette.directColor1
wrapMode: Text.Wrap wrapMode: Text.Wrap
@ -46,14 +46,12 @@ Column {
} }
StatusDescriptionListItem { StatusDescriptionListItem {
//% "Share community" title: qsTr("Share community")
title: qsTrId("share-community") subTitle: `${Constants.communityLinkPrefix}${root.community.id.substring(0, 4)}...${root.community.id.substring(root.community.id.length -2)}`
subTitle: `${Constants.communityLinkPrefix}${communityId.substring(0, 4)}...${communityId.substring(communityId.length -2)}` tooltip.text: qsTr("Copy to clipboard")
//% "Copy to clipboard"
tooltip.text: qsTrId("copy-to-clipboard")
icon.name: "copy" icon.name: "copy"
iconButton.onClicked: { iconButton.onClicked: {
let link = `${Constants.communityLinkPrefix}${communityId}` let link = `${Constants.communityLinkPrefix}${root.community.id}`
chatsModel.copyToClipboard(link) chatsModel.copyToClipboard(link)
tooltip.visible = !tooltip.visible tooltip.visible = !tooltip.visible
} }
@ -69,12 +67,12 @@ Column {
id: membersListItem id: membersListItem
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
property int nbRequests: chatsModel.communities.activeCommunity.communityMembershipRequests.nbRequests property int nbRequests: root.community.communityMembershipRequests.nbRequests
//% "Members" //% "Members"
title: qsTrId("members-label") title: qsTrId("members-label")
icon.name: "group-chat" icon.name: "group-chat"
label: nbMembers.toString() label: root.community.nbMembers.toString()
sensor.onClicked: root.membersListButtonClicked() sensor.onClicked: root.membersListButtonClicked()
components: [ components: [
@ -97,7 +95,7 @@ Column {
icon.name: "notification" icon.name: "notification"
components: [ components: [
StatusSwitch { StatusSwitch {
checked: !chatsModel.communities.activeCommunity.muted checked: !root.community.muted
onClicked: root.notificationsButtonClicked(checked) onClicked: root.notificationsButtonClicked(checked)
} }
] ]
@ -110,9 +108,8 @@ Column {
StatusListItem { StatusListItem {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: isAdmin visible: root.community.isAdmin || root.community.admin
//% "Edit community" title: qsTr("Edit community")
title: qsTrId("edit-community")
icon.name: "edit" icon.name: "edit"
type: StatusListItem.Type.Secondary type: StatusListItem.Type.Secondary
sensor.onClicked: root.editButtonClicked() sensor.onClicked: root.editButtonClicked()
@ -120,9 +117,8 @@ Column {
StatusListItem { StatusListItem {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: isAdmin visible: root.community.isAdmin || root.community.admin
//% "Transfer ownership" title: qsTr("Transfer ownership")
title: qsTrId("transfer-ownership")
icon.name: "exchange" icon.name: "exchange"
type: StatusListItem.Type.Secondary type: StatusListItem.Type.Secondary
sensor.onClicked: root.transferOwnershipButtonClicked() sensor.onClicked: root.transferOwnershipButtonClicked()
@ -143,7 +139,7 @@ Column {
//% "Roles" //% "Roles"
/* // TODO add this back when roles exist */ /* // TODO add this back when roles exist */
/* // Loader { */ /* // Loader { */
/* // active: isAdmin */ /* // active: root.community.isAdmin */
/* // width: parent.width */ /* // width: parent.width */
/* // sourceComponent: CommunityPopupButton { */ /* // sourceComponent: CommunityPopupButton { */
/* // label: qsTrId("community-roles") */ /* // label: qsTrId("community-roles") */

View File

@ -170,7 +170,9 @@ StatusAppLayout {
//% "View Community" //% "View Community"
text: qsTrId("view-community") text: qsTrId("view-community")
icon.name: "group-chat" icon.name: "group-chat"
onTriggered: openPopup(communityMembersPopup, {community: chatsModel.communities.observedCommunity}) onTriggered: openPopup(communityProfilePopup, {
community: chatsModel.communities.observedCommunity
})
} }
StatusMenuItem { StatusMenuItem {
@ -512,9 +514,12 @@ StatusAppLayout {
} }
Component { Component {
id: communityMembersPopup id: communityProfilePopup
CommunityMembersPopup {
CommunityProfilePopup {
id: communityProfilePopup
anchors.centerIn: parent anchors.centerIn: parent
onClosed: { onClosed: {
destroy() destroy()
} }