Compare commits

...
Author SHA1 Message Date
B.Melnik 3846eeffe2 WIP 2021-08-10 05:56:59 +03:00
B.Melnik 075a512758 feat(Drag&Drop): Add drag and drop funtionality on StatusChatListItem 2021-08-06 14:47:55 +03:00
4 changed files with 199 additions and 42 deletions
+20 -4
View File
@@ -1,4 +1,5 @@
import QtQuick 2.13
import QtQml.Models 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
@@ -13,7 +14,7 @@ Column {
property string categoryId: ""
property string selectedChatId: ""
property alias chatListItems: statusChatListItems
property alias chatListItems: delegateModel
property Component popupMenu
@@ -24,14 +25,17 @@ Column {
signal chatItemSelected(string id)
signal chatItemUnmuted(string id)
signal reorder(string cid, int from, int to)
onPopupMenuChanged: {
if (!!popupMenu) {
popupMenuSlot.sourceComponent = popupMenu
}
}
Repeater {
id: statusChatListItems
DelegateModel {
id: delegateModel
delegate: StatusChatListItem {
id: statusChatListItem
@@ -43,7 +47,7 @@ Column {
profileImage = statusChatList.profileImageFn(model.chatId || model.id) || ""
}
}
originalOrder: model.position
chatId: model.chatId || model.id
name: !!statusChatList.chatNameFn ? statusChatList.chatNameFn(model) : model.name
type: model.chatType
@@ -58,6 +62,13 @@ Column {
icon.color: model.color || ""
image.isIdenticon: !!!profileImage && !!!model.identityImage && !!model.identicon
image.source: profileImage || model.identityImage || model.identicon || ""
onVisualReorder: {
delegateModel.items.move(from, to)
}
onReorder: {
statusChatList.reorder(chatId, from, to)
}
onClicked: {
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
@@ -95,6 +106,11 @@ Column {
return true
}
}
}
Repeater {
id: statusChatListItems
model: delegateModel
}
Loader {
@@ -24,6 +24,7 @@ Item {
signal chatItemSelected(string id)
signal chatItemUnmuted(string id)
signal categoryAddButtonClicked(string id)
signal reorderChat(string categoryId, string chatId, int from, int to)
onPopupMenuChanged: {
if (!!popupMenu) {
@@ -54,7 +55,7 @@ Item {
StatusChatList {
id: statusChatList
anchors.horizontalCenter: parent.horizontalCenter
visible: !!chatListItems.model && chatListItems.count > 0
visible: chatListItems.count > 0
selectedChatId: statusChatListAndCategories.selectedChatId
onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
@@ -62,6 +63,10 @@ Item {
return !!!model.categoryId
}
popupMenu: statusChatListAndCategories.chatListPopupMenu
onReorder: function (cid, from, to) {
statusChatListAndCategories.reorderChat(categoryId, cid, from, to)
}
}
Repeater {
@@ -81,6 +86,9 @@ Item {
popupMenu: statusChatListAndCategories.categoryPopupMenu
chatListPopupMenu: statusChatListAndCategories.chatListPopupMenu
onReorderChat: function (categoryId, chatId, from, to) {
statusChatListAndCategories.reorderChat(categoryId, chatId, from, to)
}
}
}
}
@@ -21,6 +21,8 @@ Column {
property Component chatListPopupMenu
property Component popupMenu
signal reorderChat(string categoryId, string chatId, int from, int to)
onPopupMenuChanged: {
if (!!popupMenu) {
popupMenuSlot.sourceComponent = popupMenu
@@ -62,6 +64,10 @@ Column {
}
popupMenu: statusChatListCategory.chatListPopupMenu
onReorder: function (cid, from, to){
statusChatListCategory.reorderChat(categoryId, cid, from, to)
}
}
Loader {
+164 -37
View File
@@ -1,4 +1,8 @@
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.Theme 0.1
import StatusQ.Components 0.1
@@ -7,6 +11,8 @@ import StatusQ.Controls 0.1
Rectangle {
id: statusChatListItem
objectName: "chatItem"
property int originalOrder: -1
property string chatId: ""
property string name: ""
property alias badge: statusBadge
@@ -24,6 +30,9 @@ Rectangle {
signal clicked(var mouse)
signal unmute()
signal visualReorder(int from, int to, int order)
signal reorder(int from, int to)
enum Type {
Unknown0, // 0
OneToOneChat, // 1
@@ -46,14 +55,40 @@ Rectangle {
return sensor.containsMouse || highlighted ? Theme.palette.statusChatListItem.hoverBackgroundColor : Theme.palette.baseColor4
}
opacity: sensor.held ? 0.0 : 1.0
Behavior on y { NumberAnimation { duration: 350 }}
MouseArea {
id: sensor
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
property bool held: false
drag.target: content.item
property real startY: 0
onMouseYChanged: {
if ( (Math.abs(startY - mouseY) > 5 ) && pressed) {
held = true
}
}
onPressed: startY = mouseY
onPressAndHold: {
held = true
}
onReleased: {
if (held) {
reorder(statusChatListItem.originalOrder, statusChatListItem.originalOrder)
}
held = false
}
onClicked: statusChatListItem.clicked(mouse)
Loader {
@@ -63,7 +98,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
sourceComponent: !!statusChatListItem.image.source.toString() ?
statusRoundedImageCmp : statusLetterIdenticonCmp
statusRoundedImageCmp : statusLetterIdenticonCmp
}
Component {
@@ -89,8 +124,8 @@ Rectangle {
image.source: statusChatListItem.image.source
showLoadingIndicator: true
color: statusChatListItem.image.isIdenticon ?
Theme.palette.statusRoundedImage.backgroundColor :
"transparent"
Theme.palette.statusRoundedImage.backgroundColor :
"transparent"
border.width: statusChatListItem.image.isIdenticon ? 1 : 0
border.color: Theme.palette.directColor7
}
@@ -114,27 +149,27 @@ Rectangle {
if (statusChatListItem.muted && !sensor.containsMouse && !statusChatListItem.highlighted) {
return 0.4
}
return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
statusChatListItem.selected ||
statusChatListItem.highlighted ||
statusBadge.visible ||
sensor.containsMouse ? 1.0 : 0.7
return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
statusChatListItem.selected ||
statusChatListItem.highlighted ||
statusBadge.visible ||
sensor.containsMouse ? 1.0 : 0.7
}
icon: {
switch (statusChatListItem.type) {
case StatusChatListItem.Type.PublicCat:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
break;
case StatusChatListItem.Type.GroupChat:
return Theme.palette.name == "light" ? "tiny/group" : "tiny/group-white"
break;
case StatusChatListItem.Type.CommunityChat:
return Theme.palette.name == "light" ? "tiny/channel" : "tiny/channel-white"
break;
default:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
case StatusChatListItem.Type.PublicCat:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
break;
case StatusChatListItem.Type.GroupChat:
return Theme.palette.name == "light" ? "tiny/group" : "tiny/group-white"
break;
case StatusChatListItem.Type.CommunityChat:
return Theme.palette.name == "light" ? "tiny/channel" : "tiny/channel-white"
break;
default:
return Theme.palette.name == "light" ? "tiny/public-chat" : "tiny/public-chat-white"
}
}
}
@@ -144,30 +179,30 @@ Rectangle {
anchors.left: statusIcon.visible ? statusIcon.right : identicon.right
anchors.leftMargin: statusIcon.visible ? 1 : 8
anchors.right: mutedIcon.visible ? mutedIcon.left :
statusBadge.visible ? statusBadge.left : parent.right
statusBadge.visible ? statusBadge.left : parent.right
anchors.rightMargin: 6
anchors.verticalCenter: parent.verticalCenter
text: statusChatListItem.type === StatusChatListItem.Type.PublicChat &&
!statusChatListItem.name.startsWith("#") ?
"#" + statusChatListItem.name :
statusChatListItem.name
text: originalOrder + (statusChatListItem.type === StatusChatListItem.Type.PublicChat &&
!statusChatListItem.name.startsWith("#") ?
"#" + statusChatListItem.name :
statusChatListItem.name)
elide: Text.ElideRight
color: {
if (statusChatListItem.muted && !sensor.containsMouse && !statusChatListItem.highlighted) {
return Theme.palette.directColor5
}
return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
statusChatListItem.selected ||
statusChatListItem.highlighted ||
sensor.containsMouse ||
statusBadge.visible ? Theme.palette.directColor1 : Theme.palette.directColor4
return statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
statusChatListItem.selected ||
statusChatListItem.highlighted ||
sensor.containsMouse ||
statusBadge.visible ? Theme.palette.directColor1 : Theme.palette.directColor4
}
font.weight: !statusChatListItem.muted &&
(statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
statusBadge.visible) ? Font.Bold : Font.Medium
(statusChatListItem.hasMention ||
statusChatListItem.hasUnreadMessages ||
statusBadge.visible) ? Font.Bold : Font.Medium
font.pixelSize: 15
}
@@ -184,7 +219,7 @@ Rectangle {
MouseArea {
id: mutedIconSensor
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: statusChatListItem.unmute()
}
@@ -207,6 +242,98 @@ Rectangle {
border.color: color
visible: statusBadge.value > 0
}
}
DropArea {
id: dropArea
width: sensor.held ? 0 : parent.width
height: sensor.held ? 0 : parent.height
keys: ["chat"]
onEntered: {
reorderDelay.start()
}
onDropped: {
reorder(drag.source.originalOrder, statusChatListItem.DelegateModel.itemsIndex)
}
Timer {
id: reorderDelay
interval: 100
repeat: false
onTriggered: {
if (dropArea.containsDrag) {
dropArea.drag.source.originalOrder = statusChatListItem.originalOrder
visualReorder(dropArea.drag.source.DelegateModel.itemsIndex, statusChatListItem.DelegateModel.itemsIndex, statusChatListItem.originalOrder)
}
}
}
}
Loader {
id:content
active: sensor.held
sourceComponent: Item {
property var globalPosition: getAbsolutePosition(statusChatListItem)
parent: QC.Overlay.overlay
width: statusChatListItem.width
height: statusChatListItem.height
Drag.active: sensor.held
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
Drag.keys: ["chat"]
Drag.source: statusChatListItem
Component.onCompleted: {
x = globalPosition.x
y = globalPosition.y
}
RectangularGlow {
anchors.fill: cover
color: "#22000000"
glowRadius: 8
cornerRadius: 8
}
Rectangle {
id: cover
anchors.fill: parent
color: Theme.palette.baseColor4
radius: 8
Row {
spacing: 6
anchors.left: parent.left
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
Loader {
id: iconLoader
anchors.verticalCenter: parent.verticalCenter
sourceComponent: !!statusChatListItem.image.source.toString() ?
statusRoundedImageCmp : statusLetterIdenticonCmp
}
StatusBaseText {
anchors.verticalCenter: parent.verticalCenter
width: cover.width - iconLoader.item.width - 22
text: chatName.text
elide: Text.ElideRight
color: Theme.palette.directColor5
}
}
}
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;
}
}
}
}