338 lines
12 KiB
QML
338 lines
12 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15
|
|
import QtQuick.Layouts 1.15
|
|
|
|
import StatusQ.Core 0.1
|
|
import StatusQ.Controls 0.1
|
|
import StatusQ.Components 0.1
|
|
import StatusQ.Core.Theme 0.1
|
|
import StatusQ.Popups 0.1
|
|
|
|
import shared.controls 1.0
|
|
|
|
import utils 1.0
|
|
|
|
import AppLayouts.Profile.controls 1.0
|
|
|
|
Control {
|
|
id: root
|
|
|
|
property var baseModel
|
|
property var showcaseModel
|
|
|
|
readonly property var showcaseRoles: ["showcaseVisibility", "order"]
|
|
|
|
// to override
|
|
property string keyRole
|
|
property var roleNames: []
|
|
property var filterFunc: (modelData) => true
|
|
property string hiddenPlaceholderBanner
|
|
property string showcasePlaceholderBanner
|
|
property Component draggableDelegateComponent
|
|
property Component showcaseDraggableDelegateComponent
|
|
|
|
signal showcaseEntryChanged()
|
|
|
|
function reset() {
|
|
showcaseModel.clear()
|
|
updateBaseModelFilters()
|
|
}
|
|
|
|
function updateBaseModelFilters() {
|
|
// Reset base model to update filter conditions
|
|
hiddenItemsListView.model = null
|
|
hiddenItemsListView.model = baseModel
|
|
}
|
|
|
|
readonly property Connections showcaseUpdateConnections: Connections {
|
|
target: showcaseModel
|
|
|
|
function onBaseModelFilterConditionsMayHaveChanged() {
|
|
root.updateBaseModelFilters()
|
|
}
|
|
}
|
|
|
|
background: null
|
|
|
|
component VisibilityDropArea: AbstractButton {
|
|
id: visibilityDropAreaLocal
|
|
|
|
property int showcaseVisibility: Constants.ShowcaseVisibility.NoOne
|
|
readonly property alias containsDrag: dropArea.containsDrag
|
|
|
|
padding: Style.current.halfPadding
|
|
spacing: padding/2
|
|
|
|
icon.color: Theme.palette.primaryColor1
|
|
|
|
background: ShapeRectangle {
|
|
path.strokeColor: dropArea.containsDrag ? "transparent" : Theme.palette.directColor7
|
|
path.fillColor: dropArea.containsDrag ? Theme.palette.white : "transparent"
|
|
|
|
DropArea {
|
|
id: dropArea
|
|
anchors.fill: parent
|
|
keys: ["x-status-draggable-showcase-item-hidden"]
|
|
onEntered: function(drag) {
|
|
drag.accept()
|
|
}
|
|
|
|
onDropped: function(drop) {
|
|
var showcaseObj = drop.source.showcaseObj
|
|
|
|
// need to set total balance for an asset
|
|
if (drop.source.totalValue !== undefined) {
|
|
showcaseObj.enabledNetworkBalance = drop.source.totalValue
|
|
}
|
|
|
|
var tmpObj = Object()
|
|
root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role])
|
|
tmpObj.showcaseVisibility = visibilityDropAreaLocal.showcaseVisibility
|
|
showcaseModel.upsertItemJson(JSON.stringify(tmpObj))
|
|
root.showcaseEntryChanged()
|
|
}
|
|
}
|
|
}
|
|
|
|
contentItem: Item {
|
|
RowLayout {
|
|
width: Math.min(parent.width, implicitWidth)
|
|
anchors.centerIn: parent
|
|
spacing: visibilityDropAreaLocal.spacing
|
|
StatusIcon {
|
|
width: 20
|
|
height: 20
|
|
icon: ProfileUtils.visibilityIcon(visibilityDropAreaLocal.showcaseVisibility)
|
|
color: visibilityDropAreaLocal.icon.color
|
|
}
|
|
StatusBaseText {
|
|
Layout.fillWidth: true
|
|
font.pixelSize: 13
|
|
font.weight: Font.Medium
|
|
elide: Text.ElideRight
|
|
color: visibilityDropAreaLocal.icon.color
|
|
text: visibilityDropAreaLocal.text
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
QtObject {
|
|
id: d
|
|
|
|
readonly property int defaultDelegateHeight: 60
|
|
readonly property int contentSpacing: 12
|
|
readonly property int strokeMargin: 2
|
|
}
|
|
|
|
contentItem: ColumnLayout {
|
|
spacing: d.contentSpacing
|
|
|
|
StatusBaseText {
|
|
Layout.fillWidth: true
|
|
text: qsTr("In showcase")
|
|
color: Theme.palette.baseColor1
|
|
font.pixelSize: 13
|
|
font.weight: Font.Medium
|
|
}
|
|
|
|
StatusListView {
|
|
id: showcaseItemsListView
|
|
Layout.fillWidth: true
|
|
Layout.minimumHeight: Math.floor(targetDropArea.height + targetDropArea.anchors.bottomMargin)
|
|
model: showcaseModel
|
|
implicitHeight: contentHeight
|
|
interactive: false
|
|
|
|
displaced: Transition {
|
|
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }
|
|
}
|
|
|
|
delegate: DropArea {
|
|
id: showcaseDelegateRoot
|
|
|
|
property int visualIndex: index
|
|
|
|
ListView.onRemove: SequentialAnimation {
|
|
PropertyAction { target: showcaseDelegateRoot; property: "ListView.delayRemove"; value: true }
|
|
NumberAnimation { target: showcaseDelegateRoot; property: "scale"; to: 0; easing.type: Easing.InOutQuad }
|
|
PropertyAction { target: showcaseDelegateRoot; property: "ListView.delayRemove"; value: false }
|
|
}
|
|
|
|
width: ListView.view.width
|
|
height: visible && showcaseDraggableDelegateLoader.item ? showcaseDraggableDelegateLoader.item.height : 0
|
|
|
|
keys: ["x-status-draggable-showcase-item"]
|
|
|
|
visible: model.showcaseVisibility !== Constants.ShowcaseVisibility.NoOne
|
|
|
|
onEntered: function(drag) {
|
|
const from = drag.source.visualIndex
|
|
const to = showcaseDraggableDelegateLoader.item.visualIndex
|
|
if (to === from)
|
|
return
|
|
root.showcaseEntryChanged()
|
|
showcaseModel.move(from, to)
|
|
drag.accept()
|
|
}
|
|
|
|
Loader {
|
|
id: showcaseDraggableDelegateLoader
|
|
width: parent.width
|
|
sourceComponent: root.showcaseDraggableDelegateComponent
|
|
|
|
property var modelData: model
|
|
property var dragParentData: root
|
|
property int visualIndexData: index
|
|
}
|
|
}
|
|
|
|
// overlaid at the bottom of the listview
|
|
DropArea {
|
|
id: targetDropArea
|
|
width: parent.width
|
|
height: d.defaultDelegateHeight
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: showcaseModel.count ? Style.current.halfPadding : 0
|
|
keys: ["x-status-draggable-showcase-item-hidden"]
|
|
|
|
ShapeRectangle {
|
|
anchors.fill: parent
|
|
anchors.margins: d.strokeMargin
|
|
visible: !showcaseModel.count && !showcaseCombinedDropArea.visible
|
|
text: root.hiddenPlaceholderBanner
|
|
}
|
|
|
|
Rectangle {
|
|
id: showcaseCombinedDropArea
|
|
width: parent.width
|
|
height: parent.height + d.strokeMargin
|
|
anchors.centerIn: parent
|
|
color: Theme.palette.baseColor5
|
|
radius: Style.current.radius
|
|
visible: parent.containsDrag || dropAreaEveryone.containsDrag || dropAreaContacts.containsDrag || dropAreaVerified.containsDrag
|
|
|
|
RowLayout {
|
|
width: parent.width - spacing*2
|
|
anchors.centerIn: parent
|
|
spacing: d.contentSpacing
|
|
VisibilityDropArea {
|
|
id: dropAreaEveryone
|
|
Layout.fillWidth: true
|
|
showcaseVisibility: Constants.ShowcaseVisibility.Everyone
|
|
text: qsTr("Everyone")
|
|
}
|
|
VisibilityDropArea {
|
|
id: dropAreaContacts
|
|
Layout.fillWidth: true
|
|
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
|
|
text: qsTr("Contacts")
|
|
}
|
|
VisibilityDropArea {
|
|
id: dropAreaVerified
|
|
Layout.fillWidth: true
|
|
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
|
|
text: qsTr("Verified")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
StatusBaseText {
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: Style.current.halfPadding
|
|
text: qsTr("Hidden")
|
|
color: Theme.palette.baseColor1
|
|
font.pixelSize: 13
|
|
font.weight: Font.Medium
|
|
}
|
|
|
|
StatusListView {
|
|
id: hiddenItemsListView
|
|
Layout.fillWidth: true
|
|
Layout.minimumHeight: empty ? Math.floor(hiddenTargetDropArea.height + hiddenTargetDropArea.anchors.topMargin)
|
|
: d.defaultDelegateHeight * Math.min(count, 4)
|
|
model: root.baseModel
|
|
|
|
readonly property bool empty: !contentHeight
|
|
|
|
displaced: Transition {
|
|
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }
|
|
}
|
|
|
|
delegate: DropArea {
|
|
id: delegateRoot
|
|
|
|
property int visualIndex: index
|
|
|
|
visible: root.filterFunc(model)
|
|
width: ListView.view.width
|
|
height: visible && draggableDelegateLoader.item ? draggableDelegateLoader.item.height : 0
|
|
|
|
keys: ["x-status-draggable-showcase-item"]
|
|
|
|
onEntered: function(drag) {
|
|
drag.accept()
|
|
}
|
|
|
|
onDropped: function(drop) {
|
|
|
|
showcaseModel.setVisibilityByIndex(drop.source.visualIndex, Constants.ShowcaseVisibility.NoOne)
|
|
root.showcaseEntryChanged()
|
|
}
|
|
|
|
Rectangle {
|
|
width: parent.width
|
|
height: d.defaultDelegateHeight
|
|
anchors.centerIn: parent
|
|
color: Theme.palette.baseColor5
|
|
radius: Style.current.radius
|
|
visible: draggableDelegateLoader.item && draggableDelegateLoader.item.dragActive
|
|
}
|
|
|
|
Loader {
|
|
id: draggableDelegateLoader
|
|
width: parent.width
|
|
sourceComponent: root.draggableDelegateComponent
|
|
|
|
property var modelData: model
|
|
property var dragParentData: root
|
|
property int visualIndexData: delegateRoot.visualIndex
|
|
}
|
|
}
|
|
|
|
// overlaid at the top of the listview
|
|
DropArea {
|
|
id: hiddenTargetDropArea
|
|
width: parent.width
|
|
height: d.defaultDelegateHeight
|
|
anchors.top: parent.top
|
|
anchors.topMargin: !hiddenItemsListView.empty ? Style.current.halfPadding : 0
|
|
keys: ["x-status-draggable-showcase-item"]
|
|
|
|
ShapeRectangle {
|
|
readonly property bool stroked: hiddenItemsListView.empty && !parent.containsDrag
|
|
|
|
anchors.fill: parent
|
|
anchors.margins: d.strokeMargin
|
|
visible: hiddenItemsListView.empty || parent.containsDrag
|
|
path.fillColor: stroked ? "transparent" : Theme.palette.baseColor5
|
|
path.strokeColor: stroked ? Theme.palette.baseColor2 : "transparent"
|
|
text: root.showcasePlaceholderBanner
|
|
}
|
|
|
|
onEntered: function(drag) {
|
|
drag.accept()
|
|
}
|
|
|
|
onDropped: function(drop) {
|
|
showcaseModel.setVisibilityByIndex(drop.source.visualIndex, Constants.ShowcaseVisibility.NoOne)
|
|
root.showcaseEntryChanged()
|
|
root.updateBaseModelFilters()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|