feat(Components): introduce `StatusChatListAndCategories` component

This is a wrapping component that can be used to render community chat
lists and categories. It takes care of rendering categories, the top
chat list, as well as becominng scrollable in case the content outgrows
the available space.

Usage:

```qml
import StatusQ.Components 0.1

StatusChatListAndCategories {

    chatList.model: ... // non-categorized chat items, pass all chat items here, the component will take care of filtering categorized items out
    categoryListModel: ... // available categories (need to have `id` and `name`)

    selectedChatId: ...

    showCategoryActionButtons: true // default `false` - useful when only admin users can create and mutate categories/channels

    onChatItemSelected: ... // `id` is available for selected chat id

    categoryPopupMenu: StatusPopupMenu { // optional popup menu for category items

        property string categoryId // define this property to have it hydrated with correct id and make it available inside menu items
        ...
    }

    popupMenu: StatusPopupMenu { ... } // optional popup menu for whole list, will be triggered with right-click
}
```

Closes #133
This commit is contained in:
Pascal Precht 2021-06-15 16:27:39 +02:00 committed by Michał Cieślak
parent 4582886d90
commit 209a208455
4 changed files with 163 additions and 45 deletions

View File

@ -157,23 +157,18 @@ Rectangle {
StatusAppTwoPanelLayout { StatusAppTwoPanelLayout {
leftPanel: Item { leftPanel: StatusChatListAndCategories {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 64
StatusChatList { chatList.model: demoChatListItems
anchors.top: parent.top selectedChatId: "0"
anchors.topMargin: 64 onChatItemSelected: selectedChatId = id
anchors.horizontalCenter: parent.horizontalCenter onChatItemUnmuted: {
for (var i = 0; i < demoChatListItems.count; i++) {
selectedChatId: "0" let item = demoChatListItems.get(i);
chatListItems.model: demoChatListItems if (item.chatId === id) {
onChatItemSelected: selectedChatId = id demoChatListItems.setProperty(i, "muted", false)
onChatItemUnmuted: {
for (var i = 0; i < demoChatListItems.count; i++) {
let item = demoChatListItems.get(i);
if (item.chatId === id) {
demoChatListItems.setProperty(i, "muted", false)
}
} }
} }
} }
@ -233,10 +228,16 @@ Rectangle {
StatusAppTwoPanelLayout { StatusAppTwoPanelLayout {
leftPanel: Item { leftPanel: Item {
anchors.fill: parent anchors.fill: parent
StatusChatInfoToolBar { StatusChatInfoToolBar {
id: statusChatInfoToolBar
anchors.top: parent.top
chatInfoButton.title: "Cryptokitties" chatInfoButton.title: "Cryptokitties"
chatInfoButton.subTitle: "128 Members" chatInfoButton.subTitle: "128 Members"
chatInfoButton.image.source: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg" chatInfoButton.image.source: "https://pbs.twimg.com/profile_images/1369221718338895873/T_5fny6o_400x400.jpg"
@ -265,41 +266,22 @@ Rectangle {
} }
} }
Column { StatusChatListAndCategories {
anchors.top: parent.top anchors.top: statusChatInfoToolBar.bottom
anchors.topMargin: 64 anchors.topMargin: 8
anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom
spacing: 4 width: parent.width
StatusChatList { chatList.model: demoCommunityChatListItems
id: statusChatList categoryList.model: demoCommunityCategoryItems
anchors.horizontalCenter: parent.horizontalCenter
chatListItems.model: demoCommunityChatListItems
}
StatusChatListCategory { showCategoryActionButtons: true
name: "Public" onChatItemSelected: selectedChatId = id
showActionButtons: true
chatList.chatListItems.model: demoCommunityChatListItems
chatList.selectedChatId: "0"
chatList.onChatItemSelected: chatList.selectedChatId = id
popupMenu: categoryPopupCmp
}
StatusChatListCategory { categoryPopupMenu: StatusPopupMenu {
name: "Development"
showActionButtons: true property string categoryId
chatList.chatListItems.model: demoCommunityChatListItems
chatList.onChatItemSelected: chatList.selectedChatId = id
popupMenu: categoryPopupCmp
}
}
Component {
id: categoryPopupCmp
StatusPopupMenu {
StatusMenuItem { StatusMenuItem {
text: "Mute Category" text: "Mute Category"
icon.name: "notification" icon.name: "notification"
@ -323,8 +305,29 @@ Rectangle {
type: StatusMenuItem.Type.Danger type: StatusMenuItem.Type.Danger
} }
} }
popupMenu: StatusPopupMenu {
StatusMenuItem {
text: "Create channel"
icon.name: "channel"
}
StatusMenuItem {
text: "Create category"
icon.name: "channel-category"
}
StatusMenuSeparator {}
StatusMenuItem {
text: "Invite people"
icon.name: "share-ios"
}
}
} }
} }
rightPanel: Item { rightPanel: Item {
anchors.fill: parent anchors.fill: parent
@ -413,6 +416,7 @@ Rectangle {
hasMention: false hasMention: false
unreadMessagesCount: 0 unreadMessagesCount: 0
iconColor: "orange" iconColor: "orange"
categoryId: "public"
} }
ListElement { ListElement {
chatId: "2" chatId: "2"
@ -423,6 +427,30 @@ Rectangle {
hasMention: false hasMention: false
unreadMessagesCount: 0 unreadMessagesCount: 0
iconColor: "orange" iconColor: "orange"
categoryId: "public"
}
ListElement {
chatId: "3"
name: "language-design"
chatType: StatusChatListItem.Type.CommunityChat
muted: false
hasUnreadMessages: false
hasMention: false
unreadMessagesCount: 0
iconColor: "orange"
categoryId: "dev"
}
}
ListModel {
id: demoCommunityCategoryItems
ListElement {
categoryId: "public"
name: "Public"
}
ListElement {
categoryId: "dev"
name: "Development"
} }
} }
} }

View File

@ -0,0 +1,88 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import StatusQ.Components 0.1
import StatusQ.Popups 0.1
ScrollView {
id: statusChatListAndCategories
clip: true
contentHeight: chatListsAndCategories.height + 8
property string selectedChatId: ""
property bool showCategoryActionButtons: false
property alias chatList: statusChatList.chatListItems
property alias categoryList: statusChatListCategories
property alias sensor: sensor
property Component categoryPopupMenu
property Component popupMenu
signal chatItemSelected(string id)
signal chatItemUnmuted(string id)
signal categoryAddButtonClicked(string id)
onPopupMenuChanged: {
if (!!popupMenu) {
popupMenuSlot.sourceComponent = popupMenu
}
}
MouseArea {
id: sensor
anchors.top: parent.top
width: parent.width
height: statusChatListAndCategories.height
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button === Qt.RightButton && !!statusChatListAndCategories.popupMenu) {
popupMenuSlot.item.popup(mouse.x + 4, mouse.y + 6)
return
}
}
Column {
id: chatListsAndCategories
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
spacing: 4
StatusChatList {
id: statusChatList
anchors.horizontalCenter: parent.horizontalCenter
visible: !!chatListItems.model && chatListItems.model.count > 0
selectedChatId: statusChatListAndCategories.selectedChatId
onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
filterFn: function (model) {
return !!!model.categoryId
}
}
Repeater {
id: statusChatListCategories
visible: !!model && model.count > 0
delegate: StatusChatListCategory {
categoryId: model.categoryId
name: model.name
showActionButtons: statusChatListAndCategories.showCategoryActionButtons
addButton.onClicked: statusChatListAndCategories.categoryAddButtonClicked(model.categoryId)
chatList.chatListItems.model: statusChatListAndCategories.chatList.model
chatList.selectedChatId: statusChatListAndCategories.selectedChatId
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
popupMenu: statusChatListAndCategories.categoryPopupMenu
}
}
}
}
Loader {
id: popupMenuSlot
active: !!statusChatListAndCategories.popupMenu
}
}

View File

@ -6,6 +6,7 @@ StatusChatList 0.1 StatusChatList.qml
StatusChatListItem 0.1 StatusChatListItem.qml StatusChatListItem 0.1 StatusChatListItem.qml
StatusChatListCategory 0.1 StatusChatListCategory.qml StatusChatListCategory 0.1 StatusChatListCategory.qml
StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
StatusChatListAndCategories 0.1 StatusChatListAndCategories.qml
StatusChatToolBar 0.1 StatusChatToolBar.qml StatusChatToolBar 0.1 StatusChatToolBar.qml
StatusDescriptionListItem 0.1 StatusDescriptionListItem.qml StatusDescriptionListItem 0.1 StatusDescriptionListItem.qml
StatusLetterIdenticon 0.1 StatusLetterIdenticon.qml StatusLetterIdenticon 0.1 StatusLetterIdenticon.qml

View File

@ -18,6 +18,7 @@
<file>src/StatusQ/Popups/StatusMenuItem.qml</file> <file>src/StatusQ/Popups/StatusMenuItem.qml</file>
<file>src/StatusQ/Components/qmldir</file> <file>src/StatusQ/Components/qmldir</file>
<file>src/StatusQ/Components/StatusChatListItem.qml</file> <file>src/StatusQ/Components/StatusChatListItem.qml</file>
<file>src/StatusQ/Components/StatusChatListAndCategories.qml</file>
<file>src/StatusQ/Components/StatusChatInfoToolBar.qml</file> <file>src/StatusQ/Components/StatusChatInfoToolBar.qml</file>
<file>src/StatusQ/Components/StatusNavigationListItem.qml</file> <file>src/StatusQ/Components/StatusNavigationListItem.qml</file>
<file>src/StatusQ/Components/StatusChatToolBar.qml</file> <file>src/StatusQ/Components/StatusChatToolBar.qml</file>