fix: community context menu should not say "Leave community" if not joined

- differentiate between "Close" and "Leave" a community where the former
applies to spectated communities
- move the "leave community" confirmation popup to a shared place
(Popups.qml), extend it with the outro message and reuse it everywhere
- don't let admins leave a community
- some minor cleanups and dead code removals

Fixes #10963
This commit is contained in:
Lukáš Tinkl 2023-06-14 10:42:52 +02:00 committed by Lukáš Tinkl
parent 60d14180cf
commit 7bf7f272f3
10 changed files with 115 additions and 133 deletions

View File

@ -42,6 +42,7 @@ StackLayout {
id: joinCommunityView id: joinCommunityView
readonly property var communityData: sectionItemModel readonly property var communityData: sectionItemModel
name: communityData.name name: communityData.name
introMessage: communityData.introMessage
communityDesc: communityData.description communityDesc: communityData.description
color: communityData.color color: communityData.color
image: communityData.image image: communityData.image
@ -62,13 +63,19 @@ StackLayout {
loginType: root.rootStore.loginType loginType: root.rootStore.loginType
onNotificationButtonClicked: Global.openActivityCenterPopup() onNotificationButtonClicked: Global.openActivityCenterPopup()
onAdHocChatButtonClicked: rootStore.openCloseCreateChatView() onAdHocChatButtonClicked: rootStore.openCloseCreateChatView()
onRevealAddressClicked: { onRevealAddressClicked: openJoinCommunityDialog()
communityIntroDialog.open()
}
onInvitationPendingClicked: { onInvitationPendingClicked: {
root.rootStore.cancelPendingRequest(communityData.id) root.rootStore.cancelPendingRequest(communityData.id)
joinCommunityView.isInvitationPending = root.rootStore.isCommunityRequestPending(communityData.id) joinCommunityView.isInvitationPending = root.rootStore.isCommunityRequestPending(communityData.id)
} }
onJoined: {
root.rootStore.requestToJoinCommunityWithAuthentication(communityData.id, root.rootStore.userProfileInst.name)
}
onCancelMembershipRequest: {
root.rootStore.cancelPendingRequest(communityData.id)
joinCommunityView.isInvitationPending = root.rootStore.isCommunityRequestPending(communityData.id)
}
Connections { Connections {
target: root.rootStore.communitiesModuleInst target: root.rootStore.communitiesModuleInst
@ -78,28 +85,7 @@ StackLayout {
} }
} }
} }
CommunityIntroDialog {
id: communityIntroDialog
isInvitationPending: joinCommunityView.isInvitationPending
name: communityData.name
introMessage: communityData.introMessage
imageSrc: communityData.image
accessType: communityData.access
onJoined: {
root.rootStore.requestToJoinCommunityWithAuthentication(communityData.id, root.rootStore.userProfileInst.name)
} }
onCancelMembershipRequest: {
root.rootStore.cancelPendingRequest(communityData.id)
joinCommunityView.isInvitationPending = root.rootStore.isCommunityRequestPending(communityData.id)
}
}
}
} }
Component { Component {

View File

@ -73,8 +73,9 @@ Column {
StatusListItem { StatusListItem {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
title: qsTr("Leave community") visible: !root.community.amISectionAdmin
asset.name: "arrow-left" title: root.community.spectated ? qsTr("Close Community") : qsTr("Leave Community")
asset.name: root.community.spectated ? "close-circle" : "arrow-left"
type: StatusListItem.Type.Danger type: StatusListItem.Type.Danger
onClicked: root.leaveButtonClicked() onClicked: root.leaveButtonClicked()
} }

View File

@ -64,8 +64,9 @@ StatusModal {
store: root.store store: root.store
}) })
onLeaveButtonClicked: { onLeaveButtonClicked: {
communitySectionModule.leaveCommunity();
root.close(); root.close();
root.community.spectated ? communitySectionModule.leaveCommunity()
: Global.leaveCommunityRequested(root.community.name, root.community.id, root.community.outroMessage)
} }
onCopyToClipboard: { onCopyToClipboard: {
root.store.copyToClipboard(link); root.store.copyToClipboard(link);
@ -79,17 +80,6 @@ StatusModal {
destroyOnClose: true destroyOnClose: true
} }
} }
Component {
id: inviteFriendsView
CommunityProfilePopupInviteFriendsPanel {
width: stack.width
headerTitle: qsTr("Invite friends")
community: root.community
contactsStore: root.contactsStore
rootStore: root.store
}
}
} }
leftButtons: [ leftButtons: [
@ -102,18 +92,4 @@ StatusModal {
} }
} }
] ]
rightButtons: [
StatusButton {
text: qsTr("Invite")
visible: root.contentItem.depth > 2
height: !visible ? 0 : implicitHeight
enabled: root.contentItem.currentItem !== undefined && root.contentItem.currentItem.pubKeys.length > 0
onClicked: {
root.contentItem.currentItem.sendInvites(root.contentItem.currentItem.pubKeys, "") // NOTE: empty message
root.contentItem.pop()
}
}
]
} }

