feat(Settings/Communities): implement new communities list

Closes #11145
This commit is contained in:
Lukáš Tinkl 2023-06-21 22:37:51 +02:00 committed by Lukáš Tinkl
parent 9df6e68a77
commit 620c7a746d
16 changed files with 446 additions and 132 deletions

View File

@ -69,6 +69,10 @@ ListModel {
title: "DeviceSyncingView" title: "DeviceSyncingView"
section: "Views" section: "Views"
} }
ListElement {
title: "CommunitiesView"
section: "Views"
}
ListElement { ListElement {
title: "StatusCommunityCard" title: "StatusCommunityCard"
section: "Panels" section: "Panels"

View File

@ -221,5 +221,8 @@
], ],
"StatusButton": [ "StatusButton": [
"https://www.figma.com/file/MtAO3a7HnEH5xjCDVNilS7/%F0%9F%8E%A8-Design-System-%E2%8E%9C-Desktop?type=design&node-id=1-12&t=UHegCbqAa5K7qUKd-0" "https://www.figma.com/file/MtAO3a7HnEH5xjCDVNilS7/%F0%9F%8E%A8-Design-System-%E2%8E%9C-Desktop?type=design&node-id=1-12&t=UHegCbqAa5K7qUKd-0"
],
"CommunitiesView": [
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?type=design&node-id=16089-387522&t=HRT9BmZXnl7Lt55Q-0"
] ]
} }

View File

@ -0,0 +1,161 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import StatusQ.Core 0.1
import AppLayouts.Profile.views 1.0
import mainui 1.0
import utils 1.0
import Storybook 1.0
import Models 1.0
SplitView {
id: root
Logs { id: logs }
orientation: Qt.Vertical
Popups {
popupParent: root
rootStore: QtObject {}
}
ListModel {
id: emptyModel
}
ListModel {
id: communitiesModel
Component.onCompleted:
append([{
id: "0x0001",
name: "Test community",
description: "Lorem ipsum dolor sit amet",
introMessage: "Welcome to ze club",
outroMessage: "Sad to see you go",
joined: true,
spectated: false,
memberRole: Constants.memberRole.owner,
image: ModelsData.icons.dribble,
color: "yellow",
muted: false,
members: [ { pubKey: "0xdeadbeef" } ]
},
{
id: "0x0002",
name: "Test community 2",
description: "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat.",
introMessage: "Welcome to ze club",
outroMessage: "Sad to see you go",
joined: true,
spectated: false,
memberRole: Constants.memberRole.none,
image: ModelsData.icons.status,
color: "peach",
muted: false,
members: [ { pubKey: "0xdeadbeef" }, { pubKey: "0xdeadbeef" }, { pubKey: "0xdeadbeef" } ]
},
{
id: "0x0003",
name: "Free to join",
introMessage: "Welcome to ze club",
description: "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat.",
outroMessage: "Sad to see you go",
joined: false,
spectated: true,
memberRole: Constants.memberRole.none,
image: "",
color: "red",
muted: false,
members: [ { pubKey: "0xdeadbeef" } ]
},
{
id: "0x0004",
name: "Muted community",
introMessage: "Welcome to ze club",
description: "Lorem ipsum dolor sit amet",
outroMessage: "Sad to see you go",
joined: true,
spectated: false,
memberRole: Constants.memberRole.none,
image: "",
color: "whitesmoke",
muted: true,
members: []
},
{
id: "0x0005",
name: "Test community 4",
description: "Lorem ipsum dolor sit amet",
introMessage: "Welcome to ze club",
outroMessage: "Sad to see you go",
joined: true,
spectated: false,
memberRole: Constants.memberRole.admin,
image: ModelsData.icons.spotify,
color: "green",
muted: false,
members: [{ pubKey: "0xdeadbeef" }, { pubKey: "0xdeadbeef" }, { pubKey: "0xdeadbeef" }, { pubKey: "0xdeadbeef" }]
},
{
id: "0x0006",
name: "Pending request here",
description: "Lorem ipsum dolor sit amet",
introMessage: "Welcome to ze club",
outroMessage: "Sad to see you go",
joined: false,
spectated: true,
memberRole: Constants.memberRole.none,
image: ModelsData.icons.spotify,
color: "pink",
muted: false,
members: [{ pubKey: "0xdeadbeef" }]
}
])
}
CommunitiesView {
SplitView.fillWidth: true
SplitView.preferredHeight: 400
contentWidth: 664
profileSectionStore: QtObject {
property var communitiesProfileModule: QtObject {
function setCommunityMuted(communityId, mutedType) {
logs.logEvent("profileSectionStore::communitiesProfileModule::setCommunityMuted", ["communityId", "mutedType"], arguments)
}
function leaveCommunity(communityId) {
logs.logEvent("profileSectionStore::communitiesProfileModule::leaveCommunity", ["communityId"], arguments)
}
}
property var communitiesList: ctrlEmptyView.checked ? emptyModel : communitiesModel
}
rootStore: QtObject {
function isCommunityRequestPending(communityId) {
return communityId === "0x0006"
}
function cancelPendingRequest(communityId) {
logs.logEvent("rootStore::cancelPendingRequest", ["communityId"], arguments)
}
function setActiveCommunity(communityId) {
logs.logEvent("rootStore::setActiveCommunity", ["communityId"], arguments)
}
}
}
LogsAndControlsPanel {
id: logsAndControlsPanel
SplitView.minimumHeight: 100
SplitView.preferredHeight: 200
logsView.logText: logs.logText
Switch {
id: ctrlEmptyView
text: "No communities"
}
}
}

