diff --git a/ui/StatusQ b/ui/StatusQ index 7136968b3a..58e8f1cd23 160000 --- a/ui/StatusQ +++ b/ui/StatusQ @@ -1 +1 @@ -Subproject commit 7136968b3ad50d6d222849d53c793ecf82566786 +Subproject commit 58e8f1cd23e87572d57a886e65a31a27462cfb9c diff --git a/ui/app/AppLayouts/Chat/CommunityColumn.qml b/ui/app/AppLayouts/Chat/CommunityColumn.qml index df6fbdf45a..c7b4a6a531 100644 --- a/ui/app/AppLayouts/Chat/CommunityColumn.qml +++ b/ui/app/AppLayouts/Chat/CommunityColumn.qml @@ -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 diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopup.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopup.qml index 83c62412d4..df9b9bb4c6 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopup.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopup.qml @@ -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() } } - } + ] } diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupInviteFriendsView.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupInviteFriendsView.qml index 16e56885af..20bd81ff73 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupInviteFriendsView.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupInviteFriendsView.qml @@ -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 } diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupMembersList.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupMembersList.qml index e5e3aa398c..182107618e 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupMembersList.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupMembersList.qml @@ -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 + } } diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupOverview.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupOverview.qml index f4a08adc4b..16dafd2f4f 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupOverview.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityProfilePopupOverview.qml @@ -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 */ +/* // } */ +/* // } */ +/* // } */ +/* // } */ } diff --git a/ui/app/AppMain.qml b/ui/app/AppMain.qml index ed865bc699..07519d47ef 100644 --- a/ui/app/AppMain.qml +++ b/ui/app/AppMain.qml @@ -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()