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:
Pascal Precht 2021-07-15 13:15:56 +02:00 committed by Iuri Matias
parent c0da840a87
commit 1a9d6d178c
7 changed files with 415 additions and 552 deletions

@ -1 +1 @@
Subproject commit 7136968b3ad50d6d222849d53c793ecf82566786 Subproject commit 58e8f1cd23e87572d57a886e65a31a27462cfb9c

View File

@ -272,6 +272,7 @@ Item {
CommunityProfilePopup { CommunityProfilePopup {
id: communityProfilePopup id: communityProfilePopup
anchors.centerIn: parent
communityId: chatsModel.communities.activeCommunity.id communityId: chatsModel.communities.activeCommunity.id
name: chatsModel.communities.activeCommunity.name name: chatsModel.communities.activeCommunity.name
description: chatsModel.communities.activeCommunity.description description: chatsModel.communities.activeCommunity.description

View File

@ -1,15 +1,12 @@
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 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 communityId: chatsModel.communities.activeCommunity.id
property string name: chatsModel.communities.activeCommunity.name property string name: chatsModel.communities.activeCommunity.name
property string description: chatsModel.communities.activeCommunity.description property string description: chatsModel.communities.activeCommunity.description
@ -18,136 +15,37 @@ ModalPopup {
property string communityColor: chatsModel.communities.activeCommunity.communityColor property string communityColor: chatsModel.communities.activeCommunity.communityColor
property int nbMembers: chatsModel.communities.activeCommunity.nbMembers property int nbMembers: chatsModel.communities.activeCommunity.nbMembers
property bool isAdmin: chatsModel.communities.activeCommunity.isAdmin property bool isAdmin: chatsModel.communities.activeCommunity.isAdmin
height: stack.currentItem.height + modalHeader.height + modalFooter.height + Style.current.padding * 3
id: popup id: popup
onClosed: { onClosed: {
while (stack.depth > 1) { while (contentComponent.depth > 1) {
stack.pop() contentComponent.pop()
} }
} }
header: Item { header.title: contentComponent.currentItem.headerTitle
id: modalHeader header.subTitle: contentComponent.currentItem.headerSubtitle || ""
height: childrenRect.height header.image.source: contentComponent.currentItem.headerImageSource || ""
width: parent.width
property string title: stack.currentItem.headerTitle content: StackView {
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 {
id: stack id: stack
initialItem: profileOverview initialItem: profileOverview
width: parent.width anchors.centerIn: parent
width: popup.width
height: currentItem.implicitHeight || currentItem.height
pushEnter: Transition { enabled: false } pushEnter: Transition { enabled: false }
pushExit: Transition { enabled: false } pushExit: Transition { enabled: false }
popEnter: Transition { enabled: false } popEnter: Transition { enabled: false }
popExit: 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 { Component {
id: profileOverview id: profileOverview
CommunityProfilePopupOverview { CommunityProfilePopupOverview {
property bool useLetterIdenticon: !!!popup.source width: stack.width
headerTitle: chatsModel.communities.activeCommunity.name headerTitle: chatsModel.communities.activeCommunity.name
headerDescription: { headerSubtitle: {
switch(access) { switch(access) {
//% "Public community" //% "Public community"
case Constants.communityChatPublicAccess: return qsTrId("public-community"); case Constants.communityChatPublicAccess: return qsTrId("public-community");
@ -161,37 +59,69 @@ ModalPopup {
} }
headerImageSource: chatsModel.communities.activeCommunity.thumbnailImage headerImageSource: chatsModel.communities.activeCommunity.thumbnailImage
description: chatsModel.communities.activeCommunity.description 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 { leftButtons: [
id: modalFooter
visible: stack.depth > 1
width: parent.width
height: modalFooter.visible ? btnBack.height : 0
StatusRoundButton { StatusRoundButton {
id: btnBack
anchors.left: parent.left
icon.name: "arrow-right" icon.name: "arrow-right"
icon.width: 20
icon.height: 16 icon.height: 16
icon.width: 20
rotation: 180 rotation: 180
type: globalSettings.theme === Universal.Dark ? "secondary" : "primary" visible: contentComponent.depth > 1
height: !visible ? 0 : implicitHeight
onClicked: { onClicked: {
stack.pop() contentComponent.pop()
} }
} }
]
rightButtons: [
StatusButton { StatusButton {
text: qsTr("Invite") text: qsTr("Invite")
anchors.right: parent.right visible: popup.contentComponent.depth > 2
enabled: stack.currentItem.contactListSearch !== undefined && stack.currentItem.contactListSearch.pubKeys.length > 0 height: !visible ? 0 : implicitHeight
enabled: popup.contentComponent.currentItem.contactListSearch !== undefined && popup.contentComponent.currentItem.contactListSearch.pubKeys.length > 0
onClicked: { onClicked: {
stack.currentItem.sendInvites(stack.currentItem.contactListSearch.pubKeys) popup.contentComponent.currentItem.sendInvites(popup.contentComponent.currentItem.contactListSearch.pubKeys)
stack.pop() popup.contentComponent.pop()
} }
} }
} ]
} }

View File

@ -7,17 +7,16 @@ import "../../../../imports"
import "../../../../shared" import "../../../../shared"
import "../../../../shared/status" import "../../../../shared/status"
Item { import StatusQ.Components 0.1
import StatusQ.Popups 0.1
Column {
id: root id: root
property string headerTitle: "" property string headerTitle: ""
property string headerDescription: ""
property string headerImageSource: ""
property alias contactListSearch: contactFieldAndList property alias contactListSearch: contactFieldAndList
height: 400
function sendInvites(pubKeys) { function sendInvites(pubKeys) {
const error = chatsModel.communities.inviteUsersToCommunityById(popup.communityId, JSON.stringify(pubKeys)) const error = chatsModel.communities.inviteUsersToCommunityById(popup.communityId, JSON.stringify(pubKeys))
if (error) { if (error) {
@ -28,31 +27,32 @@ Item {
contactFieldAndList.successMessage = qsTr("Invite successfully sent") contactFieldAndList.successMessage = qsTr("Invite successfully sent")
} }
TextWithLabel { StatusModalDivider {
id: shareCommunity bottomPadding: 8
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
} }
Separator { StatusDescriptionListItem {
id: sep title: qsTr("Share community")
anchors.left: parent.left subTitle: `${Constants.communityLinkPrefix}${communityId.substring(0, 4)}...${communityId.substring(communityId.length -2)}`
anchors.right: parent.right tooltip.text: qsTr("Copy to clipboard")
anchors.top: shareCommunity.bottom icon.name: "copy"
anchors.topMargin: Style.current.smallPadding iconButton.onClicked: {
anchors.leftMargin: -Style.current.padding let link = `${Constants.communityLinkPrefix}${communityId}`
anchors.rightMargin: -Style.current.padding chatsModel.copyToClipboard(link)
tooltip.visible = !tooltip.visible
}
width: parent.width
}
StatusModalDivider {
bottomPadding: 16
} }
ContactsListAndSearch { ContactsListAndSearch {
id: contactFieldAndList id: contactFieldAndList
anchors.top: sep.bottom
anchors.topMargin: Style.current.smallPadding anchors.topMargin: Style.current.smallPadding
width: parent.width anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - 32
showCheckbox: true showCheckbox: true
hideCommunityMembers: true hideCommunityMembers: true
} }

View File

@ -1,206 +1,205 @@
import QtQuick 2.13 import QtQuick 2.13
import QtQuick.Controls 2.13 import QtQuick.Controls 2.13
import QtQuick.Layouts 1.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 "../../../../imports"
import "../../../../shared" import "../../../../shared"
import "../../../../shared/status"
import "./"
import "../components"
Item { Item {
id: root
height: childrenRect.height
implicitWidth: 480
property string headerTitle: "" property string headerTitle: ""
property string headerDescription: "" property string headerSubtitle: ""
property string headerImageSource: "" property string headerImageSource: ""
property alias members: memberList.model property alias members: memberList.model
height: 450
CommunityPopupButton { signal inviteButtonClicked()
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
}
Separator { Column {
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
}
StatusSettingsLineButton { id: memberSearchAndInviteButton
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()
}
Separator { StatusModalDivider {}
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 { Item {
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
width: parent.width width: parent.width
height: 64 height: 76
radius: Style.current.radius
color: isHovered ? Style.current.backgroundHover : Style.current.transparent
property bool isHovered: false Input {
property string nickname: appMain.getUserNickname(model.pubKey) id: memberSearch
width: parent.width - 32
StatusImageIdenticon { anchors.centerIn: parent
id: identicon placeholderText: qsTr("Member name")
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter
source: model.identicon
} }
}
StyledText { StatusListItem {
id: txtUsername id: inviteButton
text: !model.userName.endsWith(".eth") && !!contactRow.nickname ? anchors.horizontalCenter: parent.horizontalCenter
contactRow.nickname : Utils.removeStatusEns(model.userName) visible: isAdmin
anchors.left: identicon.right title: qsTr("Invite People")
anchors.leftMargin: Style.current.smallPadding icon.name: "share-ios"
anchors.verticalCenter: parent.verticalCenter 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 font.pixelSize: 15
color: Theme.palette.baseColor1
} }
StyledText { }
text: " (" + qsTr("You") + ")"
visible: !moreActionsBtn.visible Item {
anchors.left: txtUsername.right width: parent.width
anchors.leftMargin: Style.current.smallPadding height: 300
anchors.right: parent.right visible: !!memberSearch.text && !!memberList.count && !memberListColumn.height
anchors.rightMargin: Style.current.smallPadding
anchors.verticalCenter: parent.verticalCenter StatusBaseText {
color: Style.current.secondaryText anchors.centerIn: parent
text: qsTr("No contacts found")
font.pixelSize: 15 font.pixelSize: 15
color: Theme.palette.baseColor1
} }
}
MouseArea { Column {
cursorShape: Qt.PointingHandCursor id: memberListColumn
anchors.fill: parent width: parent.width
hoverEnabled: true visible: memberList.count > 0 || height > 0
onEntered: contactRow.isHovered = true anchors.horizontalCenter: parent.horizontalCenter
onExited: contactRow.isHovered = false
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: openProfilePopup(model.userName, model.pubKey, model.identicon, '', contactRow.nickname)
}
StatusContextMenuButton { Repeater {
id: moreActionsBtn id: memberList
anchors.right: parent.right delegate: StatusListItem {
anchors.rightMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter id: memberItem
visible: model.pubKey.toLowerCase() !== profileModel.profile.pubKey.toLowerCase()
MouseArea { property string nickname: appMain.getUserNickname(model.pubKey)
anchors.fill: parent property string profileImage: appMain.getProfileImage(model.pubKey)
onClicked: contextMenu.popup(-contextMenu.width + moreActionsBtn.width, moreActionsBtn.height + 4)
hoverEnabled: true visible: !!!memberSearch.text ||
cursorShape: Qt.PointingHandCursor model.userName.toLowerCase().includes(memberSearch.text.toLowerCase()) ||
onExited: { nickname.toLowerCase().includes(memberSearch.text.toLowerCase())
contactRow.isHovered = false anchors.horizontalCenter: parent.horizontalCenter
moreActionsBtn.highlighted = false
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 components: [
moreActionsBtn.highlighted = true StatusFlatRoundButton {
} id: menuButton
PopupMenu { width: 32
id: contextMenu height: 32
Action { visible: model.pubKey.toLowerCase() !== profileModel.profile.pubKey.toLowerCase()
icon.source: "../../../img/communities/menu/view-profile.svg" icon.name: "more"
icon.width: 16 type: StatusFlatRoundButton.Type.Secondary
icon.height: 16 onClicked: {
//% "View Profile" highlighted = true
text: qsTrId("view-profile") communityMemberContextMenu.popup(-communityMemberContextMenu.width+menuButton.width, menuButton.height + 4)
onTriggered: openProfilePopup(model.userName, model.pubKey, model.identicon, '', contactRow.nickname) }
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
}
} }

View File

@ -1,236 +1,166 @@
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.13 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 id: root
property string headerTitle: "" property string headerTitle: ""
property string headerDescription: "" property string headerSubtitle: ""
property string headerImageSource: "" property string headerImageSource: ""
property string description: "" property string description: ""
width: parent.width signal membersListButtonClicked()
height: childrenRect.height signal notificationsButtonClicked(bool checked)
signal editButtonClicked()
signal transferOwnershipButtonClicked()
signal leaveButtonClicked()
StyledText { StatusModalDivider {
id: descriptionText bottomPadding: 8
text: root.description }
wrapMode: Text.Wrap
Item {
height: 46
width: parent.width width: parent.width
font.pixelSize: 15 StatusBaseText {
} id: communityDescription
anchors.verticalCenter: parent.verticalCenter
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 {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: -Style.current.padding anchors.leftMargin: 16
anchors.leftMargin: -Style.current.padding anchors.rightMargin: 16
} text: root.description
font.pixelSize: 15
Item { color: Theme.palette.directColor1
id: spacer2 wrapMode: Text.Wrap
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)
} }
} }
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 */
/* // } */
/* // } */
/* // } */
/* // } */
} }

View File

@ -492,6 +492,7 @@ StatusAppLayout {
Component { Component {
id: inviteFriendsToCommunityPopup id: inviteFriendsToCommunityPopup
InviteFriendsToCommunityPopup { InviteFriendsToCommunityPopup {
anchors.centerIn: parent
onClosed: { onClosed: {
destroy() destroy()
} }
@ -501,6 +502,7 @@ StatusAppLayout {
Component { Component {
id: communityMembersPopup id: communityMembersPopup
CommunityMembersPopup { CommunityMembersPopup {
anchors.centerIn: parent
onClosed: { onClosed: {
destroy() destroy()
} }
@ -510,6 +512,7 @@ StatusAppLayout {
Component { Component {
id: editCommunityPopup id: editCommunityPopup
CreateCommunityPopup { CreateCommunityPopup {
anchors.centerIn: parent
isEdit: true isEdit: true
onClosed: { onClosed: {
destroy() destroy()