View File

@ -112,6 +112,7 @@ Item {
root.store.cancelPendingRequest(communityData.id) root.store.cancelPendingRequest(communityData.id)
joinCommunityButton.invitationPending = root.store.isCommunityRequestPending(communityData.id) joinCommunityButton.invitationPending = root.store.isCommunityRequestPending(communityData.id)
} }
onClosed: destroy()
} }
} }
} }

View File

@ -15,7 +15,8 @@ StatusListView {
property bool hasAddedContacts: false property bool hasAddedContacts: false
signal inviteFriends(var communityData) signal inviteFriends(var communityData)
signal leaveCommunityClicked(string communityId) signal closeCommunityClicked(string communityId)
signal leaveCommunityClicked(string community, string communityId, string outroMessage)
signal setCommunityMutedClicked(string communityId, bool muted) signal setCommunityMutedClicked(string communityId, bool muted)
signal setActiveCommunityClicked(string communityId) signal setActiveCommunityClicked(string communityId)
@ -43,17 +44,14 @@ StatusListView {
components: [ components: [
StatusFlatButton { StatusFlatButton {
anchors.verticalCenter: parent.verticalCenter
objectName: "CommunitiesListPanel_leaveCommunityPopupButton" objectName: "CommunitiesListPanel_leaveCommunityPopupButton"
size: StatusBaseButton.Size.Small size: StatusBaseButton.Size.Small
type: StatusBaseButton.Type.Danger type: StatusBaseButton.Type.Danger
borderColor: "transparent" borderColor: "transparent"
text: qsTr("Leave Community") enabled: !model.amISectionAdmin
onClicked: { text: model.spectated ? qsTr("Close Community") : qsTr("Leave Community")
Global.openPopup(leaveCommunityPopup, { onClicked: model.spectated ? root.closeCommunityClicked(model.id) : root.leaveCommunityClicked(model.name, model.id, model.outroMessage)
community: model.name,
communityId: model.id
})
}
}, },
StatusFlatButton { StatusFlatButton {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -68,46 +66,5 @@ StatusListView {
onClicked: root.inviteFriends(model) onClicked: root.inviteFriends(model)
} }
] ]
} // StatusListItem
property Component leaveCommunityPopup: StatusModal {
id: leavePopup
property string community: ""
property string communityId: ""
anchors.centerIn: parent
headerSettings.title: qsTr("Leave %1").arg(community)
contentItem: Item {
implicitWidth: 368
implicitHeight: msg.implicitHeight + 32
StatusBaseText {
id: msg
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: 16
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: qsTr("Are you sure you want to leave? Once you leave, you will have to request to rejoin if you change your mind.")
color: Theme.palette.directColor1
font.pixelSize: 15
} }
} }
rightButtons: [
StatusButton {
text: qsTr("Cancel")
onClicked: leavePopup.close()
},
StatusButton {
objectName: "CommunitiesListPanel_leaveCommunityButtonInPopup"
type: StatusBaseButton.Type.Danger
text: qsTr("Leave community")
onClicked: {
root.leaveCommunityClicked(leavePopup.communityId)
leavePopup.close()
}
}
]
}
} // ListView

View File

