Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
146346a862 | ||
|
|
5a5c611fd1 | ||
|
|
8d2ae42e98 |
@@ -11,12 +11,14 @@ import StatusQ.Controls 0.1
|
||||
Column {
|
||||
id: statusChatList
|
||||
|
||||
spacing: 4
|
||||
spacing: 0
|
||||
width: 288
|
||||
|
||||
property string uuid: Utils.uuid()
|
||||
|
||||
property string categoryId: ""
|
||||
property string selectedChatId: ""
|
||||
property alias chatListItems: delegateModel
|
||||
property alias chatListItems: statusChatListItems
|
||||
property bool draggableItems: false
|
||||
|
||||
property alias statusChatListItems: statusChatListItems
|
||||
@@ -29,7 +31,7 @@ Column {
|
||||
|
||||
signal chatItemSelected(string id)
|
||||
signal chatItemUnmuted(string id)
|
||||
signal chatItemReordered(string id, int from, int to)
|
||||
signal chatItemReordered(string categoryId, string id, int from, int to)
|
||||
|
||||
onPopupMenuChanged: {
|
||||
if (!!popupMenu) {
|
||||
@@ -37,191 +39,254 @@ Column {
|
||||
}
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: delegateModel
|
||||
Column {
|
||||
id: statusChatListItemsWrapper
|
||||
width: parent.width
|
||||
spacing: 4
|
||||
onImplicitHeightChanged: {
|
||||
// For some reason, the binding on emptyListDropAreaLoaoder.active alone doesn't work.
|
||||
// We have to explicitly reassign it here.
|
||||
emptyListDropAreaLoader.active = implicitHeight == 0
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
id: draggable
|
||||
width: statusChatListItem.width
|
||||
height: statusChatListItem.height
|
||||
Repeater {
|
||||
id: statusChatListItems
|
||||
delegate: Item {
|
||||
id: draggable
|
||||
width: statusChatListItem.width
|
||||
height: statusChatListItem.height
|
||||
|
||||
property alias chatListItem: statusChatListItem
|
||||
property alias chatListItem: statusChatListItem
|
||||
|
||||
visible: {
|
||||
if (!!statusChatList.filterFn) {
|
||||
return statusChatList.filterFn(model, statusChatList.categoryId)
|
||||
}
|
||||
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)
|
||||
visible: {
|
||||
if (!!statusChatList.filterFn) {
|
||||
return statusChatList.filterFn(model, statusChatList.categoryId)
|
||||
}
|
||||
active = false
|
||||
return true
|
||||
}
|
||||
onMouseYChanged: {
|
||||
if ((Math.abs(startY - mouseY) > 1) && pressed) {
|
||||
active = 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
|
||||
}
|
||||
}
|
||||
onMouseXChanged: {
|
||||
if ((Math.abs(startX - mouseX) > 1) && pressed) {
|
||||
active = true
|
||||
|
||||
onPressAndHold: active = true
|
||||
onReleased: {
|
||||
if (active && (statusChatListItem.originalOder !== statusChatListItem.newOrder ||
|
||||
statusChatListItem.categoryId !== statusChatListItem.newCategoryId)) {
|
||||
statusChatList.chatItemReordered(
|
||||
statusChatListItem.newCategoryId,
|
||||
statusChatListItem.chatId,
|
||||
statusChatListItem.originalOrder,
|
||||
statusChatListItem.newOrder
|
||||
)
|
||||
}
|
||||
active = false
|
||||
}
|
||||
}
|
||||
|
||||
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) || ""
|
||||
onMouseYChanged: {
|
||||
if ((Math.abs(startY - mouseY) > 1) && pressed) {
|
||||
active = true
|
||||
}
|
||||
}
|
||||
onMouseXChanged: {
|
||||
if ((Math.abs(startX - mouseX) > 1) && pressed) {
|
||||
active = true
|
||||
}
|
||||
}
|
||||
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 || ""
|
||||
StatusChatListItem {
|
||||
|
||||
sensor.cursorShape: dragSensor.cursorShape
|
||||
onClicked: {
|
||||
if (mouse.button === Qt.RightButton && !!statusChatList.popupMenu) {
|
||||
statusChatListItem.highlighted = true
|
||||
id: statusChatListItem
|
||||
|
||||
let originalOpenHandler = popupMenuSlot.item.openHandler
|
||||
let originalCloseHandler = popupMenuSlot.item.closeHandler
|
||||
property string chatListId: statusChatList.uuid
|
||||
property string profileImage: ""
|
||||
property var newOrder: model.position
|
||||
property var newCategoryId: model.categoryId
|
||||
|
||||
popupMenuSlot.item.openHandler = function () {
|
||||
if (!!originalOpenHandler) {
|
||||
originalOpenHandler((model.chatId || model.id))
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
opacity: dragSensor.active ? 0.3 : 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) + " POSITION: " + statusChatListItem.newOrder */
|
||||
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
|
||||
|
||||
popupMenuSlot.item.closeHandler = function () {
|
||||
if (statusChatListItem) {
|
||||
statusChatListItem.highlighted = false
|
||||
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))
|
||||
}
|
||||
}
|
||||
if (!!originalCloseHandler) {
|
||||
originalCloseHandler()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
StatusChatListDropIndicator {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: -2
|
||||
visible: dropArea.containsDrag
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DropArea {
|
||||
id: dropArea
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
keys: ["chat-item"]
|
||||
|
||||
Loader {
|
||||
id: draggedListItemLoader
|
||||
active: dragSensor.active
|
||||
sourceComponent: StatusChatListItem {
|
||||
property var globalPosition: Utils.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
|
||||
onEntered: reorderDelay.start()
|
||||
|
||||
Component.onCompleted: {
|
||||
x = globalPosition.x
|
||||
y = globalPosition.y
|
||||
Timer {
|
||||
id: reorderDelay
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (dropArea.containsDrag) {
|
||||
let newOrder = statusChatListItem.originalOrder
|
||||
|
||||
if (dropArea.drag.source.chatListItem.originalOrder > statusChatListItem.originalOrder) {
|
||||
newOrder = newOrder + 1
|
||||
}
|
||||
dropArea.drag.source.chatListItem.newOrder = newOrder
|
||||
dropArea.drag.source.chatListItem.newCategoryId = statusChatListItem.categoryId
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
Loader {
|
||||
id: draggedListItemLoader
|
||||
active: dragSensor.active
|
||||
sourceComponent: StatusChatListItem {
|
||||
property string chatListId: draggable.chatListItem.chatListId
|
||||
property var globalPosition: Utils.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"]
|
||||
Drag.source: draggable
|
||||
|
||||
icon.color: draggable.chatListItem.icon.color
|
||||
image.isIdenticon: draggable.chatListItem.image.isIdenticon
|
||||
image.source: draggable.chatListItem.image.source
|
||||
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 {
|
||||
id: popupMenuSlot
|
||||
active: !!statusChatList.popupMenu
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: emptyListDropAreaLoader
|
||||
active: statusChatListItemsWrapper.implicitHeight == 0
|
||||
width: parent.width
|
||||
height: active ? 8 : 0
|
||||
sourceComponent: Item {
|
||||
width: statusChatList.width
|
||||
height: 8
|
||||
|
||||
StatusChatListDropIndicator {
|
||||
visible: emptyListDropArea.containsDrag
|
||||
opacity: 0.5
|
||||
anchors.bottom: statusChatList.categoryId == "" ? parent.bottom : undefined
|
||||
anchors.top: statusChatList.categoryId !== "" ? parent.top : undefined
|
||||
}
|
||||
|
||||
DropArea {
|
||||
id: emptyListDropArea
|
||||
anchors.fill: parent
|
||||
visible: parent.visible
|
||||
keys: ["chat-item"]
|
||||
onEntered: reorderDelay2.start()
|
||||
Timer {
|
||||
id: reorderDelay2
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (emptyListDropArea.containsDrag) {
|
||||
emptyListDropArea.drag.source.chatListItem.newOrder = 0
|
||||
emptyListDropArea.drag.source.chatListItem.newCategoryId = statusChatList.categoryId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,14 @@ Item {
|
||||
chatList.selectedChatId: statusChatListAndCategories.selectedChatId
|
||||
chatList.onChatItemSelected: statusChatListAndCategories.chatItemSelected(id)
|
||||
chatList.onChatItemUnmuted: statusChatListAndCategories.chatItemUnmuted(id)
|
||||
chatList.onChatItemReordered: statusChatListAndCategories.chatItemReordered(model.categoryId, id, from, to)
|
||||
chatList.onChatItemReordered: {
|
||||
console.log("REORDERING CHAT ITEM:")
|
||||
console.log("FROM CATEGORY: ", model.categoryId)
|
||||
console.log("TO: ", categoryId)
|
||||
console.log("FROM POSITION: ", from)
|
||||
console.log("TO POSITION: ", to)
|
||||
statusChatListAndCategories.chatItemReordered(categoryId, id, from, to)
|
||||
}
|
||||
chatList.draggableItems: statusChatListAndCategories.draggableItems
|
||||
|
||||
popupMenu: statusChatListAndCategories.categoryPopupMenu
|
||||
@@ -155,7 +162,9 @@ Item {
|
||||
height: draggable.chatListCategory.dragActive ? 0 : parent.height
|
||||
keys: ["chat-category"]
|
||||
|
||||
onEntered: reorderDelay.start()
|
||||
onEntered: {
|
||||
reorderDelay.start()
|
||||
}
|
||||
onDropped: statusChatListAndCategories.chatListCategoryReordered(statusChatListCategory.categoryId, drag.source.originalOrder, statusChatListCategory.DelegateModel.itemsIndex)
|
||||
|
||||
Timer {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick 2.13
|
||||
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
@@ -8,6 +9,7 @@ Column {
|
||||
|
||||
spacing: 0
|
||||
opacity: dragged ? 0.5 : 1
|
||||
property string uuid: Utils.uuid()
|
||||
|
||||
objectName: "chatListCategory"
|
||||
property int originalOrder: -1
|
||||
@@ -64,6 +66,7 @@ Column {
|
||||
|
||||
StatusChatList {
|
||||
id: statusChatList
|
||||
uuid: statusChatListCategory.uuid
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: statusChatListCategory.opened
|
||||
categoryId: statusChatListCategory.categoryId
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import QtQuick 2.13
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
implicitWidth: 288
|
||||
height: 4
|
||||
color: Theme.palette.successColor1
|
||||
radius: 2
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ module StatusQ.Components
|
||||
StatusBadge 0.1 StatusBadge.qml
|
||||
StatusChatInfoToolBar 0.1 StatusChatInfoToolBar.qml
|
||||
StatusChatList 0.1 StatusChatList.qml
|
||||
StatusChatListDropIndicator 0.1 StatusChatListDropIndicator.qml
|
||||
StatusChatListItem 0.1 StatusChatListItem.qml
|
||||
StatusChatListCategory 0.1 StatusChatListCategory.qml
|
||||
StatusChatListCategoryItem 0.1 StatusChatListCategoryItem.qml
|
||||
|
||||
@@ -249,6 +249,7 @@
|
||||
<file>src/StatusQ/Controls/StatusBaseInput.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusChatListCategoryItemButton.qml</file>
|
||||
<file>src/StatusQ/Components/StatusChatList.qml</file>
|
||||
<file>src/StatusQ/Components/StatusChatListDropIndicator.qml</file>
|
||||
<file>src/StatusQ/Popups/statusModal/StatusImageWithTitle.qml</file>
|
||||
<file>src/StatusQ/Popups/statusModal/StatusModalFooter.qml</file>
|
||||
<file>src/StatusQ/Popups/statusModal/StatusModalHeader.qml</file>
|
||||
|
||||
Reference in New Issue
Block a user