View File

@ -143,11 +143,13 @@ StatusListItem {
statusListItemIcon.badge.implicitHeight: 12 // 8 px + 2 px * 2 borders statusListItemIcon.badge.implicitHeight: 12 // 8 px + 2 px * 2 borders
statusListItemIcon.badge.implicitWidth: 12 // 8 px + 2 px * 2 borders statusListItemIcon.badge.implicitWidth: 12 // 8 px + 2 px * 2 borders
components: [ components: [
StatusIcon { Loader {
anchors.verticalCenter: parent.verticalCenter active: root.isAdmin
visible: root.isAdmin sourceComponent: StatusIcon {
icon: "crown" anchors.verticalCenter: parent.verticalCenter
color: Theme.palette.directColor1 icon: "crown"
color: Theme.palette.directColor1
}
} }
] ]
} }

View File

@ -91,25 +91,6 @@ 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)
}
}
} }
} }
@ -136,7 +117,7 @@ StackLayout {
viewAndPostPermissionsModel: root.permissionsStore.viewAndPostPermissionsModel viewAndPostPermissionsModel: root.permissionsStore.viewAndPostPermissionsModel
assetsModel: root.rootStore.assetsModel assetsModel: root.rootStore.assetsModel
collectiblesModel: root.rootStore.collectiblesModel collectiblesModel: root.rootStore.collectiblesModel
isInvitationPending: root.rootStore.isCommunityRequestPending(root.sectionItemModel.id) isInvitationPending: root.rootStore.isCommunityRequestPending(chatView.communityId)
onCommunityInfoButtonClicked: root.currentIndex = 1 onCommunityInfoButtonClicked: root.currentIndex = 1
onCommunityManageButtonClicked: root.currentIndex = 1 onCommunityManageButtonClicked: root.currentIndex = 1
@ -149,8 +130,8 @@ StackLayout {
} }
onRevealAddressClicked: { onRevealAddressClicked: {
Global.openPopup(communityIntroDialogPopup, { Global.openPopup(communityIntroDialogPopup, {
communityId: root.sectionItemModel.id, communityId: chatView.communityId,
isInvitationPending: root.rootStore.isCommunityRequestPending(root.sectionItemModel.id), isInvitationPending: root.rootStore.isCommunityRequestPending(chatView.communityId),
name: root.sectionItemModel.name, name: root.sectionItemModel.name,
introMessage: root.sectionItemModel.introMessage, introMessage: root.sectionItemModel.introMessage,
imageSrc: root.sectionItemModel.image, imageSrc: root.sectionItemModel.image,
@ -158,8 +139,8 @@ StackLayout {
}) })
} }
onInvitationPendingClicked: { onInvitationPendingClicked: {
root.rootStore.cancelPendingRequest(root.sectionItemModel.id) root.rootStore.cancelPendingRequest(chatView.communityId)
chatView.isInvitationPending = root.rootStore.isCommunityRequestPending(root.sectionItemModel.id) chatView.isInvitationPending = root.rootStore.isCommunityRequestPending(chatView.communityId)
} }
} }
} }

