feat(StatusChatList): Add drag and drop support of list items

This implements drag and drop capabilities of chat items within a `StatusChatList`.
The commit introduces a `DelegateModal` to visually reorder chat items
when they're being dragged and dropped onto a `DropArea`.

To persist the new order of chat items, various signals have been introduced to chat
list related components:

```qml
StatusChatList {

    onChatItemReordered: function (id, from, to) {
        // ...
    }
}

StatusChatListAndCategories {

    onChatItemReordered: function (categoryId, chatId, from, to) {
        // ...
    }
}
```

There's no such API on the `StatusChatListCategory` type because that one already
exposes its underlying `StatusChatList` via `chatList`, which makes the signal available.

Dragging and dropping chat items is disabled by default and needs to be turned on
using the `draggableItems` property:

```qml
StatusChatList {
    draggableItems: true
    ...
}
```
This commit is contained in:
B.Melnik 2021-07-28 14:08:56 +03:00 committed by Michał Cieślak
parent 67031ad5b1
commit 85ee81cfa3
5 changed files with 254 additions and 96 deletions

View File

@ -467,6 +467,7 @@ Rectangle {
width: leftPanel.width width: leftPanel.width
height: implicitHeight > (leftPanel.height - 64) ? implicitHeight + 8 : leftPanel.height - 64 height: implicitHeight > (leftPanel.height - 64) ? implicitHeight + 8 : leftPanel.height - 64
draggableItems: true
chatList.model: models.demoCommunityChatListItems chatList.model: models.demoCommunityChatListItems
categoryList.model: models.demoCommunityCategoryItems categoryList.model: models.demoCommunityCategoryItems

View File

@ -13,6 +13,7 @@ QtObject {
unreadMessagesCount: 0 unreadMessagesCount: 0
mentionsCount: 0 mentionsCount: 0
color: "blue" color: "blue"
position: 0
} }
ListElement { ListElement {
chatId: "1" chatId: "1"
@ -22,6 +23,7 @@ QtObject {
color: "red" color: "red"
unreadMessagesCount: 1 unreadMessagesCount: 1
mentionsCount: 1 mentionsCount: 1
position: 1
} }
ListElement { ListElement {
chatId: "2" chatId: "2"
@ -32,6 +34,7 @@ QtObject {
identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC" CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
unreadMessagesCount: 0 unreadMessagesCount: 0
position: 2
} }
ListElement { ListElement {
chatId: "3" chatId: "3"
@ -40,6 +43,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
muted: false muted: false
color: "purple" color: "purple"
unreadMessagesCount: 0 unreadMessagesCount: 0
position: 3
} }
ListElement { ListElement {
chatId: "4" chatId: "4"
@ -48,6 +52,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
muted: true muted: true
color: "Orange" color: "Orange"
unreadMessagesCount: 0 unreadMessagesCount: 0
position: 4
} }
ListElement { ListElement {
chatId: "5" chatId: "5"
@ -56,6 +61,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
muted: false muted: false
color: "green" color: "green"
unreadMessagesCount: 0 unreadMessagesCount: 0
position: 5
} }
} }
@ -68,6 +74,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
muted: false muted: false
unreadMessagesCount: 0 unreadMessagesCount: 0
color: "orange" color: "orange"
position: 0
} }
ListElement { ListElement {
chatId: "1" chatId: "1"
@ -77,6 +84,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
unreadMessagesCount: 0 unreadMessagesCount: 0
color: "orange" color: "orange"
categoryId: "public" categoryId: "public"
position: 0
} }
ListElement { ListElement {
chatId: "2" chatId: "2"
@ -86,6 +94,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
unreadMessagesCount: 0 unreadMessagesCount: 0
color: "orange" color: "orange"
categoryId: "public" categoryId: "public"
position: 1
} }
ListElement { ListElement {
chatId: "3" chatId: "3"
@ -95,6 +104,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
unreadMessagesCount: 0 unreadMessagesCount: 0
color: "orange" color: "orange"
categoryId: "dev" categoryId: "dev"
position: 0
} }
} }

View File

@ -1,4 +1,6 @@
import QtQuick 2.13 import QtQuick 2.13
import QtQml.Models 2.14
import QtQuick.Controls 2.13 as QC
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
@ -13,7 +15,8 @@ Column {
property string categoryId: "" property string categoryId: ""
property string selectedChatId: "" property string selectedChatId: ""
property alias chatListItems: statusChatListItems property alias chatListItems: delegateModel
property bool draggableItems: false
property Component popupMenu property Component popupMenu
@ -23,6 +26,19 @@ Column {
signal chatItemSelected(string id) signal chatItemSelected(string id)
signal chatItemUnmuted(string id) signal chatItemUnmuted(string id)
signal chatItemReordered(string id, int from, int to)
function getAbsolutePosition(node) {
var returnPos = {};
returnPos.x = 0;
returnPos.y = 0;
if (node !== undefined && node !== null) {
var parentValue = getAbsolutePosition(node.parent);
returnPos.x = parentValue.x + node.x;
returnPos.y = parentValue.y + node.y;
}
return returnPos;
}
onPopupMenuChanged: { onPopupMenuChanged: {
if (!!popupMenu) { if (!!popupMenu) {
@ -30,75 +46,189 @@ Column {
} }
} }
Repeater { DelegateModel {
id: statusChatListItems id: delegateModel
delegate: StatusChatListItem {
id: statusChatListItem delegate: Item {
id: draggable
width: statusChatListItem.width
height: statusChatListItem.height
property string profileImage: "" property alias chatListItem: statusChatListItem
Component.onCompleted: {
if (typeof statusChatList.profileImageFn === "function") {
profileImage = statusChatList.profileImageFn(model.chatId || model.id) || ""
}
}
chatId: model.chatId || model.id
name: !!statusChatList.chatNameFn ? statusChatList.chatNameFn(model) : model.name
type: model.chatType
muted: !!model.muted
hasUnreadMessages: !!model.hasUnreadMessages || model.unviewedMessagesCount > 0
hasMention: model.mentionsCount > 0
badge.value: model.chatType === StatusChatListItem.Type.OneToOneChat ?
model.unviewedMessagesCount || 0 :
model.mentionsCount || 0
selected: (model.chatId || model.id) === statusChatList.selectedChatId
icon.color: model.color || ""
image.isIdenticon: !!!profileImage && !!!model.identityImage && !!model.identicon
image.source: profileImage || model.identityImage || model.identicon || ""
onClicked: {
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
statusChatListItem.highlighted = true
let originalOpenHandler = popupMenuSlot.item.openHandler
let originalCloseHandler = popupMenuSlot.item.closeHandler
popupMenuSlot.item.openHandler = function () {
if (!!originalOpenHandler) {
originalOpenHandler((model.chatId || model.id))
}
}
popupMenuSlot.item.closeHandler = function () {
if (statusChatListItem) {
statusChatListItem.highlighted = false
}
if (!!originalCloseHandler) {
originalCloseHandler()
}
}
popupMenuSlot.item.popup(mouse.x + 4, statusChatListItem.y + mouse.y + 6)
popupMenuSlot.item.openHandler = originalOpenHandler
return
}
if (!statusChatListItem.selected) {
statusChatList.chatItemSelected(model.chatId || model.id)
}
}
onUnmute: statusChatList.chatItemUnmuted(model.chatId || model.id)
visible: { visible: {
if (!!statusChatList.filterFn) { if (!!statusChatList.filterFn) {
return statusChatList.filterFn(model, statusChatList.categoryId) return statusChatList.filterFn(model, statusChatList.categoryId)
} }
return true return true
} }
MouseArea {
id: dragSensor
anchors.fill: parent
cursorShape: active ? Qt.ClosedHandCursor : Qt.PointingHandCursor
hoverEnabled: true
pressAndHoldInterval: 150
enabled: statusChatList.draggableItems
property bool active: false
property real startY: 0
property real startX: 0
drag.target: draggedListItemLoader.item
drag.threshold: 0.1
drag.filterChildren: true
onPressed: {
startY = mouseY
startX = mouseX
}
onPressAndHold: active = true
onReleased: {
if (active) {
statusChatList.chatItemReordered(statusChatListItem.chatId, statusChatListItem.originalOrder, statusChatListItem.originalOrder)
}
active = false
}
onMouseYChanged: {
if ((Math.abs(startY - mouseY) > 1) && pressed) {
active = true
}
}
onMouseXChanged: {
if ((Math.abs(startX - mouseX) > 1) && pressed) {
active = true
}
}
StatusChatListItem {
id: statusChatListItem
property string profileImage: ""
opacity: dragSensor.active ? 0.0 : 1.0
Component.onCompleted: {
if (typeof statusChatList.profileImageFn === "function") {
profileImage = statusChatList.profileImageFn(model.chatId || model.id) || ""
}
}
originalOrder: model.position
chatId: model.chatId || model.id
categoryId: model.categoryId || ""
name: !!statusChatList.chatNameFn ? statusChatList.chatNameFn(model) : model.name
type: model.chatType
muted: !!model.muted
hasUnreadMessages: !!model.hasUnreadMessages || model.unviewedMessagesCount > 0
hasMention: model.mentionsCount > 0
badge.value: model.chatType === StatusChatListItem.Type.OneToOneChat ?
model.unviewedMessagesCount || 0 :
model.mentionsCount || 0
selected: (model.chatId || model.id) === statusChatList.selectedChatId
icon.color: model.color || ""
image.isIdenticon: !!!profileImage && !!!model.identityImage && !!model.identicon
image.source: profileImage || model.identityImage || model.identicon || ""
sensor.cursorShape: dragSensor.cursorShape
onClicked: {
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
statusChatListItem.highlighted = true
let originalOpenHandler = popupMenuSlot.item.openHandler
let originalCloseHandler = popupMenuSlot.item.closeHandler
popupMenuSlot.item.openHandler = function () {
if (!!originalOpenHandler) {
originalOpenHandler((model.chatId || model.id))
}
}
popupMenuSlot.item.closeHandler = function () {
if (statusChatListItem) {
statusChatListItem.highlighted = false
}
if (!!originalCloseHandler) {
originalCloseHandler()
}
}
popupMenuSlot.item.popup(mouse.x + 4, statusChatListItem.y + mouse.y + 6)
popupMenuSlot.item.openHandler = originalOpenHandler
return
}
if (!statusChatListItem.selected) {
statusChatList.chatItemSelected(model.chatId || model.id)
}
}
onUnmute: statusChatList.chatItemUnmuted(model.chatId || model.id)
}
}
DropArea {
id: dropArea
width: dragSensor.active ? 0 : parent.width
height: dragSensor.active ? 0 : parent.height
keys: ["chat-item-category-" + statusChatListItem.categoryId]
onEntered: reorderDelay.start()
onDropped: statusChatList.chatItemReordered(statusChatListItem.chatId, drag.source.originalOrder, statusChatListItem.DelegateModel.itemsIndex)
Timer {
id: reorderDelay
interval: 100
repeat: false
onTriggered: {
if (dropArea.containsDrag) {
dropArea.drag.source.chatListItem.originalOrder = statusChatListItem.originalOrder
delegateModel.items.move(dropArea.drag.source.DelegateModel.itemsIndex, draggable.DelegateModel.itemsIndex)
}
}
}
}
Loader {
id: draggedListItemLoader
active: dragSensor.active
sourceComponent: StatusChatListItem {
property var globalPosition: statusChatList.getAbsolutePosition(draggable)
parent: QC.Overlay.overlay
sensor.cursorShape: dragSensor.cursorShape
Drag.active: dragSensor.active
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
Drag.keys: ["chat-item-category-" + categoryId]
Drag.source: draggable
Component.onCompleted: {
x = globalPosition.x
y = globalPosition.y
}
chatId: draggable.chatListItem.chatId
categoryId: draggable.chatListItem.categoryId
name: draggable.chatListItem.name
type: draggable.chatListItem.type
muted: draggable.chatListItem.muted
dragged: true
hasUnreadMessages: draggable.chatListItem.hasUnreadMessages
hasMention: draggable.chatListItem.hasMention
badge.value: draggable.chatListItem.badge.value
selected: draggable.chatListItem.selected
icon.color: draggable.chatListItem.icon.color
image.isIdenticon: draggable.chatListItem.image.isIdenticon
image.source: draggable.chatListItem.image.source
}
}
} }
} }
Repeater {
id: statusChatListItems
model: delegateModel
}
Loader { Loader {
id: popupMenuSlot id: popupMenuSlot
active: !!statusChatList.popupMenu active: !!statusChatList.popupMenu

View File

@ -16,6 +16,7 @@ Item {
property alias chatList: statusChatList.chatListItems property alias chatList: statusChatList.chatListItems
property alias categoryList: statusChatListCategories property alias categoryList: statusChatListCategories
property alias sensor: sensor property alias sensor: sensor
property bool draggableItems: false
property Component categoryPopupMenu property Component categoryPopupMenu
property Component chatListPopupMenu property Component chatListPopupMenu
@ -23,6 +24,7 @@ Item {
signal chatItemSelected(string id) signal chatItemSelected(string id)
signal chatItemUnmuted(string id) signal chatItemUnmuted(string id)
signal chatItemReordered(string categoryId, string chatId, int from, int to)
signal categoryAddButtonClicked(string id) signal categoryAddButtonClicked(string id)
onPopupMenuChanged: { onPopupMenuChanged: {
@ -54,14 +56,17 @@ Item {
StatusChatList { StatusChatList {
id: statusChatList id: statusChatList
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: !!chatListItems.model && chatListItems.count > 0 visible: chatListItems.count > 0
selectedChatId: statusChatListAndCategories.selectedChatId selectedChatId: statusChatListAndCategories.selectedChatId
onChatItemSelected: statusChatListAndCategories.chatItemSelected(id) onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id) onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
onChatItemReordered: statusChatListAndCategories.chatItemReordered(categoryId, id, from, to)
draggableItems: statusChatListAndCategories.draggableItems
filterFn: function (model) { filterFn: function (model) {
return !!!model.categoryId return !!!model.categoryId
} }
popupMenu: statusChatListAndCategories.chatListPopupMenu popupMenu: statusChatListAndCategories.chatListPopupMenu
} }
Repeater { Repeater {
@ -78,6 +83,8 @@ Item {
chatList.selectedChatId: statusChatListAndCategories.selectedChatId chatList.selectedChatId: statusChatListAndCategories.selectedChatId
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(id) chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
chatList.onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id) chatList.onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
chatList.onChatItemReordered: statusChatListAndCategories.chatItemReordered(model.categoryId, id, from, to)
chatList.draggableItems: statusChatListAndCategories.draggableItems
popupMenu: statusChatListAndCategories.categoryPopupMenu popupMenu: statusChatListAndCategories.categoryPopupMenu
chatListPopupMenu: statusChatListAndCategories.chatListPopupMenu chatListPopupMenu: statusChatListAndCategories.chatListPopupMenu

View File

@ -1,4 +1,8 @@
import QtQuick 2.13 import QtQuick 2.13
import QtQml.Models 2.13
import QtQuick.Controls 2.13 as QC
import QtGraphicalEffects 1.13
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
@ -7,7 +11,10 @@ import StatusQ.Controls 0.1
Rectangle { Rectangle {
id: statusChatListItem id: statusChatListItem
objectName: "chatItem"
property int originalOrder: -1
property string chatId: "" property string chatId: ""
property string categoryId: ""
property string name: "" property string name: ""
property alias badge: statusBadge property alias badge: statusBadge
property bool hasUnreadMessages: false property bool hasUnreadMessages: false
@ -20,6 +27,8 @@ Rectangle {
property int type: StatusChatListItem.Type.PublicChat property int type: StatusChatListItem.Type.PublicChat
property bool highlighted: false property bool highlighted: false
property bool selected: false property bool selected: false
property bool dragged: false
property alias sensor: sensor
signal clicked(var mouse) signal clicked(var mouse)
signal unmute() signal unmute()
@ -46,6 +55,8 @@ Rectangle {
return sensor.containsMouse || highlighted ? Theme.palette.statusChatListItem.hoverBackgroundColor : Theme.palette.baseColor4 return sensor.containsMouse || highlighted ? Theme.palette.statusChatListItem.hoverBackgroundColor : Theme.palette.baseColor4
} }
opacity: dragged ? 0.7 : 1
MouseArea { MouseArea {
id: sensor id: sensor
@ -63,7 +74,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
sourceComponent: !!statusChatListItem.image.source.toString() ? sourceComponent: !!statusChatListItem.image.source.toString() ?
statusRoundedImageCmp : statusLetterIdenticonCmp statusRoundedImageCmp : statusLetterIdenticonCmp
} }
Component { Component {
@ -89,8 +100,8 @@ Rectangle {
image.source: statusChatListItem.image.source image.source: statusChatListItem.image.source
showLoadingIndicator: true showLoadingIndicator: true
color: statusChatListItem.image.isIdenticon ? color: statusChatListItem.image.isIdenticon ?
Theme.palette.statusRoundedImage.backgroundColor : Theme.palette.statusRoundedImage.backgroundColor :
"transparent" "transparent"
border.width: statusChatListItem.image.isIdenticon ? 1 : 0 border.width: statusChatListItem.image.isIdenticon ? 1 : 0
border.color: Theme.palette.directColor7 border.color: Theme.palette.directColor7
} }
@ -115,26 +126,26 @@ Rectangle {
return 0.4 return 0.4
} }
return statusChatListItem.hasMention || return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages || statusChatListItem.hasUnreadMessages ||
statusChatListItem.selected || statusChatListItem.selected ||
statusChatListItem.highlighted || statusChatListItem.highlighted ||
statusBadge.visible || statusBadge.visible ||
sensor.containsMouse ? 1.0 : 0.7 sensor.containsMouse ? 1.0 : 0.7
} }
icon: { icon: {
switch (statusChatListItem.type) { switch (statusChatListItem.type) {
case StatusChatListItem.Type.PublicCat: case StatusChatListItem.Type.PublicCat:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white" return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
break; break;
case StatusChatListItem.Type.GroupChat: case StatusChatListItem.Type.GroupChat:
return Theme.palette.name == "light" ? "tiny/group" : "tiny/group-white" return Theme.palette.name == "light" ? "tiny/group" : "tiny/group-white"
break; break;
case StatusChatListItem.Type.CommunityChat: case StatusChatListItem.Type.CommunityChat:
return Theme.palette.name == "light" ? "tiny/channel" : "tiny/channel-white" return Theme.palette.name == "light" ? "tiny/channel" : "tiny/channel-white"
break; break;
default: default:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white" return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
} }
} }
} }
@ -144,30 +155,30 @@ Rectangle {
anchors.left: statusIcon.visible ? statusIcon.right : identicon.right anchors.left: statusIcon.visible ? statusIcon.right : identicon.right
anchors.leftMargin: statusIcon.visible ? 1 : 8 anchors.leftMargin: statusIcon.visible ? 1 : 8
anchors.right: mutedIcon.visible ? mutedIcon.left : anchors.right: mutedIcon.visible ? mutedIcon.left :
statusBadge.visible ? statusBadge.left : parent.right statusBadge.visible ? statusBadge.left : parent.right
anchors.rightMargin: 6 anchors.rightMargin: 6
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: statusChatListItem.type === StatusChatListItem.Type.PublicChat && text: (statusChatListItem.type === StatusChatListItem.Type.PublicChat &&
!statusChatListItem.name.startsWith("#") ? !statusChatListItem.name.startsWith("#") ?
"#" + statusChatListItem.name : "#" + statusChatListItem.name :
statusChatListItem.name statusChatListItem.name)
elide: Text.ElideRight elide: Text.ElideRight
color: { color: {
if (statusChatListItem.muted && !sensor.containsMouse && !statusChatListItem.highlighted) { if (statusChatListItem.muted && !sensor.containsMouse && !statusChatListItem.highlighted) {
return Theme.palette.directColor5 return Theme.palette.directColor5
} }
return statusChatListItem.hasMention || return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages || statusChatListItem.hasUnreadMessages ||
statusChatListItem.selected || statusChatListItem.selected ||
statusChatListItem.highlighted || statusChatListItem.highlighted ||
sensor.containsMouse || sensor.containsMouse ||
statusBadge.visible ? Theme.palette.directColor1 : Theme.palette.directColor4 statusBadge.visible ? Theme.palette.directColor1 : Theme.palette.directColor4
} }
font.weight: !statusChatListItem.muted && font.weight: !statusChatListItem.muted &&
(statusChatListItem.hasMention || (statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages || statusChatListItem.hasUnreadMessages ||
statusBadge.visible) ? Font.Bold : Font.Medium statusBadge.visible) ? Font.Bold : Font.Medium
font.pixelSize: 15 font.pixelSize: 15
} }
@ -207,6 +218,5 @@ Rectangle {
border.color: color border.color: color
visible: statusBadge.value > 0 visible: statusBadge.value > 0
} }
} }
} }