feat(StatusChatList): introduce `popupMenu` property

Chat list items can open a context on right click as well, so `StatusChatList`
needs to provide an API for users to pass down a `StatusPopupMenu` accordingly.

This is now possible with a dedicated `popupMenu` proporty that can be
used as follows:

```qml
StatusChatList {
    ...
    popupMenu: StatusPopupMenu {

        property string chatId

        openHandler: function () {
            ...
        }

        StatusMenuItem {
            ...
        }
        ...
    }
}
```

As will all `popupMenu` properties in StatusQ component, having this explicit API
option enables us to have control over how triggering components (in this case chat
list items) behave when they open a context menu (e.g. keeping them highlighted as long
as the menu is active).

When defining a `chatId` property, `StatusChatList` will hydrate it with the id of
the chat list item that has triggered the menu.

If there's more logic to be executed upon opening the menu, `openHandler` serves
as a hook similar to other popup menus. Inside the hook, users have access to the
specific `chatId`.

Closes #171
This commit is contained in:
Pascal Precht 2021-06-23 12:04:19 +02:00 committed by Michał Cieślak
parent 4d595221eb
commit c2f418205f
4 changed files with 113 additions and 3 deletions

View File

@ -181,6 +181,7 @@ Rectangle {
chatListItems.model: demoChatListItems
selectedChatId: "0"
onChatItemSelected: selectedChatId = id
onChatItemUnmuted: {
for (var i = 0; i < demoChatListItems.count; i++) {
@ -190,6 +191,41 @@ Rectangle {
}
}
}
popupMenu: StatusPopupMenu {
property string chatId
StatusMenuItem {
text: "View Profile"
icon.name: "group-chat"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Mute chat"
icon.name: "notification"
}
StatusMenuItem {
text: "Mark as Read"
icon.name: "checkmark-circle"
}
StatusMenuItem {
text: "Clear history"
icon.name: "close-circle"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Delete chat"
icon.name: "delete"
type: StatusMenuItem.Type.Danger
}
}
}
}
@ -334,6 +370,33 @@ Rectangle {
}
}
chatListPopupMenu: StatusPopupMenu {
property string chatId
StatusMenuItem {
text: "Mute chat"
icon.name: "notification"
}
StatusMenuItem {
text: "Mark as Read"
icon.name: "checkmark-circle"
}
StatusMenuItem {
text: "Clear history"
icon.name: "close-circle"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Delete chat"
icon.name: "delete"
type: StatusMenuItem.Type.Danger
}
}
popupMenu: StatusPopupMenu {
StatusMenuItem {

View File

@ -15,15 +15,24 @@ Column {
property string selectedChatId: ""
property alias chatListItems: statusChatListItems
property Component popupMenu
property var filterFn
signal chatItemSelected(string id)
signal chatItemUnmuted(string id)
onPopupMenuChanged: {
if (!!popupMenu) {
popupMenuSlot.sourceComponent = popupMenu
}
}
Repeater {
id: statusChatListItems
delegate: StatusChatListItem {
chatId: model.chatId
id: statusChatListItem
chatId: model.chatId || model.id
name: model.name
type: model.chatType
muted: !!model.muted
@ -35,8 +44,36 @@ Column {
icon.color: model.color || ""
image.source: model.identicon || ""
onClicked: statusChatList.chatItemSelected(model.chatId)
onUnmute: statusChatList.chatItemUnmuted(model.chatId)
onClicked: {
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
highlighted = true
let originalOpenHandler = popupMenuSlot.item.openHandler
let originalCloseHandler = popupMenuSlot.item.closeHandler
popupMenuSlot.item.openHandler = function () {
if (popupMenuSlot.item.hasOwnProperty('chatId')) {
popupMenuSlot.item.chatId = model.chatId || model.id
}
if (!!originalOpenHandler) {
originalOpenHandler()
}
}
popupMenuSlot.item.closeHandler = function () {
highlighted = false
if (!!originalCloseHandler) {
originalCloseHandler()
}
}
popupMenuSlot.item.popup(mouse.x + 4, statusChatListItem.y + mouse.y + 6)
popupMenuSlot.item.openHandler = originalOpenHandler
return
}
statusChatList.chatItemSelected(model.chatId || model.id)
}
onUnmute: statusChatList.chatItemUnmuted(model.chatId || model.id)
visible: {
if (!!statusChatList.filterFn) {
return statusChatList.filterFn(model, statusChatList.categoryId)
@ -45,4 +82,9 @@ Column {
}
}
}
Loader {
id: popupMenuSlot
active: !!statusChatList.popupMenu
}
}

View File

@ -17,6 +17,7 @@ Item {
property alias sensor: sensor
property Component categoryPopupMenu
property Component chatListPopupMenu
property Component popupMenu
signal chatItemSelected(string id)
@ -76,6 +77,7 @@ Item {
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
popupMenu: statusChatListAndCategories.categoryPopupMenu
chatListPopupMenu: statusChatListAndCategories.chatListPopupMenu
}
}
}

View File

@ -18,6 +18,7 @@ Column {
property alias toggleButton: statusChatListCategoryItem.toggleButton
property alias chatList: statusChatList
property Component chatListPopupMenu
property Component popupMenu
onPopupMenuChanged: {
@ -59,6 +60,8 @@ Column {
filterFn: function (model) {
return !!model.categoryId && model.categoryId == statusChatList.categoryId
}
popupMenu: statusChatListCategory.chatListPopupMenu
}
Loader {