431 lines
15 KiB
QML
431 lines
15 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15
|
|
import QtQuick.Layouts 1.15
|
|
import QtQml 2.15
|
|
|
|
import StatusQ.Controls 0.1
|
|
import StatusQ.Core 0.1
|
|
import StatusQ.Core.Utils 0.1
|
|
import StatusQ.Core.Theme 0.1
|
|
|
|
import shared.controls 1.0
|
|
import utils 1.0
|
|
|
|
import AppLayouts.Profile.controls 1.0
|
|
|
|
DoubleFlickableWithFolding {
|
|
id: root
|
|
|
|
readonly property var showcaseRoles: ["showcaseVisibility", "order"]
|
|
|
|
required property string keyRole
|
|
required property var roleNames
|
|
required property var filterFunc
|
|
|
|
property var baseModel
|
|
property var showcaseModel
|
|
|
|
property Component showcaseDraggableDelegateComponent
|
|
property Component hiddenDraggableDelegateComponent
|
|
|
|
property Component additionalFooterComponent
|
|
|
|
property string emptyInShowcasePlaceholderText
|
|
property string emptyHiddenPlaceholderText
|
|
|
|
readonly property Connections showcaseUpdateConnections: Connections {
|
|
target: root.showcaseModel
|
|
|
|
function onBaseModelFilterConditionsMayHaveChanged() {
|
|
root.updateBaseModelFilters()
|
|
}
|
|
}
|
|
|
|
function reset() {
|
|
root.showcaseModel.clear()
|
|
updateBaseModelFilters()
|
|
}
|
|
|
|
function updateBaseModelFilters() {
|
|
// Reset base model to update filter conditions
|
|
hiddenListView.model = null
|
|
hiddenListView.model = root.baseModel
|
|
}
|
|
|
|
signal showcaseEntryChanged()
|
|
|
|
QtObject {
|
|
id: d
|
|
|
|
readonly property var dragHiddenItemKey: ["x-status-draggable-showcase-item-hidden"]
|
|
readonly property var dragShowcaseItemKey: ["x-status-draggable-showcase-item"]
|
|
|
|
property bool isAnyShowcaseDragActive: false
|
|
property bool isAnyHiddenDragActive: false
|
|
|
|
property int additionalHeaderComponentWidth: 350 // by design
|
|
property int additionalHeaderComponentHeight: 40 // by design
|
|
}
|
|
|
|
clip: true
|
|
|
|
ScrollBar.vertical: StatusScrollBar {
|
|
policy: ScrollBar.AsNeeded
|
|
visible: resolveVisibility(policy, root.height, root.contentHeight)
|
|
}
|
|
|
|
flickable1: EmptyShapeRectangleFooterListView {
|
|
id: inShowcaseListView
|
|
|
|
model: root.showcaseModel
|
|
width: root.width
|
|
placeholderText: root.emptyInShowcasePlaceholderText
|
|
footerHeight: ProfileUtils.defaultDelegateHeight
|
|
footerContentVisible: !dropAreaRow.visible
|
|
spacing: Style.current.halfPadding
|
|
|
|
header: FoldableHeader {
|
|
width: ListView.view.width
|
|
title: qsTr("In showcase")
|
|
folded: root.flickable1Folded
|
|
rightAdditionalComponent: VisibilityDropAreaButtonsRow {
|
|
width: d.additionalHeaderComponentWidth
|
|
height: d.additionalHeaderComponentHeight
|
|
margins: 0
|
|
visible: root.flickable1Folded &&
|
|
(d.isAnyHiddenDragActive ||
|
|
parent.containsDrag ||
|
|
everyoneContainsDrag ||
|
|
contactsContainsDrag ||
|
|
verifiedContainsDrag)
|
|
}
|
|
|
|
onToggleFolding: root.flip1Folding()
|
|
}
|
|
|
|
delegate: DropArea {
|
|
id: showcaseDelegateRoot
|
|
|
|
property int visualIndex: index
|
|
|
|
width: ListView.view.width
|
|
height: visible && showcaseDraggableDelegateLoader.item ? showcaseDraggableDelegateLoader.item.height : 0
|
|
|
|
keys: d.dragShowcaseItemKey
|
|
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()
|
|
root.showcaseModel.move(from, to, 1)
|
|
drag.accept()
|
|
}
|
|
|
|
// TODO:
|
|
// This animation is causing issues when there are no elements in the showcase list.
|
|
// Reenable it once the refactor of the models and delegates is done (simplified): #13498
|
|
// 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 }
|
|
// }
|
|
|
|
// In showcase delegate item container:
|
|
Loader {
|
|
id: showcaseDraggableDelegateLoader
|
|
|
|
property var modelData: model
|
|
property var dragParentData: root
|
|
property int visualIndexData: index
|
|
|
|
width: parent.width
|
|
sourceComponent: root.showcaseDraggableDelegateComponent
|
|
}
|
|
|
|
// Delegate shadow background when dragging:
|
|
ShadowDelegate {
|
|
id: showcaseShadow
|
|
|
|
visible: showcaseDraggableDelegateLoader.item && showcaseDraggableDelegateLoader.item.dragActive
|
|
onVisibleChanged: d.isAnyShowcaseDragActive = visible
|
|
}
|
|
|
|
Binding {
|
|
when: dropAreaRow.visible
|
|
target: showcaseDraggableDelegateLoader.item
|
|
property: "blurState"
|
|
value: true
|
|
restoreMode: Binding.RestoreBindingOrValue
|
|
}
|
|
}
|
|
|
|
// Overlaid showcase listview content drop area:
|
|
DropArea {
|
|
anchors.bottom: parent.bottom
|
|
width: parent.width
|
|
height: parent.contentHeight
|
|
keys: d.dragHiddenItemKey
|
|
|
|
// Shown at the bottom of the listview
|
|
VisibilityDropAreaButtonsRow {
|
|
id: dropAreaRow
|
|
|
|
width: parent.width
|
|
height: ProfileUtils.defaultDelegateHeight
|
|
anchors.bottom: parent.bottom
|
|
visible: d.isAnyHiddenDragActive ||
|
|
parent.containsDrag ||
|
|
everyoneContainsDrag ||
|
|
contactsContainsDrag ||
|
|
verifiedContainsDrag
|
|
}
|
|
}
|
|
}
|
|
|
|
flickable2: EmptyShapeRectangleFooterListView {
|
|
id: hiddenListView
|
|
|
|
model: root.baseModel
|
|
width: root.width
|
|
placeholderText: root.emptyHiddenPlaceholderText
|
|
footerHeight: ProfileUtils.defaultDelegateHeight
|
|
footerContentVisible: !hiddenDropAreaButton.visible
|
|
empty: root.showcaseModel.hiddenCount === 0 && !root.flickable2Folded // TO BE REMOVE: #13498
|
|
additionalFooterComponent: root.additionalFooterComponent
|
|
spacing: Style.current.halfPadding
|
|
|
|
header: FoldableHeader {
|
|
width: ListView.view.width
|
|
title: qsTr("Hidden")
|
|
folded: root.flickable2Folded
|
|
rightAdditionalComponent: VisibilityDropAreaButton {
|
|
visible: root.flickable2Folded && (d.isAnyShowcaseDragActive || parent.containsDrag || containsDrag)
|
|
width: d.additionalHeaderComponentWidth
|
|
height: d.additionalHeaderComponentHeight
|
|
rightInset: 1
|
|
text: qsTr("Hide")
|
|
dropAreaKeys: d.dragShowcaseItemKey
|
|
|
|
onDropped: {
|
|
root.showcaseModel.setVisibilityByIndex(drop.source.visualIndex, visibility)
|
|
root.showcaseEntryChanged()
|
|
}
|
|
}
|
|
|
|
onToggleFolding: root.flip2Folding()
|
|
}
|
|
|
|
delegate: DropArea {
|
|
id: hiddenDelegateRoot
|
|
|
|
property int visualIndex: index
|
|
|
|
visible: root.filterFunc(model)
|
|
width: ListView.view.width
|
|
height: visible && hiddenDraggableDelegateLoader.item ? hiddenDraggableDelegateLoader.item.height : 0
|
|
|
|
keys: d.dragShowcaseItemKey
|
|
|
|
onEntered: function(drag) {
|
|
drag.accept()
|
|
}
|
|
|
|
onDropped: function(drop) {
|
|
root.showcaseModel.setVisibilityByIndex(drop.source.visualIndex, Constants.ShowcaseVisibility.NoOne)
|
|
root.showcaseEntryChanged()
|
|
}
|
|
|
|
// Hidden delegate item container:
|
|
Loader {
|
|
id: hiddenDraggableDelegateLoader
|
|
|
|
property var modelData: model
|
|
property var dragParentData: root
|
|
property int visualIndexData: hiddenDelegateRoot.visualIndex
|
|
|
|
width: parent.width
|
|
sourceComponent: root.hiddenDraggableDelegateComponent
|
|
}
|
|
|
|
// Delegate shadow background when dragging:
|
|
ShadowDelegate {
|
|
id: hiddenShadow
|
|
|
|
visible: hiddenDraggableDelegateLoader.item && hiddenDraggableDelegateLoader.item.dragActive
|
|
onVisibleChanged: d.isAnyHiddenDragActive = visible
|
|
}
|
|
|
|
Binding {
|
|
when: hiddenDropAreaButton.visible
|
|
target: hiddenDraggableDelegateLoader.item
|
|
property: "blurState"
|
|
value: true
|
|
restoreMode: Binding.RestoreBindingOrValue
|
|
}
|
|
}
|
|
|
|
// Overlaid hidden listview content drop area:
|
|
DropArea {
|
|
anchors.top: parent.top
|
|
width: parent.width
|
|
height: parent.contentHeight
|
|
keys: d.dragShowcaseItemKey
|
|
|
|
// Shown at the top of the listview
|
|
VisibilityDropAreaButton {
|
|
id: hiddenDropAreaButton
|
|
|
|
anchors.top: parent.top
|
|
anchors.topMargin: hiddenListView.headerItem.height + Style.current.padding
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
visible: d.isAnyShowcaseDragActive || parent.containsDrag || hiddenDropAreaButton.containsDrag
|
|
width: parent.width - Style.current.padding
|
|
height: ProfileUtils.defaultDelegateHeight - Style.current.padding
|
|
text: qsTr("Hide")
|
|
dropAreaKeys: d.dragShowcaseItemKey
|
|
|
|
onDropped: {
|
|
root.showcaseModel.setVisibilityByIndex(drop.source.visualIndex, visibility)
|
|
root.showcaseEntryChanged()
|
|
root.updateBaseModelFilters()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
component VisibilityDropAreaButton: AbstractButton {
|
|
id: visibilityDropAreaButton
|
|
|
|
readonly property alias containsDrag: dropArea.containsDrag
|
|
|
|
property int showcaseVisibility: Constants.ShowcaseVisibility.NoOne
|
|
property var dropAreaKeys
|
|
|
|
signal dropped(var drop, int visibility)
|
|
|
|
padding: Style.current.halfPadding
|
|
spacing: padding/2
|
|
|
|
icon.color: Theme.palette.primaryColor1
|
|
|
|
background: ShapeRectangle {
|
|
path.strokeColor: dropArea.containsDrag ? Theme.palette.primaryColor2 : Theme.palette.directColor7
|
|
path.fillColor: dropArea.containsDrag ? Theme.palette.primaryColor3 : Theme.palette.baseColor4
|
|
|
|
DropArea {
|
|
id: dropArea
|
|
|
|
anchors.fill: parent
|
|
keys: visibilityDropAreaButton.dropAreaKeys
|
|
|
|
onEntered: function(drag) {
|
|
drag.accept()
|
|
}
|
|
|
|
onDropped: function(drop) {
|
|
visibilityDropAreaButton.dropped(drop, visibilityDropAreaButton.showcaseVisibility)
|
|
}
|
|
}
|
|
}
|
|
|
|
contentItem: Item {
|
|
RowLayout {
|
|
width: Math.min(parent.width, implicitWidth)
|
|
anchors.centerIn: parent
|
|
spacing: visibilityDropAreaButton.spacing
|
|
|
|
StatusIcon {
|
|
width: 20
|
|
height: width
|
|
icon: ProfileUtils.visibilityIcon(visibilityDropAreaButton.showcaseVisibility)
|
|
color: visibilityDropAreaButton.icon.color
|
|
}
|
|
|
|
StatusBaseText {
|
|
Layout.fillWidth: true
|
|
font.pixelSize: Style.current.additionalTextSize
|
|
font.weight: Font.Medium
|
|
elide: Text.ElideRight
|
|
color: visibilityDropAreaButton.icon.color
|
|
text: visibilityDropAreaButton.text
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
component VisibilityDropAreaButtonsRow: Item {
|
|
id: visibilityDropAreaRow
|
|
|
|
readonly property bool everyoneContainsDrag: dropAreaEveryone.containsDrag
|
|
readonly property bool contactsContainsDrag: dropAreaContacts.containsDrag
|
|
readonly property bool verifiedContainsDrag: dropAreaVerified.containsDrag
|
|
property int margins: Style.current.halfPadding
|
|
|
|
function dropped(drop, visibility) {
|
|
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 = visibility
|
|
root.showcaseModel.upsertItemJson(JSON.stringify(tmpObj))
|
|
root.showcaseEntryChanged()
|
|
}
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: visibilityDropAreaRow.margins
|
|
spacing: Style.current.halfPadding
|
|
|
|
VisibilityDropAreaButton {
|
|
id: dropAreaEveryone
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
showcaseVisibility: Constants.ShowcaseVisibility.Everyone
|
|
text: qsTr("Everyone")
|
|
dropAreaKeys: d.dragHiddenItemKey
|
|
|
|
onDropped: visibilityDropAreaRow.dropped(drop, visibility)
|
|
}
|
|
|
|
VisibilityDropAreaButton {
|
|
id: dropAreaContacts
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
|
|
text: qsTr("Contacts")
|
|
dropAreaKeys: d.dragHiddenItemKey
|
|
|
|
onDropped: visibilityDropAreaRow.dropped(drop, visibility)
|
|
}
|
|
|
|
VisibilityDropAreaButton {
|
|
id: dropAreaVerified
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
|
|
text: qsTr("Verified")
|
|
dropAreaKeys: d.dragHiddenItemKey
|
|
|
|
onDropped: visibilityDropAreaRow.dropped(drop, visibility)
|
|
}
|
|
}
|
|
}
|
|
|
|
component ShadowDelegate: Rectangle {
|
|
width: parent.width
|
|
height: ProfileUtils.defaultDelegateHeight
|
|
anchors.centerIn: parent
|
|
color: Theme.palette.baseColor5
|
|
radius: Style.current.radius
|
|
}
|
|
}
|