@ -30,9 +30,7 @@ SettingsContentBase {
titleRowComponentLoader.sourceComponent: StatusButton { titleRowComponentLoader.sourceComponent: StatusButton {
text: qsTr("Import community") text: qsTr("Import community")
size: StatusBaseButton.Size.Small size: StatusBaseButton.Size.Small
onClicked: { onClicked: Global.importCommunityPopupRequested()
Global.openPopup(importCommunitiesPopupComponent)
}
} }
Item { Item {
@ -117,10 +115,14 @@ SettingsContentBase {
] ]
} }
onLeaveCommunityClicked: { onCloseCommunityClicked: {
root.profileSectionStore.communitiesProfileModule.leaveCommunity(communityId) root.profileSectionStore.communitiesProfileModule.leaveCommunity(communityId)
} }
onLeaveCommunityClicked: {
Global.leaveCommunityRequested(community, communityId, outroMessage)
}
onSetCommunityMutedClicked: { onSetCommunityMutedClicked: {
root.profileSectionStore.communitiesProfileModule.setCommunityMuted(communityId, muted) root.profileSectionStore.communitiesProfileModule.setCommunityMuted(communityId, muted)
} }
@ -135,16 +137,6 @@ SettingsContentBase {
null) null)
} }
} }
} // Column
} // Item
property Component importCommunitiesPopupComponent: ImportCommunityPopup {
anchors.centerIn: parent
store: root.profileSectionStore
onClosed: {
destroy()
} }
} }
}
} // ScrollView

View File

@ -354,6 +354,8 @@ Item {
onTriggered: popups.openCommunityProfilePopup(appMain.rootStore, model, communityContextMenu.chatCommunitySectionModule) onTriggered: popups.openCommunityProfilePopup(appMain.rootStore, model, communityContextMenu.chatCommunitySectionModule)
} }
StatusMenuSeparator {}
StatusAction { StatusAction {
text: model.muted ? qsTr("Unmute Community") : qsTr("Mute Community") text: model.muted ? qsTr("Unmute Community") : qsTr("Mute Community")
icon.name: model.muted ? "notification-muted" : "notification" icon.name: model.muted ? "notification-muted" : "notification"
@ -362,13 +364,20 @@ Item {
} }
} }
StatusMenuSeparator {} StatusMenuSeparator { visible: leaveCommunityMenuItem.enabled }
StatusAction { StatusAction {
text: qsTr("Leave Community") id: leaveCommunityMenuItem
icon.name: "arrow-left" enabled: !model.amISectionAdmin
text: {
if (model.spectated)
return qsTr("Close Community")
return qsTr("Leave Community")
}
icon.name: model.spectated ? "close-circle" : "arrow-left"
type: StatusAction.Type.Danger type: StatusAction.Type.Danger
onTriggered: communityContextMenu.chatCommunitySectionModule.leaveCommunity() onTriggered: model.spectated ? communityContextMenu.chatCommunitySectionModule.leaveCommunity()
: popups.openLeaveCommunityPopup(model.name, model.id, model.outroMessage)
} }
} }
} }

View File