View File

@ -108,11 +108,10 @@ SettingsPageLayout {
model: root.membersModel model: root.membersModel
rootStore: root.rootStore rootStore: root.rootStore
placeholderText: { placeholderText: {
if (root.membersModel.count === 0) { if (root.membersModel.count === 0)
return qsTr("No members to search") return qsTr("No members to search")
} else {
return qsTr("Search %1's %n member(s)", "", root.membersModel ? root.membersModel.count : 0).arg(root.communityName) return qsTr("Search %1's %n member(s)", "", root.membersModel ? root.membersModel.count : 0).arg(root.communityName)
}
} }
panelType: CommunityMembersTabPanel.TabType.AllMembers panelType: CommunityMembersTabPanel.TabType.AllMembers
@ -136,13 +135,10 @@ SettingsPageLayout {
model: root.pendingMemberRequestsModel model: root.pendingMemberRequestsModel
rootStore: root.rootStore rootStore: root.rootStore
placeholderText: { placeholderText: {
if (root.pendingMemberRequestsModel.count === 0) { if (root.pendingMemberRequestsModel.count === 0)
return qsTr("No pending requests to search") return qsTr("No pending requests to search")
} else {
return qsTr("Search %1's %2 pending request%3").arg(root.communityName) return qsTr("Search %1's %n pending request(s)", "", root.pendingMemberRequestsModel.count).arg(root.communityName)
.arg(root.pendingMemberRequestsModel.count)
.arg(root.pendingMemberRequestsModel.count > 1 ? "s" : "")
}
} }
panelType: CommunityMembersTabPanel.TabType.PendingRequests panelType: CommunityMembersTabPanel.TabType.PendingRequests
@ -157,13 +153,10 @@ SettingsPageLayout {
model: root.declinedMemberRequestsModel model: root.declinedMemberRequestsModel
rootStore: root.rootStore rootStore: root.rootStore
placeholderText: { placeholderText: {
if (root.declinedMemberRequestsModel.count === 0) { if (root.declinedMemberRequestsModel.count === 0)
return qsTr("No rejected members to search") return qsTr("No rejected members to search")
} else {
return qsTr("Search %1's %2 rejected member%3").arg(root.communityName) return qsTr("Search %1's %n rejected member(s)", "", root.declinedMemberRequestsModel.count).arg(root.communityName)
.arg(root.declinedMemberRequestsModel.count)
.arg(root.declinedMemberRequestsModel.count > 1 ? "s" : "")
}
} }
panelType: CommunityMembersTabPanel.TabType.DeclinedRequests panelType: CommunityMembersTabPanel.TabType.DeclinedRequests
@ -177,13 +170,10 @@ SettingsPageLayout {
model: root.bannedMembersModel model: root.bannedMembersModel
rootStore: root.rootStore rootStore: root.rootStore
placeholderText: { placeholderText: {
if (root.bannedMembersModel.count === 0) { if (root.bannedMembersModel.count === 0)
return qsTr("No banned members to search") return qsTr("No banned members to search")
} else {
return qsTr("Search %1's %2 banned member%3").arg(root.communityName) return qsTr("Search %1's %n banned member(s)", "", root.bannedMembersModel.count).arg(root.communityName)
.arg(root.bannedMembersModel.count)
.arg(root.bannedMembersModel.count > 1 ? "s" : "")
}
} }
panelType: CommunityMembersTabPanel.TabType.BannedMembers panelType: CommunityMembersTabPanel.TabType.BannedMembers

View File

@ -165,7 +165,7 @@ Item {
ProfileContextMenu { ProfileContextMenu {
id: memberContextMenuView id: memberContextMenuView
store: root.rootStore store: root.rootStore
myPublicKey: root.rootStore.myPublicKey() myPublicKey: userProfile.pubKey
onOpenProfileClicked: { onOpenProfileClicked: {
Global.openProfilePopup(publicKey, null) Global.openProfilePopup(publicKey, null)

View File

@ -632,6 +632,7 @@ StatusSectionLayout {
TransferOwnershipPopup { TransferOwnershipPopup {
anchors.centerIn: parent anchors.centerIn: parent
store: root.rootStore store: root.rootStore
onClosed: destroy()
} }
} }

View File

@ -300,7 +300,6 @@ StatusSectionLayout {
profileSectionStore: root.store profileSectionStore: root.store
rootStore: root.globalStore rootStore: root.globalStore
contactStore: root.store.contactsStore
sectionTitle: root.store.getNameForSubsection(Constants.settingsSubsection.communitiesSettings) sectionTitle: root.store.getNameForSubsection(Constants.settingsSubsection.communitiesSettings)
contentWidth: d.contentWidth contentWidth: d.contentWidth
} }

View File

@ -8,88 +8,155 @@ import StatusQ.Controls 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
import utils 1.0 import utils 1.0
import shared.controls.chat.menuItems 1.0 import shared.controls.chat.menuItems 1.0
StatusListView { StatusListView {
id: root id: root
property bool hasAddedContacts: false property var rootStore
signal inviteFriends(var communityData) signal inviteFriends(var communityData)
signal closeCommunityClicked(string communityId) signal closeCommunityClicked(string communityId)
signal leaveCommunityClicked(string community, string communityId, string outroMessage) signal leaveCommunityClicked(string community, string communityId, string outroMessage)
signal setCommunityMutedClicked(string communityId, int mutedType) signal setCommunityMutedClicked(string communityId, int mutedType)
signal setActiveCommunityClicked(string communityId) signal setActiveCommunityClicked(string communityId)
signal showCommunityIntroDialog(string communityId, string name, string introMessage, string imageSrc, int accessType)
signal cancelMembershipRequest(string communityId)
interactive: false interactive: false
implicitHeight: contentItem.childrenRect.height implicitHeight: contentItem.childrenRect.height
spacing: 0 spacing: 0
delegate: StatusListItem { delegate: StatusListItem {
id: statusCommunityItem id: listItem
width: parent.width width: ListView.view.width
title: model.name title: model.name
statusListItemTitle.font.pixelSize: 17 statusListItemTitle.font.pixelSize: 17
statusListItemTitle.font.bold: true statusListItemTitle.font.bold: true
statusListItemIcon.anchors.verticalCenter: undefined
statusListItemIcon.anchors.top: statusListItemTitleArea.top
subTitle: model.description subTitle: model.description
tertiaryTitle: qsTr("%n member(s)", "", model.members.count) tertiaryTitle: qsTr("%n member(s)", "", model.members.count)
statusListItemTertiaryTitle.font.weight: Font.Medium
asset.name: model.image asset.name: model.image
asset.isLetterIdenticon: !model.image asset.isLetterIdenticon: !model.image
asset.bgColor: model.color || Theme.palette.primaryColor1 asset.bgColor: model.color || Theme.palette.primaryColor1
asset.width: 40 asset.width: 40
asset.height: 40 asset.height: 40
visible: model.joined
height: visible ? implicitHeight: 0
onClicked: setActiveCommunityClicked(model.id) onClicked: setActiveCommunityClicked(model.id)
components: [ readonly property bool isOwner: model.memberRole === Constants.memberRole.owner
readonly property bool isAdmin: model.memberRole === Constants.memberRole.admin
readonly property bool isInvitationPending: root.rootStore.isCommunityRequestPending(model.id)
components: [
StatusFlatButton { StatusFlatButton {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
size: StatusBaseButton.Size.Small size: StatusBaseButton.Size.Small
icon.name: "dots-icon" icon.name: "notification-muted"
onClicked: menu.popup(0, height) icon.color: Theme.palette.baseColor1
visible: model.muted
onClicked: root.setCommunityMutedClicked(model.id, Constants.MutingVariations.Unmuted)
},
StatusFlatButton {
anchors.verticalCenter: parent.verticalCenter
size: StatusBaseButton.Size.Small
text: listItem.isInvitationPending ? qsTr("Membership Request Sent") : qsTr("View & Join Community")
visible: model.spectated
onClicked: root.showCommunityIntroDialog(model.id, model.name, model.introMessage, model.image, model.access)
},
StatusFlatButton {
anchors.verticalCenter: parent.verticalCenter
size: StatusBaseButton.Size.Small
icon.name: "more"
icon.color: Theme.palette.directColor1
highlighted: moreMenu.opened
onClicked: moreMenu.popup(-moreMenu.width + width, height + 4)
property StatusMenu menu: StatusMenu { StatusMenu {
id: communityContextMenu id: moreMenu
width: 180
StatusAction { StatusAction {
text: qsTr("Invite People") text: qsTr("Community Admin")
icon.name: "share-ios" icon.name: "settings"
enabled: model.canManageUsers enabled: listItem.isOwner || listItem.isAdmin
onTriggered: root.inviteFriends(model) onTriggered: {
} moreMenu.close()
Global.switchToCommunity(model.id)
MuteChatMenuItem { Global.switchToCommunitySettings(model.id)
enabled: !model.muted
title: qsTr("Mute Community")
onMuteTriggered: {
root.setCommunityMutedClicked(model.id, interval)
communityContextMenu.close()
} }
} }
StatusAction { StatusAction {
enabled: model.muted
text: qsTr("Unmute Community") text: qsTr("Unmute Community")
icon.name: "notification-muted" enabled: model.muted
onTriggered: root.setCommunityMutedClicked(model.id, Constants.MutingVariations.Unmuted) icon.name: "notification"
onTriggered: {
moreMenu.close()
root.setCommunityMutedClicked(model.id, Constants.MutingVariations.Unmuted)
}
}
MuteChatMenuItem {
enabled: (model.joined || (model.spectated && !listItem.isInvitationPending)) && !model.muted
title: qsTr("Mute Community")
onMuteTriggered: {
moreMenu.close()
root.setCommunityMutedClicked(model.id, interval)
}
} }
StatusMenuSeparator {}
StatusAction { StatusAction {
text: model.spectated ? qsTr("Close Community") : qsTr("Leave Community") text: qsTr("Invite People")
icon.name: "arrow-left" icon.name: "invite-users"
onTriggered: {
moreMenu.close()
root.inviteFriends(model)
}
}
StatusAction {
id: shareAddressesMenuItem
text: qsTr("Edit Shared Addresses")
icon.name: "wallet"
enabled: {
if (listItem.isOwner)
return false
if (model.spectated && !listItem.isInvitationPending)
return false
return true
}
onTriggered: {
moreMenu.close()
Global.openEditSharedAddressesFlow(model.id)
// TODO shared addresses flow, cf https://github.com/status-im/status-desktop/issues/11138
}
}
StatusMenuSeparator {
visible: shareAddressesMenuItem.enabled && leaveMenuItem.enabled
}
StatusAction {
id: leaveMenuItem
objectName: "CommunitiesListPanel_leaveCommunityPopupButton"
text: {
if (listItem.isInvitationPending)
return qsTr("Cancel Membership Request")
return model.spectated ? qsTr("Close Community") : qsTr("Leave Community")
}
icon.name: {
if (listItem.isInvitationPending)
return "arrow-left"
return model.spectated ? "close-circle" : "arrow-left"
}
type: StatusAction.Type.Danger type: StatusAction.Type.Danger
onTriggered: model.spectated ? root.closeCommunityClicked(model.id) enabled: !listItem.isOwner
: root.leaveCommunityClicked(model.name, model.id, model.outroMessage) onTriggered: {
moreMenu.close()
if (listItem.isInvitationPending)
root.cancelMembershipRequest(model.id)
else if (model.spectated)
root.closeCommunityClicked(model.id)
else
root.leaveCommunityClicked(model.name, model.id, model.outroMessage)
}
} }
} }
} }

View File

@ -23,7 +23,6 @@ SettingsContentBase {
property var profileSectionStore property var profileSectionStore
property var rootStore property var rootStore
property var contactStore
clip: true clip: true
@ -41,7 +40,7 @@ SettingsContentBase {
ColumnLayout { ColumnLayout {
id: noCommunitiesLayout id: noCommunitiesLayout
anchors.fill: parent anchors.fill: parent
visible: communitiesList.count === 0 visible: !root.profileSectionStore.communitiesList.count
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Image { Image {
@ -90,53 +89,141 @@ SettingsContentBase {
anchors.left: parent.left anchors.left: parent.left
spacing: Style.current.padding spacing: Style.current.padding
StatusBaseText { Heading {
anchors.left: parent.left text: qsTr("Owner")
anchors.leftMargin: Style.current.padding visible: panelOwners.count
color: Theme.palette.baseColor1
text: qsTr("Communities you've joined")
} }
CommunitiesListPanel { Panel {
id: communitiesList id: panelOwners
filters: ValueFilter {
objectName: "CommunitiesView_communitiesListPanel" readonly property int role: Constants.memberRole.owner
width: parent.width roleName: "memberRole"
value: role
model: SortFilterProxyModel {
id: filteredModel
sourceModel: root.profileSectionStore.communitiesList
filters: [
ValueFilter {
roleName: "joined"
value: true
}
]
} }
}
onCloseCommunityClicked: { Heading {
root.profileSectionStore.communitiesProfileModule.leaveCommunity(communityId) text: qsTr("Admin")
visible: panelAdmins.count
}
Panel {
id: panelAdmins
filters: ValueFilter {
readonly property int role: Constants.memberRole.admin
roleName: "memberRole"
value: role
} }
}
onLeaveCommunityClicked: { Heading {
Global.leaveCommunityRequested(community, communityId, outroMessage) text: qsTr("Member")
visible: panelMembers.count
}
Panel {
id: panelMembers
filters: ExpressionFilter {
readonly property int ownerRole: Constants.memberRole.owner
readonly property int adminRole: Constants.memberRole.admin
expression: model.joined && model.memberRole !== ownerRole && model.memberRole !== adminRole
} }
}
onSetCommunityMutedClicked: { Heading {
root.profileSectionStore.communitiesProfileModule.setCommunityMuted(communityId, mutedType) text: qsTr("Pending")
} visible: panelPendingRequests.count
}
onSetActiveCommunityClicked: { Panel {
rootStore.setActiveCommunity(communityId) id: panelPendingRequests
} filters: ValueFilter {
roleName: "spectated"
onInviteFriends: { value: true
Global.openInviteFriendsToCommunityPopup(communityData,
root.profileSectionStore.communitiesProfileModule,
null)
} }
} }
} }
} }
component Heading: StatusBaseText {
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
color: Theme.palette.baseColor1
}
component Panel: CommunitiesListPanel {
id: panel
property var filters
width: parent.width
rootStore: root.rootStore
model: SortFilterProxyModel {
sourceModel: root.profileSectionStore.communitiesList
filters: panel.filters
}
onCloseCommunityClicked: {
root.profileSectionStore.communitiesProfileModule.leaveCommunity(communityId)
}
onLeaveCommunityClicked: {
Global.leaveCommunityRequested(community, communityId, outroMessage)
}
onSetCommunityMutedClicked: {
root.profileSectionStore.communitiesProfileModule.setCommunityMuted(communityId, mutedType)
}
onSetActiveCommunityClicked: {
rootStore.setActiveCommunity(communityId)
}
onInviteFriends: {
Global.openInviteFriendsToCommunityPopup(communityData,
root.profileSectionStore.communitiesProfileModule,
null)
}
onShowCommunityIntroDialog: {
Global.openPopup(communityIntroDialogPopup, {
communityId: communityId,
isInvitationPending: root.rootStore.isCommunityRequestPending(communityId),
name: name,
introMessage: introMessage,
imageSrc: imageSrc,
accessType: accessType
})
}
onCancelMembershipRequest: {
root.rootStore.cancelPendingRequest(communityId)
}
}
readonly property var communityIntroDialogPopup: Component {
id: communityIntroDialogPopup
CommunityIntroDialog {
id: communityIntroDialog
property string communityId
readonly property var chatCommunitySectionModule: {
root.rootStore.mainModuleInst.prepareCommunitySectionModuleForCommunityId(communityIntroDialog.communityId)
return root.rootStore.mainModuleInst.getCommunitySectionModule()
}
onJoined: {
chatCommunitySectionModule.requestToJoinCommunityWithAuthentication(communityIntroDialog.communityId, root.rootStore.userProfileInst.name)
}
onCancelMembershipRequest: {
root.rootStore.cancelPendingRequest(communityIntroDialog.communityId)
}
onClosed: {
destroy()
}
}
}
} }

View File

@ -93,6 +93,14 @@ QtObject {
return communitiesModuleInst.isMemberOfCommunity(communityId, pubKey) return communitiesModuleInst.isMemberOfCommunity(communityId, pubKey)
} }
function isCommunityRequestPending(id: string) {
return communitiesModuleInst.isCommunityRequestPending(id)
}
function cancelPendingRequest(id: string) {
communitiesModuleInst.cancelRequestToJoinCommunity(id)
}
function copyToClipboard(text) { function copyToClipboard(text) {
globalUtils.copyToClipboard(text) globalUtils.copyToClipboard(text)
} }

View File

@ -369,7 +369,7 @@ Item {
StatusAction { StatusAction {
enabled: model.muted enabled: model.muted
text: qsTr("Unmute Community") text: qsTr("Unmute Community")
icon.name: "notification-muted" icon.name: "notification"
onTriggered: { onTriggered: {
communityContextMenu.chatCommunitySectionModule.setCommunityMuted(Constants.MutingVariations.Unmuted) communityContextMenu.chatCommunitySectionModule.setCommunityMuted(Constants.MutingVariations.Unmuted)
} }
@ -1096,6 +1096,15 @@ Item {
restoreMode: Binding.RestoreBindingOrValue restoreMode: Binding.RestoreBindingOrValue
} }
Connections {
target: Global
function onSwitchToCommunitySettings(communityId: string) {
if (communityId !== model.id)
return
chatLayoutComponent.currentIndex = 1 // Settings
}
}
emojiPopup: statusEmojiPopup.item emojiPopup: statusEmojiPopup.item
stickersPopup: statusStickersPopupLoader.item stickersPopup: statusStickersPopupLoader.item
sectionItemModel: model sectionItemModel: model

View File

@ -549,8 +549,8 @@ QtObject {
type: StatusBaseButton.Type.Danger type: StatusBaseButton.Type.Danger
text: qsTr("Leave %1").arg(leavePopup.community) text: qsTr("Leave %1").arg(leavePopup.community)
onClicked: { onClicked: {
root.rootStore.profileSectionStore.communitiesProfileModule.leaveCommunity(leavePopup.communityId)
leavePopup.close() leavePopup.close()
root.rootStore.profileSectionStore.communitiesProfileModule.leaveCommunity(leavePopup.communityId)
} }
} }
] ]

View File

@ -14,7 +14,7 @@ StatusMenu {
title: isCommunityChat ? qsTr("Mute Channel") : qsTr("Mute Chat") title: isCommunityChat ? qsTr("Mute Channel") : qsTr("Mute Chat")
assetSettings.name: "notification" assetSettings.name: "notification-muted"
StatusAction { StatusAction {
text: qsTr("For 15 mins") text: qsTr("For 15 mins")
@ -37,7 +37,7 @@ StatusMenu {
} }
StatusAction { StatusAction {
text: qsTr("Until you turn it back on") text: qsTr("Until I turn it back on")
onTriggered: muteTriggered(Constants.MutingVariations.TillUnmuted) onTriggered: muteTriggered(Constants.MutingVariations.TillUnmuted)
} }
} }

View File

@ -54,9 +54,11 @@ QtObject {
signal openSendModal(string address) signal openSendModal(string address)
signal switchToCommunity(string communityId) signal switchToCommunity(string communityId)
signal switchToCommunitySettings(string communityId)
signal createCommunityPopupRequested(bool isDiscordImport) signal createCommunityPopupRequested(bool isDiscordImport)
signal importCommunityPopupRequested() signal importCommunityPopupRequested()
signal leaveCommunityRequested(string community, string communityId, string outroMessage) signal leaveCommunityRequested(string community, string communityId, string outroMessage)
signal openEditSharedAddressesFlow(string communityId)
signal playSendMessageSound() signal playSendMessageSound()
signal playNotificationSound() signal playNotificationSound()