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
This commit is contained in:
parent
2b3bbb0b1e
commit
b1e5a15e2a
|
@ -35,6 +35,7 @@ QtObject:
|
||||||
groups*: GroupsView
|
groups*: GroupsView
|
||||||
transactions*: TransactionsView
|
transactions*: TransactionsView
|
||||||
activeChannel*: ChatItemView
|
activeChannel*: ChatItemView
|
||||||
|
contextChannel*: ChatItemView
|
||||||
previousActiveChannelIndex: int
|
previousActiveChannelIndex: int
|
||||||
activeCommunity*: CommunityItemView
|
activeCommunity*: CommunityItemView
|
||||||
observedCommunity*: CommunityItemView
|
observedCommunity*: CommunityItemView
|
||||||
|
@ -54,6 +55,7 @@ QtObject:
|
||||||
proc delete(self: ChatsView) =
|
proc delete(self: ChatsView) =
|
||||||
self.chats.delete
|
self.chats.delete
|
||||||
self.activeChannel.delete
|
self.activeChannel.delete
|
||||||
|
self.contextChannel.delete
|
||||||
self.observedCommunity.delete
|
self.observedCommunity.delete
|
||||||
self.activeCommunity.delete
|
self.activeCommunity.delete
|
||||||
self.currentSuggestions.delete
|
self.currentSuggestions.delete
|
||||||
|
@ -73,6 +75,7 @@ QtObject:
|
||||||
result.connected = false
|
result.connected = false
|
||||||
result.chats = newChannelsList(status)
|
result.chats = newChannelsList(status)
|
||||||
result.activeChannel = newChatItemView(status)
|
result.activeChannel = newChatItemView(status)
|
||||||
|
result.contextChannel = newChatItemView(status)
|
||||||
result.activeCommunity = newCommunityItemView(status)
|
result.activeCommunity = newCommunityItemView(status)
|
||||||
result.observedCommunity = newCommunityItemView(status)
|
result.observedCommunity = newCommunityItemView(status)
|
||||||
result.currentSuggestions = newSuggestionsList()
|
result.currentSuggestions = newSuggestionsList()
|
||||||
|
@ -190,6 +193,8 @@ QtObject:
|
||||||
|
|
||||||
proc activeChannelChanged*(self: ChatsView) {.signal.}
|
proc activeChannelChanged*(self: ChatsView) {.signal.}
|
||||||
|
|
||||||
|
proc contextChannelChanged*(self: ChatsView) {.signal.}
|
||||||
|
|
||||||
proc sendingMessage*(self: ChatsView) {.signal.}
|
proc sendingMessage*(self: ChatsView) {.signal.}
|
||||||
|
|
||||||
proc appReady*(self: ChatsView) {.signal.}
|
proc appReady*(self: ChatsView) {.signal.}
|
||||||
|
@ -267,6 +272,19 @@ QtObject:
|
||||||
write = setActiveChannel
|
write = setActiveChannel
|
||||||
notify = activeChannelChanged
|
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.} =
|
proc setActiveChannelToTimeline*(self: ChatsView) {.slot.} =
|
||||||
if not self.activeChannel.chatItem.isNil:
|
if not self.activeChannel.chatItem.isNil:
|
||||||
self.previousActiveChannelIndex = self.chats.chats.findIndexById(self.activeChannel.id)
|
self.previousActiveChannelIndex = self.chats.chats.findIndexById(self.activeChannel.id)
|
||||||
|
|
|
@ -38,7 +38,7 @@ Rectangle {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
switch (chatsModel.activeChannel.chatType) {
|
switch (chatsModel.activeChannel.chatType) {
|
||||||
case Constants.chatTypePrivateGroupChat:
|
case Constants.chatTypePrivateGroupChat:
|
||||||
groupInfoPopup.open()
|
groupInfoPopup.openMenu(chatsModel.activeChannel, chatsModel.getActiveChannelIdx())
|
||||||
break;
|
break;
|
||||||
case Constants.chatTypeOneToOne:
|
case Constants.chatTypeOneToOne:
|
||||||
const profileImage = appMain.getProfileImage(chatsModel.activeChannel.id)
|
const profileImage = appMain.getProfileImage(chatsModel.activeChannel.id)
|
||||||
|
@ -128,7 +128,7 @@ Rectangle {
|
||||||
icon.height: chatTopBarContent.iconSize
|
icon.height: chatTopBarContent.iconSize
|
||||||
//% "Group Information"
|
//% "Group Information"
|
||||||
text: qsTrId("group-information")
|
text: qsTrId("group-information")
|
||||||
onTriggered: groupInfoPopup.open()
|
onTriggered: groupInfoPopup.openMenu(chatsModel.activeChannel, chatsModel.getActiveChannelIdx())
|
||||||
}
|
}
|
||||||
Action {
|
Action {
|
||||||
icon.source: "../../../img/close.svg"
|
icon.source: "../../../img/close.svg"
|
||||||
|
|
|
@ -168,12 +168,13 @@ Rectangle {
|
||||||
wrapper.hovered = false
|
wrapper.hovered = false
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
chatsModel.setActiveChannelByIndex(index)
|
|
||||||
chatGroupsListView.currentIndex = index
|
|
||||||
if (mouse.button & Qt.RightButton) {
|
if (mouse.button & Qt.RightButton) {
|
||||||
channelContextMenu.openMenu(chatsModel.activeChannel, index)
|
chatsModel.setContextChannel(chatId)
|
||||||
|
channelContextMenu.openMenu(chatsModel.contextChannel, index)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
chatsModel.setActiveChannelByIndex(index)
|
||||||
|
chatGroupsListView.currentIndex = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,8 @@ import "../../../../imports"
|
||||||
|
|
||||||
PopupMenu {
|
PopupMenu {
|
||||||
property int channelIndex
|
property int channelIndex
|
||||||
property bool channelMuted
|
property var contextChannel
|
||||||
property int chatType
|
|
||||||
property string chatName
|
|
||||||
property string chatId
|
|
||||||
property string chatIdenticon
|
|
||||||
property var groupInfoPopup
|
property var groupInfoPopup
|
||||||
property var groupsListView
|
|
||||||
|
|
||||||
id: channelContextMenu
|
id: channelContextMenu
|
||||||
width: 175
|
width: 175
|
||||||
|
@ -31,11 +26,7 @@ PopupMenu {
|
||||||
]
|
]
|
||||||
|
|
||||||
function openMenu(channel, index) {
|
function openMenu(channel, index) {
|
||||||
channelContextMenu.channelMuted = channel.muted
|
channelContextMenu.contextChannel = channel
|
||||||
channelContextMenu.chatType = channel.chatType
|
|
||||||
channelContextMenu.chatName = channel.name
|
|
||||||
channelContextMenu.chatId = channel.id
|
|
||||||
channelContextMenu.chatIdenticon = channel.identicon
|
|
||||||
if (index !== undefined) {
|
if (index !== undefined) {
|
||||||
channelContextMenu.channelIndex = index
|
channelContextMenu.channelIndex = index
|
||||||
}
|
}
|
||||||
|
@ -43,13 +34,13 @@ PopupMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
Action {
|
Action {
|
||||||
enabled: channelContextMenu.chatType !== Constants.chatTypePublic
|
enabled: channelContextMenu.contextChannel.chatType !== Constants.chatTypePublic
|
||||||
text: {
|
text: {
|
||||||
if (channelContextMenu.chatType === Constants.chatTypeOneToOne) {
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) {
|
||||||
//% "View Profile"
|
//% "View Profile"
|
||||||
return qsTrId("view-profile")
|
return qsTrId("view-profile")
|
||||||
}
|
}
|
||||||
if (channelContextMenu.chatType === Constants.chatTypePrivateGroupChat) {
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) {
|
||||||
//% "View Group"
|
//% "View Group"
|
||||||
return qsTrId("view-group")
|
return qsTrId("view-group")
|
||||||
}
|
}
|
||||||
|
@ -60,16 +51,16 @@ PopupMenu {
|
||||||
icon.width: 16
|
icon.width: 16
|
||||||
icon.height: 16
|
icon.height: 16
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
//chatsModel.setActiveChannelByIndex(channelContextMenu.channelIndex)
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) {
|
||||||
if (!!groupsListView) {
|
const userProfileImage = appMain.getProfileImage(channelContextMenu.contextChannel.id)
|
||||||
groupsListView.currentIndex = channelContextMenu.channelIndex
|
return openProfilePopup(
|
||||||
|
channelContextMenu.contextChannel.name,
|
||||||
|
channelContextMenu.contextChannel.id,
|
||||||
|
userProfileImage || channelContextMenu.contextChannel.identicon
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (channelContextMenu.chatType === Constants.chatTypeOneToOne) {
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) {
|
||||||
const userProfileImage = appMain.getProfileImage(channelContextMenu.chatId)
|
return groupInfoPopup.openMenu(channelContextMenu.contextChannel)
|
||||||
return openProfilePopup(channelContextMenu.chatName, channelContextMenu.chatId, userProfileImage || channelContextMenu.chatIdenticon)
|
|
||||||
}
|
|
||||||
if (channelContextMenu.chatType === Constants.chatTypePrivateGroupChat) {
|
|
||||||
return groupInfoPopup.open()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +68,7 @@ PopupMenu {
|
||||||
Separator {}
|
Separator {}
|
||||||
|
|
||||||
Action {
|
Action {
|
||||||
text: channelContextMenu.channelMuted ?
|
text: channelContextMenu.contextChannel.muted ?
|
||||||
//% "Unmute chat"
|
//% "Unmute chat"
|
||||||
qsTrId("unmute-chat") :
|
qsTrId("unmute-chat") :
|
||||||
//% "Mute chat"
|
//% "Mute chat"
|
||||||
|
@ -118,11 +109,11 @@ PopupMenu {
|
||||||
|
|
||||||
Action {
|
Action {
|
||||||
text: {
|
text: {
|
||||||
if (channelContextMenu.chatType === Constants.chatTypeOneToOne) {
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) {
|
||||||
//% "Delete chat"
|
//% "Delete chat"
|
||||||
return qsTrId("delete-chat")
|
return qsTrId("delete-chat")
|
||||||
}
|
}
|
||||||
if (channelContextMenu.chatType === Constants.chatTypePrivateGroupChat) {
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) {
|
||||||
//% "Leave group"
|
//% "Leave group"
|
||||||
return qsTrId("leave-group")
|
return qsTrId("leave-group")
|
||||||
}
|
}
|
||||||
|
@ -130,7 +121,7 @@ PopupMenu {
|
||||||
return qsTrId("leave-chat")
|
return qsTrId("leave-chat")
|
||||||
}
|
}
|
||||||
icon.source: {
|
icon.source: {
|
||||||
if (channelContextMenu.chatType === Constants.chatTypeOneToOne) {
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypeOneToOne) {
|
||||||
return "../../../img/delete.svg"
|
return "../../../img/delete.svg"
|
||||||
}
|
}
|
||||||
return "../../../img/leave_chat.svg"
|
return "../../../img/leave_chat.svg"
|
||||||
|
|
|
@ -13,18 +13,19 @@ ModalPopup {
|
||||||
property int memberCount: 1
|
property int memberCount: 1
|
||||||
readonly property int maxMembers: 10
|
readonly property int maxMembers: 10
|
||||||
property var pubKeys: []
|
property var pubKeys: []
|
||||||
|
property var channel
|
||||||
property bool isAdmin: false
|
property bool isAdmin: false
|
||||||
|
|
||||||
function resetSelectedMembers(){
|
function resetSelectedMembers(){
|
||||||
pubKeys = [];
|
pubKeys = [];
|
||||||
memberCount = chatsModel.activeChannel.members.rowCount();
|
memberCount = channel.members.rowCount();
|
||||||
currMemberCount = memberCount;
|
currMemberCount = memberCount;
|
||||||
contactList.membersData.clear();
|
contactList.membersData.clear();
|
||||||
|
|
||||||
const contacts = chatView.getContactListObject()
|
const contacts = chatView.getContactListObject()
|
||||||
|
|
||||||
contacts.forEach(function (contact) {
|
contacts.forEach(function (contact) {
|
||||||
if(chatsModel.activeChannel.contains(contact.pubKey) ||
|
if(popup.channel.contains(contact.pubKey) ||
|
||||||
!contact.isContact) {
|
!contact.isContact) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -32,16 +33,21 @@ ModalPopup {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openMenu(channel) {
|
||||||
|
popup.channel = channel
|
||||||
|
popup.open()
|
||||||
|
}
|
||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
addMembers = false;
|
addMembers = false;
|
||||||
popup.isAdmin = chatsModel.activeChannel.isAdmin(profileModel.profile.pubKey)
|
popup.isAdmin = popup.channel.isAdmin(profileModel.profile.pubKey)
|
||||||
btnSelectMembers.enabled = false;
|
btnSelectMembers.enabled = false;
|
||||||
resetSelectedMembers();
|
resetSelectedMembers();
|
||||||
}
|
}
|
||||||
|
|
||||||
function doAddMembers(){
|
function doAddMembers(){
|
||||||
if(pubKeys.length === 0) return;
|
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();
|
popup.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,14 +61,14 @@ ModalPopup {
|
||||||
width: 36
|
width: 36
|
||||||
height: 36
|
height: 36
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
color: chatsModel.activeChannel.color
|
color: popup.channel.color
|
||||||
chatName: chatsModel.activeChannel.name
|
chatName: popup.channel.name
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledTextEdit {
|
StyledTextEdit {
|
||||||
id: groupName
|
id: groupName
|
||||||
//% "Add members"
|
//% "Add members"
|
||||||
text: addMembers ? qsTrId("add-members") : chatsModel.activeChannel.name
|
text: addMembers ? qsTrId("add-members") : popup.channel.name
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 2
|
anchors.topMargin: 2
|
||||||
anchors.left: letterIdenticon.right
|
anchors.left: letterIdenticon.right
|
||||||
|
@ -174,7 +180,7 @@ ModalPopup {
|
||||||
pubKeys.splice(idx, 1);
|
pubKeys.splice(idx, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memberCount = chatsModel.activeChannel.members.rowCount() + pubKeys.length;
|
memberCount = popup.channel.members.rowCount() + pubKeys.length;
|
||||||
btnSelectMembers.enabled = pubKeys.length > 0
|
btnSelectMembers.enabled = pubKeys.length > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,7 +207,7 @@ ModalPopup {
|
||||||
spacing: 15
|
spacing: 15
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
model: chatsModel.activeChannel.members
|
model: popup.channel.members
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: contactRow
|
id: contactRow
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -273,14 +279,14 @@ ModalPopup {
|
||||||
icon.source: "../../../img/make-admin.svg"
|
icon.source: "../../../img/make-admin.svg"
|
||||||
//% "Make Admin"
|
//% "Make Admin"
|
||||||
text: qsTrId("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 {
|
Action {
|
||||||
icon.source: "../../../img/remove-from-group.svg"
|
icon.source: "../../../img/remove-from-group.svg"
|
||||||
icon.color: Style.current.red
|
icon.color: Style.current.red
|
||||||
//% "Remove From Group"
|
//% "Remove From Group"
|
||||||
text: qsTrId("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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue