refactor(Communities): use `StatusModal` in `CommunityDetailPopup`

Closes #2892
This commit is contained in:
Pascal Precht 2021-07-19 14:25:52 +02:00 committed by Iuri Matias
parent 4b059f6190
commit 92d042184a
3 changed files with 126 additions and 397 deletions

View File

@ -1,11 +1,17 @@
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Dialogs 1.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 "../../../../imports"
import "../../../../shared" import "../../../../shared"
import "../../../../shared/status"
import "../ContactsColumn"
ModalPopup { StatusModal {
property QtObject community: chatsModel.communities.observedCommunity property QtObject community: chatsModel.communities.observedCommunity
property string communityId: community.id property string communityId: community.id
property string name: community.name property string name: community.name
@ -21,221 +27,154 @@ ModalPopup {
id: popup id: popup
header: Item { header.title: name
height: childrenRect.height header.subTitle: {
width: parent.width let subTitle = ""
switch(access) {
case Constants.communityChatPublicAccess:
Loader { subTitle = qsTr("Public community");
id: communityImg break;
sourceComponent: !!popup.source ? commmunityImgCmp : letterIdenticonCmp 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 { content: Column {
id: commmunityImgCmp width: popup.width
RoundedImage {
source: popup.source Item {
width: 40 height: childrenRect.height + 8
height: 40 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 { StatusModalDivider {
id: letterIdenticonCmp topPadding: 8
StatusLetterIdenticon { bottomPadding: 8
width: 40 }
height: 40
chatName: popup.name Item {
color: popup.communityColor 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 { ScrollView {
id: communityName width: popup.width
text: popup.name height: 300
anchors.top: parent.top ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
anchors.topMargin: 2 clip: true
anchors.left: communityImg.right ListView {
anchors.leftMargin: Style.current.smallPadding id: chatList
font.bold: true anchors.fill: parent
font.pixelSize: 17 clip: true
readOnly: true model: community.chats
} boundsBehavior: Flickable.StopAtBounds
delegate: StatusListItem {
StyledText { anchors.horizontalCenter: parent.horizontalCenter
id: accessText title: "#" + model.name
text: { subTitle: model.description
switch(access) { icon.isLetterIdenticon: true
//% "Public community" icon.background.color: popup.communityColor
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");
} }
} }
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 { leftButtons: [
id: sep1 StatusRoundButton {
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 {
id: backButton id: backButton
icon.name: "leave_chat" icon.name: "arrow-right"
width: 44 icon.height: 16
height: 44 icon.width: 20
iconColor: Style.current.primary rotation: 180
highlighted: true
icon.color: Style.current.primary
icon.width: 28
icon.height: 28
radius: width / 2
onClicked: { onClicked: {
openPopup(communitiesPopupComponent) openPopup(communitiesPopupComponent)
popup.close() popup.close()
} }
} }
]
rightButtons: [
StatusButton { StatusButton {
property bool isPendingRequest: { property bool isPendingRequest: {
if (access !== Constants.communityChatOnRequestAccess) { if (access !== Constants.communityChatOnRequestAccess) {
return false return false
} }
return chatsModel.communities.isCommunityRequestPending(communityId) return chatsModel.communities.isCommunityRequestPending(popup.communityId)
} }
text: { text: {
if (ensOnly && !profileModel.profile.ensVerified) { if (popup.ensOnly && !profileModel.profile.ensVerified) {
//% "Membership requires an ENS username" return qsTr("Membership requires an ENS username")
return qsTrId("membership-requires-an-ens-username")
} }
if (canJoin) { if (popup.canJoin) {
//% "Join %1" return qsTr("Join %1").arg(popup.name);
return qsTrId("join---1-").arg(popup.name);
} }
if (isPendingRequest) { if (isPendingRequest) {
//% "Pending" //% "Pending"
return qsTrId("invite-chat-pending") return qsTrId("invite-chat-pending")
} }
switch(access) { switch(popup.access) {
//% "Join %1" case Constants.communityChatPublicAccess: return qsTr("Join %1").arg(popup.name);
case Constants.communityChatPublicAccess: return qsTrId("join---1-").arg(popup.name); case Constants.communityChatInvitationOnlyAccess: return qsTr("You need to be invited");
//% "You need to be invited" case Constants.communityChatOnRequestAccess: return qsTr("Request to join %1").arg(popup.name);
case Constants.communityChatInvitationOnlyAccess: return qsTrId("you-need-to-be-invited"); default: return qsTr("Unknown community");
//% "Request to join %1"
case Constants.communityChatOnRequestAccess: return qsTrId("request-to-join---1-").arg(popup.name);
//% "Unknown community"
default: return qsTrId("unknown-community");
} }
} }
enabled: { enabled: {
if (ensOnly && !profileModel.profile.ensVerified) { if (popup.ensOnly && !profileModel.profile.ensVerified) {
return false return false
} }
if (access === Constants.communityChatInvitationOnlyAccess || isPendingRequest) { if (popup.access === Constants.communityChatInvitationOnlyAccess || isPendingRequest) {
return false return false
} }
if (canJoin) { if (canJoin) {
@ -243,8 +182,6 @@ ModalPopup {
} }
return true return true
} }
anchors.right: parent.right
onClicked: { onClicked: {
let error let error
if (access === Constants.communityChatOnRequestAccess && !popup.isMember) { if (access === Constants.communityChatOnRequestAccess && !popup.isMember) {
@ -267,14 +204,14 @@ ModalPopup {
popup.close() popup.close()
} }
} }
]
MessageDialog { MessageDialog {
id: joiningError id: joiningError
//% "Error joining the community" //% "Error joining the community"
title: qsTrId("error-joining-the-community") title: qsTrId("error-joining-the-community")
icon: StandardIcon.Critical icon: StandardIcon.Critical
standardButtons: StandardButton.Ok standardButtons: StandardButton.Ok
}
} }
} }

View File

@ -230,6 +230,7 @@ Item {
Component { Component {
id: communityDetailPopup id: communityDetailPopup
CommunityDetailPopup { CommunityDetailPopup {
anchors.centerIn: parent
onClosed: { onClosed: {
destroy() destroy()
} }

View File

@ -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}
}
##^##*/