From 92d042184a5a1fe53cca64915fa75fc7d738fb54 Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Mon, 19 Jul 2021 14:25:52 +0200 Subject: [PATCH] refactor(Communities): use `StatusModal` in `CommunityDetailPopup` Closes #2892 --- .../CommunityDetailPopup.qml | 313 +++++++----------- ui/app/AppLayouts/Chat/ContactsColumn.qml | 1 + .../Chat/ContactsColumn/Channel.qml | 209 ------------ 3 files changed, 126 insertions(+), 397 deletions(-) delete mode 100644 ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml diff --git a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityDetailPopup.qml b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityDetailPopup.qml index c1d7953da8..360bf0b88e 100644 --- a/ui/app/AppLayouts/Chat/CommunityComponents/CommunityDetailPopup.qml +++ b/ui/app/AppLayouts/Chat/CommunityComponents/CommunityDetailPopup.qml @@ -1,11 +1,17 @@ import QtQuick 2.12 +import QtQuick.Controls 2.3 import QtQuick.Dialogs 1.3 + +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 "../ContactsColumn" -ModalPopup { +StatusModal { property QtObject community: chatsModel.communities.observedCommunity property string communityId: community.id property string name: community.name @@ -21,221 +27,154 @@ ModalPopup { id: popup - header: Item { - height: childrenRect.height - width: parent.width - - - Loader { - id: communityImg - sourceComponent: !!popup.source ? commmunityImgCmp : letterIdenticonCmp + header.title: name + header.subTitle: { + let subTitle = "" + switch(access) { + case Constants.communityChatPublicAccess: + subTitle = qsTr("Public community"); + break; + case Constants.communityChatInvitationOnlyAccess: + subTitle = qsTr("Invitation only community"); + break; + case Constants.communityChatOnRequestAccess: + subTitle = qsTr("On request community"); + break; + default: + subTitle = qsTrId("Unknown community"); + break; } + if (ensOnly) { + subTitle += qsTr(" - ENS only") + } + return subTitle + } - Component { - id: commmunityImgCmp - RoundedImage { - source: popup.source - width: 40 - height: 40 + content: Column { + width: popup.width + + Item { + height: childrenRect.height + 8 + width: parent.width - 32 + anchors.horizontalCenter: parent.horizontalCenter + + StatusBaseText { + id: description + anchors.top: parent.top + anchors.topMargin: 16 + text: popup.description + font.pixelSize: 15 + color: Theme.palette.directColor1 + wrapMode: Text.WordWrap + } + + StatusIcon { + id: statusIcon + anchors.top: description.bottom + anchors.topMargin: 16 + anchors.left: parent.left + icon: "tiny/contact" + width: 16 + color: Theme.palette.directColor1 + } + + StatusBaseText { + text: qsTr("%1 members").arg(nbMembers) + font.pixelSize: 15 + font.weight: Font.Medium + color: Theme.palette.directColor1 + anchors.left: statusIcon.right + anchors.leftMargin: 2 + anchors.verticalCenter: statusIcon.verticalCenter } } - Component { - id: letterIdenticonCmp - StatusLetterIdenticon { - width: 40 - height: 40 - chatName: popup.name - color: popup.communityColor + StatusModalDivider { + topPadding: 8 + bottomPadding: 8 + } + + Item { + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width - 32 + height: 34 + StatusBaseText { + text: qsTr("Channels") + anchors.bottom: parent.bottom + anchors.bottomMargin: 4 + font.pixelSize: 15 + color: Theme.palette.baseColor1 } } - StyledTextEdit { - id: communityName - text: popup.name - anchors.top: parent.top - anchors.topMargin: 2 - anchors.left: communityImg.right - anchors.leftMargin: Style.current.smallPadding - font.bold: true - font.pixelSize: 17 - readOnly: true - } - - StyledText { - id: accessText - text: { - switch(access) { - //% "Public community" - case Constants.communityChatPublicAccess: return qsTrId("public-community"); - //% "Invitation only community" - case Constants.communityChatInvitationOnlyAccess: return qsTrId("invitation-only-community"); - //% "On request community" - case Constants.communityChatOnRequestAccess: return qsTrId("on-request-community"); - //% "Unknown community" - default: return qsTrId("unknown-community"); + ScrollView { + width: popup.width + height: 300 + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + clip: true + ListView { + id: chatList + anchors.fill: parent + clip: true + model: community.chats + boundsBehavior: Flickable.StopAtBounds + delegate: StatusListItem { + anchors.horizontalCenter: parent.horizontalCenter + title: "#" + model.name + subTitle: model.description + icon.isLetterIdenticon: true + icon.background.color: popup.communityColor } } - anchors.left: communityName.left - anchors.top: communityName.bottom - anchors.topMargin: 2 - font.pixelSize: 15 - font.weight: Font.Thin - color: Style.current.secondaryText - } - - StyledText { - visible: popup.ensOnly - //% " - ENS Only" - text: qsTrId("---ens-only") - anchors.left: accessText.right - anchors.verticalCenter: accessText.verticalCenter - anchors.topMargin: 2 - font.pixelSize: 15 - font.weight: Font.Thin - color: Style.current.secondaryText - } - } - - StyledText { - id: descriptionText - text: popup.description - wrapMode: Text.Wrap - width: parent.width - font.pixelSize: 15 - font.weight: Font.Thin - } - - Item { - id: memberContainer - width: parent.width - height: memberImage.height - anchors.top: descriptionText.bottom - anchors.topMargin: Style.current.padding - - SVGImage { - id: memberImage - source: "../../../img/member.svg" - width: 16 - height: 16 - } - - - StyledText { - text: nbMembers === 1 ? - //% "1 member" - qsTrId("1-member") : - //% "%1 members" - qsTrId("-1-members").arg(popup.nbMembers) - wrapMode: Text.WrapAnywhere - width: parent.width - anchors.left: memberImage.right - anchors.leftMargin: 4 - font.pixelSize: 15 - font.weight: Font.Medium } } - Separator { - id: sep1 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: memberContainer.bottom - anchors.topMargin: Style.current.smallPadding - anchors.leftMargin: -Style.current.padding - anchors.rightMargin: -Style.current.padding - } - - StyledText { - id: chatsTitle - //% "Chats" - text: qsTrId("chats") - anchors.top: sep1.bottom - anchors.topMargin: Style.current.bigPadding - font.pixelSize: 15 - font.weight: Font.Thin - } - - - ListView { - id: chatsList - width: parent.width - anchors.top: chatsTitle.bottom - anchors.topMargin: 4 - anchors.bottom: parent.bottom - clip: true - model: community.chats - boundsBehavior: Flickable.StopAtBounds - delegate: Channel { - id: channelItem - unviewedMessagesCount: "" - width: parent.width - name: model.name - lastMessage: model.description - contentType: Constants.messageType - color: Style.current.transparent - enableMouseArea: false - } - } - - footer: Item { - width: parent.width - height: backButton.height - - StatusIconButton { + leftButtons: [ + StatusRoundButton { id: backButton - icon.name: "leave_chat" - width: 44 - height: 44 - iconColor: Style.current.primary - highlighted: true - icon.color: Style.current.primary - icon.width: 28 - icon.height: 28 - radius: width / 2 + icon.name: "arrow-right" + icon.height: 16 + icon.width: 20 + rotation: 180 onClicked: { openPopup(communitiesPopupComponent) popup.close() } } + ] + rightButtons: [ StatusButton { property bool isPendingRequest: { if (access !== Constants.communityChatOnRequestAccess) { return false } - return chatsModel.communities.isCommunityRequestPending(communityId) + return chatsModel.communities.isCommunityRequestPending(popup.communityId) } text: { - if (ensOnly && !profileModel.profile.ensVerified) { - //% "Membership requires an ENS username" - return qsTrId("membership-requires-an-ens-username") + if (popup.ensOnly && !profileModel.profile.ensVerified) { + return qsTr("Membership requires an ENS username") } - if (canJoin) { - //% "Join ‘%1’" - return qsTrId("join---1-").arg(popup.name); + if (popup.canJoin) { + return qsTr("Join ‘%1’").arg(popup.name); } if (isPendingRequest) { //% "Pending" return qsTrId("invite-chat-pending") } - switch(access) { - //% "Join ‘%1’" - case Constants.communityChatPublicAccess: return qsTrId("join---1-").arg(popup.name); - //% "You need to be invited" - case Constants.communityChatInvitationOnlyAccess: return qsTrId("you-need-to-be-invited"); - //% "Request to join ‘%1’" - case Constants.communityChatOnRequestAccess: return qsTrId("request-to-join---1-").arg(popup.name); - //% "Unknown community" - default: return qsTrId("unknown-community"); + switch(popup.access) { + case Constants.communityChatPublicAccess: return qsTr("Join ‘%1’").arg(popup.name); + case Constants.communityChatInvitationOnlyAccess: return qsTr("You need to be invited"); + case Constants.communityChatOnRequestAccess: return qsTr("Request to join ‘%1’").arg(popup.name); + default: return qsTr("Unknown community"); } } enabled: { - if (ensOnly && !profileModel.profile.ensVerified) { + if (popup.ensOnly && !profileModel.profile.ensVerified) { return false } - if (access === Constants.communityChatInvitationOnlyAccess || isPendingRequest) { + if (popup.access === Constants.communityChatInvitationOnlyAccess || isPendingRequest) { return false } if (canJoin) { @@ -243,8 +182,6 @@ ModalPopup { } return true } - - anchors.right: parent.right onClicked: { let error if (access === Constants.communityChatOnRequestAccess && !popup.isMember) { @@ -267,14 +204,14 @@ ModalPopup { popup.close() } } + ] - MessageDialog { - id: joiningError - //% "Error joining the community" - title: qsTrId("error-joining-the-community") - icon: StandardIcon.Critical - standardButtons: StandardButton.Ok - } + MessageDialog { + id: joiningError + //% "Error joining the community" + title: qsTrId("error-joining-the-community") + icon: StandardIcon.Critical + standardButtons: StandardButton.Ok } } diff --git a/ui/app/AppLayouts/Chat/ContactsColumn.qml b/ui/app/AppLayouts/Chat/ContactsColumn.qml index 283fdc89b0..5e713ee5f9 100644 --- a/ui/app/AppLayouts/Chat/ContactsColumn.qml +++ b/ui/app/AppLayouts/Chat/ContactsColumn.qml @@ -230,6 +230,7 @@ Item { Component { id: communityDetailPopup CommunityDetailPopup { + anchors.centerIn: parent onClosed: { destroy() } diff --git a/ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml b/ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml deleted file mode 100644 index 61c2dc2bdb..0000000000 --- a/ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml +++ /dev/null @@ -1,209 +0,0 @@ -import QtQuick 2.13 -import QtQuick.Controls 2.13 -import "../../../../shared" -import "../../../../shared/status" -import "../../../../imports" -import "../components" - -Item { - property string chatId: "" - property string categoryId: "" - property string name: "channelName" - property string lastMessage: "My latest message\n with a return" - property string timestamp: "1605212622434" - property string unviewedMessagesCount: "2" - property string identicon - property int mentionsCount: 0 - property int chatType: Constants.chatTypePublic - property int realChatType: { - if (chatType === Constants.chatTypeCommunity) { - // TODO add a check for private community chats once it is created - return Constants.chatTypePublic - } - return chatType - } - - property string filterCategory: "" - property string searchStr: "" - property bool isCompact: appSettings.useCompactMode - property int contentType: 1 - property bool muted: false - property bool hovered: false - property bool enableMouseArea: true - property color color: { - if (ListView.isCurrentItem) { - return Style.current.menuBackgroundActive - } - if (wrapper.hovered) { - return Style.current.menuBackgroundHover - } - return Style.current.transparent - } - - property string profileImage: realChatType === Constants.chatTypeOneToOne ? appMain.getProfileImage(chatId) || "" : "" - - // Hide the box if it is filtered out - property bool isVisible: categoryId === filterCategory && (searchStr === "" || name.includes(searchStr)) - - id: wrapper - anchors.right: parent.right - anchors.top: applicationWindow.top - anchors.left: parent.left - visible: isVisible ? true : false - height: isVisible ? rectangle.height + (isCompact ? 4 : Style.current.halfPadding) : 0 - - Rectangle { - Connections { - enabled: realChatType === Constants.chatTypeOneToOne - target: profileModel.contacts.list - onContactChanged: { - if (pubkey === wrapper.chatId) { - wrapper.profileImage = appMain.getProfileImage(wrapper.chatId) - } - } - } - - id: rectangle - color: wrapper.color - radius: 8 - height: !isCompact ? 64 : 40 - width: parent.width - - StatusIdenticon { - id: contactImage - height: !isCompact ? 40 : 28 - width: !isCompact ? 40 : 28 - chatId: wrapper.chatId - chatName: wrapper.name - chatType: wrapper.realChatType - identicon: wrapper.profileImage || wrapper.identicon - anchors.left: parent.left - anchors.leftMargin: !isCompact ? Style.current.padding : Style.current.smallPadding - anchors.verticalCenter: parent.verticalCenter - } - - SVGImage { - id: channelIcon - width: 16 - height: 16 - fillMode: Image.PreserveAspectFit - source: "../../../img/channel-icon-" + (wrapper.realChatType === Constants.chatTypePublic ? "public-chat.svg" : "group.svg") - anchors.left: contactImage.right - anchors.leftMargin: !isCompact ? Style.current.padding : Style.current.smallPadding - anchors.top: !isCompact ? parent.top : undefined - anchors.topMargin: !isCompact ? Style.current.smallPadding : 0 - anchors.verticalCenter: !isCompact ? undefined : parent.verticalCenter - visible: wrapper.realChatType !== Constants.chatTypeOneToOne - } - - StyledText { - id: contactInfo - text: wrapper.realChatType !== Constants.chatTypePublic ? - Emoji.parse(Utils.removeStatusEns(Utils.filterXSS(wrapper.name))) : - "#" + Utils.filterXSS(wrapper.name) - anchors.right: contactTime.visible ? contactTime.left : parent.right - anchors.rightMargin: Style.current.smallPadding - elide: Text.ElideRight - color: muted ? Style.current.secondaryText : Style.current.textColor - font.weight: Font.Medium - font.pixelSize: 15 - anchors.left: channelIcon.visible ? channelIcon.right : contactImage.right - anchors.leftMargin: channelIcon.visible ? 2 : - (!isCompact ? Style.current.padding : Style.current.halfPadding) - anchors.top: !isCompact ? parent.top : undefined - anchors.topMargin: !isCompact ? Style.current.smallPadding : 0 - anchors.verticalCenter: !isCompact ? undefined : parent.verticalCenter - } - - StyledText { - id: lastChatMessage - visible: !isCompact - text: { - switch(contentType){ - //% "Image" - case Constants.imageType: return qsTrId("image"); - //% "Sticker" - case Constants.stickerType: return qsTrId("sticker"); - //% "No messages" - default: return lastMessage ? Emoji.parse(Utils.filterXSS(lastMessage)).replace(/\n|\r/g, ' ') : qsTrId("no-messages") - } - } - textFormat: Text.RichText - clip: true // This is needed because emojis don't ellide correctly - anchors.right: contactNumberChatsCircle.left - anchors.rightMargin: Style.current.smallPadding - elide: Text.ElideRight - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.smallPadding - font.pixelSize: 15 - anchors.left: contactImage.right - anchors.leftMargin: Style.current.padding - color: Style.current.secondaryText - } - - StyledText { - id: contactTime - visible: !isCompact - text: Utils.formatDateTime(wrapper.timestamp, globalSettings.locale) - anchors.right: parent.right - anchors.rightMargin: Style.current.padding - anchors.top: parent.top - anchors.topMargin: Style.current.smallPadding - font.pixelSize: 11 - color: Style.current.secondaryText - } - Rectangle { - id: contactNumberChatsCircle - width: 22 - height: 22 - radius: 50 - anchors.right: parent.right - anchors.rightMargin: !isCompact ? Style.current.padding : Style.current.smallPadding - anchors.bottom: !isCompact ? parent.bottom : undefined - anchors.bottomMargin: !isCompact ? Style.current.smallPadding : 0 - anchors.verticalCenter: !isCompact ? undefined : parent.verticalCenter - color: Style.current.blue - visible: (unviewedMessagesCount > 0) || wrapper.mentionsCount > 0 - StyledText { - id: contactNumberChats - text: wrapper.mentionsCount > 0 ? '@' : (wrapper.unviewedMessagesCount < 100 ? wrapper.unviewedMessagesCount : "99+") - font.pixelSize: 12 - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - color: Style.current.white - } - } - - MouseArea { - enabled: enableMouseArea - cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - acceptedButtons: Qt.LeftButton | Qt.RightButton - anchors.fill: parent - hoverEnabled: true - onEntered: { - wrapper.hovered = true - } - onExited: { - wrapper.hovered = false - } - onClicked: { - if (mouse.button & Qt.RightButton) { - chatsModel.channelView.setContextChannel(chatId) - channelContextMenu.openMenu(chatsModel.channelView.contextChannel, index) - return; - } - chatGroupsListView.currentIndex = index - chatsModel.channelView.setActiveChannelByIndex(index) - } - } - - } -} - - - -/*##^## -Designer { - D{i:0;formeditorColor:"#ffffff";height:64;width:640} -} -##^##*/