From b1e5a15e2a88e8dad9480a8a67690e49f655f7d0 Mon Sep 17 00:00:00 2001 From: Pascal Precht Date: Mon, 25 Jan 2021 16:58:33 +0100 Subject: [PATCH] refactor(ChannelContextMenu): remove dependency on active channel This commit does a bunch of things: - First and foremost, it removes the active channel dependency. This is needed to have it operate on the correct channel object, without forcing us to change the active channel (e.g. right-clicking on a channel item that's not active, will make it active eventually) - To make that work, this commit changes the `ChannelContextMenu` to receive a `ChatItemView`, so it can be used for things like determining what menu options are shown, what members are in a group, whether someone is admin of a group etc. - This also required a new `QtProperty` called `contextChannel`. The reason this is required, is because in some cases, like receiving members count of groups, we need a complete `ChatItemView` object as we don't have access to certain APIs otherwise. - Unfortunately, we can't pass down `activeChannel` every where for that because sometimes the context menu should not actually operate on the active channel. Fixes: #1755 --- src/app/chat/view.nim | 18 ++++++++ ui/app/AppLayouts/Chat/ChatColumn/TopBar.qml | 4 +- .../Chat/ContactsColumn/Channel.qml | 7 +-- .../Chat/components/ChannelContextMenu.qml | 45 ++++++++----------- .../Chat/components/GroupInfoPopup.qml | 28 +++++++----- 5 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index 44ac93014d..9b96590511 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -35,6 +35,7 @@ QtObject: groups*: GroupsView transactions*: TransactionsView activeChannel*: ChatItemView + contextChannel*: ChatItemView previousActiveChannelIndex: int activeCommunity*: CommunityItemView observedCommunity*: CommunityItemView @@ -54,6 +55,7 @@ QtObject: proc delete(self: ChatsView) = self.chats.delete self.activeChannel.delete + self.contextChannel.delete self.observedCommunity.delete self.activeCommunity.delete self.currentSuggestions.delete @@ -73,6 +75,7 @@ QtObject: result.connected = false result.chats = newChannelsList(status) result.activeChannel = newChatItemView(status) + result.contextChannel = newChatItemView(status) result.activeCommunity = newCommunityItemView(status) result.observedCommunity = newCommunityItemView(status) result.currentSuggestions = newSuggestionsList() @@ -190,6 +193,8 @@ QtObject: proc activeChannelChanged*(self: ChatsView) {.signal.} + proc contextChannelChanged*(self: ChatsView) {.signal.} + proc sendingMessage*(self: ChatsView) {.signal.} proc appReady*(self: ChatsView) {.signal.} @@ -267,6 +272,19 @@ QtObject: write = setActiveChannel notify = activeChannelChanged + proc setContextChannel*(self: ChatsView, channel: string) {.slot.} = + let contextChannel = self.chats.getChannel(self.chats.chats.findIndexById(channel)) + self.contextChannel.setChatItem(contextChannel) + self.contextChannelChanged() + + proc getContextChannel*(self: ChatsView): QVariant {.slot.} = + newQVariant(self.contextChannel) + + QtProperty[QVariant] contextChannel: + read = getContextChannel + write = setContextChannel + notify = contextChannelChanged + proc setActiveChannelToTimeline*(self: ChatsView) {.slot.} = if not self.activeChannel.chatItem.isNil: self.previousActiveChannelIndex = self.chats.chats.findIndexById(self.activeChannel.id) diff --git a/ui/app/AppLayouts/Chat/ChatColumn/TopBar.qml b/ui/app/AppLayouts/Chat/ChatColumn/TopBar.qml index ad917fcdde..0799e9484e 100644 --- a/ui/app/AppLayouts/Chat/ChatColumn/TopBar.qml +++ b/ui/app/AppLayouts/Chat/ChatColumn/TopBar.qml @@ -38,7 +38,7 @@ Rectangle { onClicked: { switch (chatsModel.activeChannel.chatType) { case Constants.chatTypePrivateGroupChat: - groupInfoPopup.open() + groupInfoPopup.openMenu(chatsModel.activeChannel, chatsModel.getActiveChannelIdx()) break; case Constants.chatTypeOneToOne: const profileImage = appMain.getProfileImage(chatsModel.activeChannel.id) @@ -128,7 +128,7 @@ Rectangle { icon.height: chatTopBarContent.iconSize //% "Group Information" text: qsTrId("group-information") - onTriggered: groupInfoPopup.open() + onTriggered: groupInfoPopup.openMenu(chatsModel.activeChannel, chatsModel.getActiveChannelIdx()) } Action { icon.source: "../../../img/close.svg" diff --git a/ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml b/ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml index b1ea633e5f..22c9087160 100644 --- a/ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml +++ b/ui/app/AppLayouts/Chat/ContactsColumn/Channel.qml @@ -168,12 +168,13 @@ Rectangle { wrapper.hovered = false } onClicked: { - chatsModel.setActiveChannelByIndex(index) - chatGroupsListView.currentIndex = index if (mouse.button & Qt.RightButton) { - channelContextMenu.openMenu(chatsModel.activeChannel, index) + chatsModel.setContextChannel(chatId) + channelContextMenu.openMenu(chatsModel.contextChannel, index) return; } + chatsModel.setActiveChannelByIndex(index) + chatGroupsListView.currentIndex = index } } diff --git a/ui/app/AppLayouts/Chat/components/ChannelContextMenu.qml b/ui/app/AppLayouts/Chat/components/ChannelContextMenu.qml index 58890b6d67..4e39874828 100644 --- a/ui/app/AppLayouts/Chat/components/ChannelContextMenu.qml +++ b/ui/app/AppLayouts/Chat/components/ChannelContextMenu.qml @@ -7,13 +7,8 @@ import "../../../../imports" PopupMenu { property int channelIndex - property bool channelMuted - property int chatType - property string chatName - property string chatId - property string chatIdenticon + property var contextChannel property var groupInfoPopup - property var groupsListView id: channelContextMenu width: 175 @@ -31,11 +26,7 @@ PopupMenu { ] function openMenu(channel, index) { - channelContextMenu.channelMuted = channel.muted - channelContextMenu.chatType = channel.chatType - channelContextMenu.chatName = channel.name - channelContextMenu.chatId = channel.id - channelContextMenu.chatIdenticon = channel.identicon + channelContextMenu.contextChannel = channel if (index !== undefined) { channelContextMenu.channelIndex = index } @@ -43,13 +34,13 @@ PopupMenu { } Action { - enabled: channelContextMenu.chatType !== Constants.chatTypePublic + enabled: channelContextMenu.contextChannel.chatType !== Constants.chatTypePublic text: { - if (channelContextMenu.chatType === Constants.chatTypeOneToOne) { + if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) { //% "View Profile" return qsTrId("view-profile") } - if (channelContextMenu.chatType === Constants.chatTypePrivateGroupChat) { + if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) { //% "View Group" return qsTrId("view-group") } @@ -60,16 +51,16 @@ PopupMenu { icon.width: 16 icon.height: 16 onTriggered: { - //chatsModel.setActiveChannelByIndex(channelContextMenu.channelIndex) - if (!!groupsListView) { - groupsListView.currentIndex = channelContextMenu.channelIndex + if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) { + const userProfileImage = appMain.getProfileImage(channelContextMenu.contextChannel.id) + return openProfilePopup( + channelContextMenu.contextChannel.name, + channelContextMenu.contextChannel.id, + userProfileImage || channelContextMenu.contextChannel.identicon + ) } - if (channelContextMenu.chatType === Constants.chatTypeOneToOne) { - const userProfileImage = appMain.getProfileImage(channelContextMenu.chatId) - return openProfilePopup(channelContextMenu.chatName, channelContextMenu.chatId, userProfileImage || channelContextMenu.chatIdenticon) - } - if (channelContextMenu.chatType === Constants.chatTypePrivateGroupChat) { - return groupInfoPopup.open() + if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) { + return groupInfoPopup.openMenu(channelContextMenu.contextChannel) } } } @@ -77,7 +68,7 @@ PopupMenu { Separator {} Action { - text: channelContextMenu.channelMuted ? + text: channelContextMenu.contextChannel.muted ? //% "Unmute chat" qsTrId("unmute-chat") : //% "Mute chat" @@ -118,11 +109,11 @@ PopupMenu { Action { text: { - if (channelContextMenu.chatType === Constants.chatTypeOneToOne) { + if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) { //% "Delete chat" return qsTrId("delete-chat") } - if (channelContextMenu.chatType === Constants.chatTypePrivateGroupChat) { + if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) { //% "Leave group" return qsTrId("leave-group") } @@ -130,7 +121,7 @@ PopupMenu { return qsTrId("leave-chat") } icon.source: { - if (channelContextMenu.chatType === Constants.chatTypeOneToOne) { + if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) { return "../../../img/delete.svg" } return "../../../img/leave_chat.svg" diff --git a/ui/app/AppLayouts/Chat/components/GroupInfoPopup.qml b/ui/app/AppLayouts/Chat/components/GroupInfoPopup.qml index b61558df0e..d80a50ab87 100644 --- a/ui/app/AppLayouts/Chat/components/GroupInfoPopup.qml +++ b/ui/app/AppLayouts/Chat/components/GroupInfoPopup.qml @@ -13,18 +13,19 @@ ModalPopup { property int memberCount: 1 readonly property int maxMembers: 10 property var pubKeys: [] + property var channel property bool isAdmin: false function resetSelectedMembers(){ pubKeys = []; - memberCount = chatsModel.activeChannel.members.rowCount(); + memberCount = channel.members.rowCount(); currMemberCount = memberCount; contactList.membersData.clear(); const contacts = chatView.getContactListObject() contacts.forEach(function (contact) { - if(chatsModel.activeChannel.contains(contact.pubKey) || + if(popup.channel.contains(contact.pubKey) || !contact.isContact) { return; } @@ -32,16 +33,21 @@ ModalPopup { }) } + function openMenu(channel) { + popup.channel = channel + popup.open() + } + onOpened: { addMembers = false; - popup.isAdmin = chatsModel.activeChannel.isAdmin(profileModel.profile.pubKey) + popup.isAdmin = popup.channel.isAdmin(profileModel.profile.pubKey) btnSelectMembers.enabled = false; resetSelectedMembers(); } function doAddMembers(){ if(pubKeys.length === 0) return; - chatsModel.groups.addMembers(chatsModel.activeChannel.id, JSON.stringify(pubKeys)); + chatsModel.groups.addMembers(popup.channel.id, JSON.stringify(pubKeys)); popup.close(); } @@ -55,14 +61,14 @@ ModalPopup { width: 36 height: 36 anchors.top: parent.top - color: chatsModel.activeChannel.color - chatName: chatsModel.activeChannel.name + color: popup.channel.color + chatName: popup.channel.name } StyledTextEdit { id: groupName //% "Add members" - text: addMembers ? qsTrId("add-members") : chatsModel.activeChannel.name + text: addMembers ? qsTrId("add-members") : popup.channel.name anchors.top: parent.top anchors.topMargin: 2 anchors.left: letterIdenticon.right @@ -174,7 +180,7 @@ ModalPopup { pubKeys.splice(idx, 1); } } - memberCount = chatsModel.activeChannel.members.rowCount() + pubKeys.length; + memberCount = popup.channel.members.rowCount() + pubKeys.length; btnSelectMembers.enabled = pubKeys.length > 0 } } @@ -201,7 +207,7 @@ ModalPopup { spacing: 15 Layout.fillWidth: true Layout.fillHeight: true - model: chatsModel.activeChannel.members + model: popup.channel.members delegate: Item { id: contactRow width: parent.width @@ -273,14 +279,14 @@ ModalPopup { icon.source: "../../../img/make-admin.svg" //% "Make Admin" text: qsTrId("make-admin") - onTriggered: chatsModel.groups.makeAdmin(chatsModel.activeChannel.id, model.pubKey) + onTriggered: chatsModel.groups.makeAdmin(popup.channel.id, model.pubKey) } Action { icon.source: "../../../img/remove-from-group.svg" icon.color: Style.current.red //% "Remove From Group" text: qsTrId("remove-from-group") - onTriggered: chatsModel.groups.kickMember(chatsModel.activeChannel.id, model.pubKey) + onTriggered: chatsModel.groups.kickMember(popup.channel.id, model.pubKey) } } }