@ -1,5 +1,13 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Dialogs 1.0 import QtQuick.Layouts 1.15
import QtQuick.Dialogs 1.3
import QtQml.Models 2.15
import QtQml 2.15
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Popups 0.1
import AppLayouts.Chat.popups 1.0 import AppLayouts.Chat.popups 1.0
import AppLayouts.Profile.popups 1.0 import AppLayouts.Profile.popups 1.0
@ -44,6 +52,7 @@ QtObject {
Global.closePopupRequested.connect(closePopup) Global.closePopupRequested.connect(closePopup)
Global.openDeleteMessagePopup.connect(openDeleteMessagePopup) Global.openDeleteMessagePopup.connect(openDeleteMessagePopup)
Global.openDownloadImageDialog.connect(openDownloadImageDialog) Global.openDownloadImageDialog.connect(openDownloadImageDialog)
Global.leaveCommunityRequested.connect(openLeaveCommunityPopup)
} }
property var currentPopup property var currentPopup
@ -228,6 +237,10 @@ QtObject {
popup.open() popup.open()
} }
function openLeaveCommunityPopup(community, communityId, outroMessage) {
openPopup(leaveCommunityPopupComponent, {community, communityId, outroMessage})
}
readonly property list<Component> _components: [ readonly property list<Component> _components: [
Component { Component {
id: removeContactConfirmationDialog id: removeContactConfirmationDialog
@ -280,7 +293,6 @@ QtObject {
Component { Component {
id: sendIDRequestPopupComponent id: sendIDRequestPopupComponent
SendContactRequestModal { SendContactRequestModal {
anchors.centerIn: parent
rootStore: root.rootStore rootStore: root.rootStore
onAccepted: root.rootStore.profileSectionStore.contactsStore.sendVerificationRequest(userPublicKey, message) onAccepted: root.rootStore.profileSectionStore.contactsStore.sendVerificationRequest(userPublicKey, message)
onClosed: destroy() onClosed: destroy()
@ -291,7 +303,6 @@ QtObject {
id: inviteFriendsToCommunityPopup id: inviteFriendsToCommunityPopup
InviteFriendsToCommunityPopup { InviteFriendsToCommunityPopup {
anchors.centerIn: parent
rootStore: root.rootStore rootStore: root.rootStore
contactsStore: root.rootStore.contactStore contactsStore: root.rootStore.contactStore
onClosed: destroy() onClosed: destroy()
@ -302,7 +313,6 @@ QtObject {
id: sendContactRequestPopupComponent id: sendContactRequestPopupComponent
SendContactRequestModal { SendContactRequestModal {
anchors.centerIn: parent
rootStore: root.rootStore rootStore: root.rootStore
onAccepted: root.rootStore.profileSectionStore.contactsStore.sendContactRequest(userPublicKey, message) onAccepted: root.rootStore.profileSectionStore.contactsStore.sendContactRequest(userPublicKey, message)
onClosed: destroy() onClosed: destroy()
@ -312,7 +322,6 @@ QtObject {
Component { Component {
id: backupSeedModalComponent id: backupSeedModalComponent
BackupSeedModal { BackupSeedModal {
anchors.centerIn: parent
privacyStore: rootStore.profileSectionStore.privacyStore privacyStore: rootStore.profileSectionStore.privacyStore
onClosed: destroy() onClosed: destroy()
} }
@ -321,7 +330,6 @@ QtObject {
Component { Component {
id: displayNamePopupComponent id: displayNamePopupComponent
DisplayNamePopup { DisplayNamePopup {
anchors.centerIn: parent
profileStore: rootStore.profileSectionStore.profileStore profileStore: rootStore.profileSectionStore.profileStore
onClosed: destroy() onClosed: destroy()
} }
@ -395,7 +403,6 @@ QtObject {
id: communityProfilePopup id: communityProfilePopup
CommunityProfilePopup { CommunityProfilePopup {
anchors.centerIn: parent
contactsStore: rootStore.contactStore contactsStore: rootStore.contactStore
hasAddedContacts: rootStore.hasAddedContacts hasAddedContacts: rootStore.hasAddedContacts
@ -459,7 +466,6 @@ QtObject {
Component { Component {
id: createCommunitiesPopupComponent id: createCommunitiesPopupComponent
CreateCommunityPopup { CreateCommunityPopup {
anchors.centerIn: parent
store: root.communitiesStore store: root.communitiesStore
onClosed: { onClosed: {
destroy() destroy()
@ -498,6 +504,59 @@ QtObject {
destroy() destroy()
} }
} }
},
Component {
id: leaveCommunityPopupComponent
StatusModal {
id: leavePopup
property string community
property string communityId
property string outroMessage
headerSettings.title: qsTr("Are you sure want to leave '%1'?").arg(community)
padding: 16
width: 640
contentItem: ColumnLayout {
spacing: 16
StatusBaseText {
id: outroMessage
Layout.fillWidth: true
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: leavePopup.outroMessage
visible: !!text
}
StatusMenuSeparator {
Layout.fillWidth: true
visible: outroMessage.visible
}
StatusBaseText {
Layout.fillWidth: true
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
font.pixelSize: 13
text: qsTr("You will need to request to join if you want to become a member again in the future. If you joined the Community via public key ensure you have a copy of it before you go.")
}
}
rightButtons: [
StatusFlatButton {
text: qsTr("Cancel")
onClicked: leavePopup.close()
},
StatusButton {
objectName: "CommunitiesListPanel_leaveCommunityButtonInPopup"
type: StatusBaseButton.Type.Danger
text: qsTr("Leave %1").arg(leavePopup.community)
onClicked: {
root.rootStore.profileSectionStore.communitiesProfileModule.leaveCommunity(leavePopup.communityId)
leavePopup.close()
}
}
]
onClosed: destroy()
}
} }
] ]
} }

View File

@ -56,6 +56,7 @@ QtObject {
signal switchToCommunity(string communityId) signal switchToCommunity(string communityId)
signal createCommunityPopupRequested(bool isDiscordImport) signal createCommunityPopupRequested(bool isDiscordImport)
signal importCommunityPopupRequested() signal importCommunityPopupRequested()
signal leaveCommunityRequested(string community, string communityId, string outroMessage)
signal playSendMessageSound() signal playSendMessageSound()
signal playNotificationSound() signal playNotificationSound()