2023-03-20 12:29:05 +00:00
|
|
|
import QtQuick 2.15
|
|
|
|
import QtQuick.Controls 2.15
|
|
|
|
import QtQuick.Layouts 1.15
|
2024-02-15 17:26:05 +00:00
|
|
|
import QtQml 2.15
|
2024-02-28 12:19:14 +00:00
|
|
|
import QtQml.Models 2.15
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
import StatusQ 0.1
|
2023-03-20 12:29:05 +00:00
|
|
|
import StatusQ.Controls 0.1
|
2024-02-15 17:26:05 +00:00
|
|
|
import StatusQ.Core 0.1
|
|
|
|
import StatusQ.Core.Utils 0.1
|
2023-03-20 12:29:05 +00:00
|
|
|
import StatusQ.Core.Theme 0.1
|
2024-03-03 16:34:08 +00:00
|
|
|
import StatusQ.Controls.Validators 0.1
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2023-05-02 08:01:04 +00:00
|
|
|
import shared.controls 1.0
|
2023-03-20 12:29:05 +00:00
|
|
|
import utils 1.0
|
|
|
|
|
|
|
|
import AppLayouts.Profile.controls 1.0
|
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
import SortFilterProxyModel 0.2
|
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
DoubleFlickableWithFolding {
|
2023-03-20 12:29:05 +00:00
|
|
|
id: root
|
|
|
|
|
2024-02-29 09:07:35 +00:00
|
|
|
property Component delegate: ProfileShowcasePanelDelegate {}
|
2024-02-15 17:26:05 +00:00
|
|
|
|
2024-03-03 11:02:30 +00:00
|
|
|
// Expected roles:
|
2024-02-28 12:19:14 +00:00
|
|
|
// - visibility: int
|
|
|
|
property var inShowcaseModel
|
|
|
|
property var hiddenModel
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-21 13:39:27 +00:00
|
|
|
property Component additionalFooterComponent
|
|
|
|
|
2024-02-28 12:19:14 +00:00
|
|
|
// Placeholder text to be shown when the list is empty
|
2024-02-15 17:26:05 +00:00
|
|
|
property string emptyInShowcasePlaceholderText
|
|
|
|
property string emptyHiddenPlaceholderText
|
2024-03-03 16:34:08 +00:00
|
|
|
property string emptySearchPlaceholderText
|
2024-02-15 17:26:05 +00:00
|
|
|
|
2024-03-08 20:11:48 +00:00
|
|
|
property int showcaseLimit: 100
|
2024-03-03 11:02:30 +00:00
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
// Searcher related properties:
|
|
|
|
property string searchPlaceholderText
|
2024-04-19 09:46:23 +00:00
|
|
|
readonly property alias searcherText: d.searcherText
|
|
|
|
|
|
|
|
//SFPM filters to apply to both in showcase and hidden models
|
|
|
|
property FastExpressionFilter filter
|
2024-03-03 16:34:08 +00:00
|
|
|
|
2024-03-03 11:02:30 +00:00
|
|
|
// Signal to request position change of the visible items
|
2024-02-29 07:43:38 +00:00
|
|
|
signal changePositionRequested(int from, int to)
|
2024-03-03 11:02:30 +00:00
|
|
|
|
2024-02-28 12:19:14 +00:00
|
|
|
// Signal to request visibility change of the items
|
|
|
|
signal setVisibilityRequested(var key, int toVisibility)
|
2024-02-15 17:26:05 +00:00
|
|
|
|
2024-02-28 12:19:14 +00:00
|
|
|
ScrollBar.vertical: StatusScrollBar {
|
|
|
|
policy: ScrollBar.AsNeeded
|
|
|
|
visible: resolveVisibility(policy, root.height, root.contentHeight)
|
|
|
|
}
|
2023-11-01 16:54:22 +00:00
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
QtObject {
|
|
|
|
id: d
|
|
|
|
|
2024-03-03 11:02:30 +00:00
|
|
|
readonly property bool limitReached: root.showcaseLimit === inShowcaseCounterTracker.count
|
2024-03-03 16:34:08 +00:00
|
|
|
readonly property bool searchActive: root.searcherText !== ""
|
2024-04-19 09:46:23 +00:00
|
|
|
property string searcherText: ""
|
2024-03-03 11:02:30 +00:00
|
|
|
|
2024-02-23 07:14:55 +00:00
|
|
|
readonly property var dragHiddenItemKey: ["x-status-draggable-showcase-item-hidden"]
|
|
|
|
readonly property var dragShowcaseItemKey: ["x-status-draggable-showcase-item"]
|
|
|
|
|
|
|
|
property bool isAnyShowcaseDragActive: false
|
2024-04-19 09:46:23 +00:00
|
|
|
onIsAnyShowcaseDragActiveChanged: {
|
|
|
|
if(!isAnyShowcaseDragActive) {
|
|
|
|
// Sync the order of the visible items when the drag is finished
|
|
|
|
// MovableModel is used only for DND operations. No interference needed when the DND is not active
|
|
|
|
visibleModel.syncOrder()
|
|
|
|
}
|
|
|
|
}
|
2024-02-23 07:14:55 +00:00
|
|
|
property bool isAnyHiddenDragActive: false
|
2024-02-26 11:07:06 +00:00
|
|
|
|
|
|
|
property int additionalHeaderComponentWidth: 350 // by design
|
|
|
|
property int additionalHeaderComponentHeight: 40 // by design
|
2024-03-03 11:02:30 +00:00
|
|
|
|
|
|
|
property bool startAnimation: false
|
|
|
|
|
2024-03-10 21:31:48 +00:00
|
|
|
property var dragItem: null
|
|
|
|
|
2024-03-03 11:02:30 +00:00
|
|
|
signal setVisibilityInternalRequested(var key, int toVisibility)
|
|
|
|
onSetVisibilityInternalRequested: {
|
|
|
|
if(toVisibility !== Constants.ShowcaseVisibility.NoOne) {
|
|
|
|
startAnimation = !startAnimation
|
|
|
|
}
|
|
|
|
root.setVisibilityRequested(key, toVisibility)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ModelChangeTracker {
|
|
|
|
id: inShowcaseCounterTracker
|
|
|
|
|
|
|
|
property int count: {
|
|
|
|
revision
|
|
|
|
return model.rowCount()
|
|
|
|
}
|
|
|
|
|
|
|
|
model: root.inShowcaseModel
|
2023-11-01 16:54:22 +00:00
|
|
|
}
|
|
|
|
|
2024-04-19 09:46:23 +00:00
|
|
|
SortFilterProxyModel {
|
|
|
|
id: inShowcaseSFPM
|
|
|
|
|
|
|
|
sourceModel: root.inShowcaseModel
|
|
|
|
delayed: true
|
|
|
|
filters: root.filter
|
|
|
|
}
|
|
|
|
|
|
|
|
SortFilterProxyModel {
|
|
|
|
id: hiddenSFPM
|
|
|
|
|
|
|
|
sourceModel: root.hiddenModel
|
|
|
|
delayed: true
|
|
|
|
filters: root.filter
|
|
|
|
}
|
|
|
|
|
|
|
|
MovableModel {
|
|
|
|
id: visibleModel
|
|
|
|
|
|
|
|
sourceModel: inShowcaseSFPM
|
|
|
|
}
|
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
clip: true
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
flickable1: EmptyShapeRectangleFooterListView {
|
|
|
|
id: inShowcaseListView
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-04-19 09:46:23 +00:00
|
|
|
model: visibleModel
|
2024-02-15 17:26:05 +00:00
|
|
|
width: root.width
|
2024-03-03 16:34:08 +00:00
|
|
|
placeholderText: d.searchActive ? root.emptySearchPlaceholderText : root.emptyInShowcasePlaceholderText
|
2024-02-23 07:14:55 +00:00
|
|
|
footerHeight: ProfileUtils.defaultDelegateHeight
|
|
|
|
footerContentVisible: !dropAreaRow.visible
|
2024-10-15 19:26:12 +00:00
|
|
|
spacing: Theme.halfPadding
|
2024-02-28 12:19:14 +00:00
|
|
|
delegate: delegateWrapper
|
2024-03-03 16:34:08 +00:00
|
|
|
header: ColumnLayout {
|
|
|
|
width: ListView.view.width
|
|
|
|
spacing: 0
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
SearchBox {
|
|
|
|
id: searcher
|
2024-03-03 11:02:30 +00:00
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
Layout.fillWidth: true
|
2024-03-03 11:02:30 +00:00
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
placeholderText: root.searchPlaceholderText
|
|
|
|
validators: [
|
|
|
|
StatusValidator {
|
|
|
|
property bool isEmoji: false
|
|
|
|
|
|
|
|
name: "check-for-no-emojis"
|
|
|
|
validate: (value) => {
|
|
|
|
if (!value) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
isEmoji = Constants.regularExpressions.emoji.test(value)
|
|
|
|
if (isEmoji){
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return Constants.regularExpressions.alphanumericalExpanded1.test(value)
|
|
|
|
}
|
|
|
|
errorMessage: isEmoji ?
|
|
|
|
qsTr("Your search is too cool (use A-Z and 0-9, hyphens and underscores only)")
|
|
|
|
: qsTr("Your search contains invalid characters (use A-Z and 0-9, hyphens and underscores only)")
|
2024-03-03 11:02:30 +00:00
|
|
|
}
|
2024-03-03 16:34:08 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
Binding {
|
2024-04-19 09:46:23 +00:00
|
|
|
target: d
|
2024-03-03 16:34:08 +00:00
|
|
|
property: "searcherText"
|
|
|
|
value: searcher.text
|
|
|
|
restoreMode: Binding.RestoreBindingOrValue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FoldableHeader {
|
|
|
|
readonly property bool isDropAreaVisible: root.flickable1Folded && d.isAnyHiddenDragActive
|
2024-03-03 11:02:30 +00:00
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
Layout.fillWidth: true
|
|
|
|
|
|
|
|
title: qsTr("In showcase")
|
|
|
|
folded: root.flickable1Folded
|
|
|
|
rightAdditionalComponent: isDropAreaVisible && d.limitReached ? limitReachedHeaderButton :
|
|
|
|
isDropAreaVisible ? dropHeaderAreaComponent : counterComponent
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: counterComponent
|
|
|
|
StatusBaseText {
|
|
|
|
id: counterText
|
|
|
|
|
|
|
|
width: d.additionalHeaderComponentWidth
|
|
|
|
height: d.additionalHeaderComponentHeight
|
|
|
|
horizontalAlignment: Text.AlignRight
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
text: "%1 / %2".arg(inShowcaseCounterTracker.count).arg(root.showcaseLimit)
|
2024-10-15 19:26:12 +00:00
|
|
|
font.pixelSize: Theme.tertiaryTextFontSize
|
2024-03-03 16:34:08 +00:00
|
|
|
color: Theme.palette.baseColor1
|
|
|
|
|
|
|
|
ColorAnimation {
|
|
|
|
id: animateColor
|
|
|
|
target: counterText
|
|
|
|
properties: "color"
|
|
|
|
from: Theme.palette.successColor1
|
|
|
|
to: Theme.palette.baseColor1
|
|
|
|
duration: 2000
|
|
|
|
}
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: d
|
|
|
|
function onStartAnimationChanged() {
|
|
|
|
animateColor.start()
|
|
|
|
}
|
2024-03-03 11:02:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
Component {
|
|
|
|
id: dropHeaderAreaComponent
|
|
|
|
VisibilityDropAreaButtonsRow {
|
|
|
|
margins: 0
|
|
|
|
width: d.additionalHeaderComponentWidth
|
|
|
|
height: d.additionalHeaderComponentHeight
|
|
|
|
}
|
2024-03-03 11:02:30 +00:00
|
|
|
}
|
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
Component {
|
|
|
|
id: limitReachedHeaderButton
|
|
|
|
VisibilityDropAreaButton {
|
|
|
|
width: d.additionalHeaderComponentWidth
|
|
|
|
height: d.additionalHeaderComponentHeight
|
|
|
|
rightInset: 1
|
|
|
|
text: qsTr("Showcase limit of %1 reached").arg(root.showcaseLimit)
|
|
|
|
enabled: false
|
|
|
|
textColor: Theme.palette.baseColor1
|
|
|
|
iconVisible: false
|
|
|
|
}
|
2024-03-03 11:02:30 +00:00
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-03-03 16:34:08 +00:00
|
|
|
onToggleFolding: root.flip1Folding()
|
|
|
|
}
|
2024-03-03 11:02:30 +00:00
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-23 07:14:55 +00:00
|
|
|
// Overlaid showcase listview content drop area:
|
2024-02-15 17:26:05 +00:00
|
|
|
DropArea {
|
|
|
|
anchors.bottom: parent.bottom
|
2024-02-23 07:14:55 +00:00
|
|
|
width: parent.width
|
|
|
|
height: parent.contentHeight
|
|
|
|
keys: d.dragHiddenItemKey
|
|
|
|
|
|
|
|
// Shown at the bottom of the listview
|
|
|
|
VisibilityDropAreaButtonsRow {
|
|
|
|
id: dropAreaRow
|
2024-02-15 17:26:05 +00:00
|
|
|
|
|
|
|
width: parent.width
|
2024-02-23 07:14:55 +00:00
|
|
|
height: ProfileUtils.defaultDelegateHeight
|
|
|
|
anchors.bottom: parent.bottom
|
2024-03-03 11:02:30 +00:00
|
|
|
visible: !d.limitReached &&
|
|
|
|
(d.isAnyHiddenDragActive ||
|
|
|
|
parent.containsDrag ||
|
|
|
|
everyoneContainsDrag ||
|
|
|
|
contactsContainsDrag ||
|
|
|
|
verifiedContainsDrag)
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-03 11:02:30 +00:00
|
|
|
|
|
|
|
// Overlaid showcase listview content when limit reached:
|
|
|
|
VisibilityDropAreaButton {
|
|
|
|
id: limitReachedButton
|
|
|
|
|
|
|
|
anchors.bottom: parent.bottom
|
2024-10-15 19:26:12 +00:00
|
|
|
anchors.bottomMargin: Theme.halfPadding
|
2024-03-03 11:02:30 +00:00
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
2024-10-15 19:26:12 +00:00
|
|
|
width: parent.width - Theme.padding
|
|
|
|
height: ProfileUtils.defaultDelegateHeight - Theme.padding
|
2024-03-03 11:02:30 +00:00
|
|
|
visible: d.isAnyHiddenDragActive && d.limitReached
|
|
|
|
enabled: false
|
|
|
|
text: qsTr("Showcase limit of %1 reached").arg(root.showcaseLimit)
|
|
|
|
textColor: Theme.palette.baseColor1
|
|
|
|
iconVisible: false
|
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
flickable2: EmptyShapeRectangleFooterListView {
|
|
|
|
id: hiddenListView
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-04-19 09:46:23 +00:00
|
|
|
model: hiddenSFPM
|
2024-02-15 17:26:05 +00:00
|
|
|
width: root.width
|
2024-03-03 16:34:08 +00:00
|
|
|
placeholderText: d.searchActive ? root.emptySearchPlaceholderText : root.emptyHiddenPlaceholderText
|
2024-02-23 07:14:55 +00:00
|
|
|
footerHeight: ProfileUtils.defaultDelegateHeight
|
|
|
|
footerContentVisible: !hiddenDropAreaButton.visible
|
2024-02-21 13:39:27 +00:00
|
|
|
additionalFooterComponent: root.additionalFooterComponent
|
2024-10-15 19:26:12 +00:00
|
|
|
spacing: Theme.halfPadding
|
2024-02-28 12:19:14 +00:00
|
|
|
delegate: delegateWrapper
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
header: FoldableHeader {
|
|
|
|
width: ListView.view.width
|
|
|
|
title: qsTr("Hidden")
|
|
|
|
folded: root.flickable2Folded
|
2024-02-26 11:07:06 +00:00
|
|
|
rightAdditionalComponent: VisibilityDropAreaButton {
|
|
|
|
visible: root.flickable2Folded && (d.isAnyShowcaseDragActive || parent.containsDrag || containsDrag)
|
|
|
|
width: d.additionalHeaderComponentWidth
|
|
|
|
height: d.additionalHeaderComponentHeight
|
|
|
|
rightInset: 1
|
|
|
|
text: qsTr("Hide")
|
|
|
|
dropAreaKeys: d.dragShowcaseItemKey
|
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
onToggleFolding: root.flip2Folding()
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|
|
|
|
|
2024-02-23 07:14:55 +00:00
|
|
|
// Overlaid hidden listview content drop area:
|
2024-02-15 17:26:05 +00:00
|
|
|
DropArea {
|
2024-02-23 07:14:55 +00:00
|
|
|
anchors.top: parent.top
|
|
|
|
width: parent.width
|
|
|
|
height: parent.contentHeight
|
|
|
|
keys: d.dragShowcaseItemKey
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-23 07:14:55 +00:00
|
|
|
// Shown at the top of the listview
|
|
|
|
VisibilityDropAreaButton {
|
|
|
|
id: hiddenDropAreaButton
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-23 07:14:55 +00:00
|
|
|
anchors.top: parent.top
|
2024-10-15 19:26:12 +00:00
|
|
|
anchors.topMargin: hiddenListView.headerItem.height + Theme.padding
|
2024-02-23 07:14:55 +00:00
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
|
|
|
|
visible: d.isAnyShowcaseDragActive || parent.containsDrag || hiddenDropAreaButton.containsDrag
|
2024-10-15 19:26:12 +00:00
|
|
|
width: parent.width - Theme.padding
|
|
|
|
height: ProfileUtils.defaultDelegateHeight - Theme.padding
|
2024-02-23 07:14:55 +00:00
|
|
|
text: qsTr("Hide")
|
|
|
|
dropAreaKeys: d.dragShowcaseItemKey
|
2024-03-10 21:31:48 +00:00
|
|
|
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|
2024-02-15 17:26:05 +00:00
|
|
|
}
|
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-23 07:14:55 +00:00
|
|
|
component VisibilityDropAreaButton: AbstractButton {
|
|
|
|
id: visibilityDropAreaButton
|
2024-02-15 17:26:05 +00:00
|
|
|
|
|
|
|
readonly property alias containsDrag: dropArea.containsDrag
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-03-03 11:02:30 +00:00
|
|
|
property bool iconVisible: true
|
|
|
|
property string textColor: icon.color
|
2024-02-23 07:14:55 +00:00
|
|
|
property int showcaseVisibility: Constants.ShowcaseVisibility.NoOne
|
2024-03-03 11:02:30 +00:00
|
|
|
property var dropAreaKeys: []
|
2024-02-23 07:14:55 +00:00
|
|
|
|
2024-10-15 19:26:12 +00:00
|
|
|
padding: Theme.halfPadding
|
2024-02-15 17:26:05 +00:00
|
|
|
spacing: padding/2
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
icon.color: Theme.palette.primaryColor1
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-03-10 21:31:48 +00:00
|
|
|
visible: d.dragItem && d.dragItem.showcaseMaxVisibility >= showcaseVisibility
|
|
|
|
|
2024-03-18 08:14:35 +00:00
|
|
|
background: Rectangle {
|
|
|
|
id: shapeWrapper
|
2024-02-23 07:14:55 +00:00
|
|
|
|
2024-03-18 08:14:35 +00:00
|
|
|
color: dropArea.containsDrag ? Theme.palette.primaryColor3 : Theme.palette.getColor(Theme.palette.baseColor4, 0.7)
|
2024-10-15 19:26:12 +00:00
|
|
|
radius: Theme.radius
|
2024-03-18 08:14:35 +00:00
|
|
|
|
|
|
|
ShapeRectangle {
|
2024-02-15 17:26:05 +00:00
|
|
|
anchors.fill: parent
|
2024-03-18 08:14:35 +00:00
|
|
|
anchors.margins: path.strokeWidth / 2
|
|
|
|
radius: shapeWrapper.radius
|
|
|
|
path.strokeColor: dropArea.containsDrag ? Theme.palette.primaryColor3 : Theme.palette.directColor7
|
|
|
|
path.fillColor: "transparent"
|
|
|
|
DropArea {
|
|
|
|
id: dropArea
|
|
|
|
|
|
|
|
anchors.fill: parent
|
|
|
|
keys: visibilityDropAreaButton.dropAreaKeys
|
|
|
|
|
|
|
|
onEntered: function(drag) {
|
|
|
|
drag.accept()
|
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-03-18 08:14:35 +00:00
|
|
|
onDropped: function(drop) {
|
|
|
|
d.setVisibilityInternalRequested(drop.source.key, visibilityDropAreaButton.showcaseVisibility)
|
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-15 17:26:05 +00:00
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
contentItem: Item {
|
|
|
|
RowLayout {
|
|
|
|
width: Math.min(parent.width, implicitWidth)
|
|
|
|
anchors.centerIn: parent
|
2024-02-23 07:14:55 +00:00
|
|
|
spacing: visibilityDropAreaButton.spacing
|
2023-03-20 12:29:05 +00:00
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
StatusIcon {
|
2024-03-03 11:02:30 +00:00
|
|
|
visible: visibilityDropAreaButton.iconVisible
|
2024-02-15 17:26:05 +00:00
|
|
|
width: 20
|
|
|
|
height: width
|
2024-02-23 07:14:55 +00:00
|
|
|
icon: ProfileUtils.visibilityIcon(visibilityDropAreaButton.showcaseVisibility)
|
|
|
|
color: visibilityDropAreaButton.icon.color
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|
|
|
|
|
2024-02-15 17:26:05 +00:00
|
|
|
StatusBaseText {
|
|
|
|
Layout.fillWidth: true
|
2024-10-15 19:26:12 +00:00
|
|
|
font.pixelSize: Theme.additionalTextSize
|
2024-02-15 17:26:05 +00:00
|
|
|
font.weight: Font.Medium
|
|
|
|
elide: Text.ElideRight
|
2024-03-03 11:02:30 +00:00
|
|
|
color: visibilityDropAreaButton.textColor
|
2024-02-23 07:14:55 +00:00
|
|
|
text: visibilityDropAreaButton.text
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-02-23 07:14:55 +00:00
|
|
|
|
|
|
|
component VisibilityDropAreaButtonsRow: Item {
|
|
|
|
id: visibilityDropAreaRow
|
|
|
|
|
|
|
|
readonly property bool everyoneContainsDrag: dropAreaEveryone.containsDrag
|
|
|
|
readonly property bool contactsContainsDrag: dropAreaContacts.containsDrag
|
|
|
|
readonly property bool verifiedContainsDrag: dropAreaVerified.containsDrag
|
2024-10-15 19:26:12 +00:00
|
|
|
property int margins: Theme.halfPadding
|
2024-02-23 07:14:55 +00:00
|
|
|
|
|
|
|
RowLayout {
|
|
|
|
anchors.fill: parent
|
2024-02-26 11:07:06 +00:00
|
|
|
anchors.margins: visibilityDropAreaRow.margins
|
2024-10-15 19:26:12 +00:00
|
|
|
spacing: Theme.halfPadding
|
2024-02-23 07:14:55 +00:00
|
|
|
|
|
|
|
VisibilityDropAreaButton {
|
|
|
|
id: dropAreaEveryone
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
showcaseVisibility: Constants.ShowcaseVisibility.Everyone
|
|
|
|
text: qsTr("Everyone")
|
|
|
|
dropAreaKeys: d.dragHiddenItemKey
|
|
|
|
}
|
|
|
|
|
|
|
|
VisibilityDropAreaButton {
|
|
|
|
id: dropAreaContacts
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
showcaseVisibility: Constants.ShowcaseVisibility.Contacts
|
|
|
|
text: qsTr("Contacts")
|
|
|
|
dropAreaKeys: d.dragHiddenItemKey
|
|
|
|
}
|
|
|
|
|
|
|
|
VisibilityDropAreaButton {
|
|
|
|
id: dropAreaVerified
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
showcaseVisibility: Constants.ShowcaseVisibility.IdVerifiedContacts
|
|
|
|
text: qsTr("Verified")
|
|
|
|
dropAreaKeys: d.dragHiddenItemKey
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
component ShadowDelegate: Rectangle {
|
|
|
|
width: parent.width
|
|
|
|
height: ProfileUtils.defaultDelegateHeight
|
|
|
|
anchors.centerIn: parent
|
|
|
|
color: Theme.palette.baseColor5
|
2024-10-15 19:26:12 +00:00
|
|
|
radius: Theme.radius
|
2024-02-23 07:14:55 +00:00
|
|
|
}
|
2024-03-03 16:34:08 +00:00
|
|
|
|
2024-02-28 12:19:14 +00:00
|
|
|
Component {
|
|
|
|
id: delegateWrapper
|
2024-03-03 11:02:30 +00:00
|
|
|
DropArea {
|
2024-02-28 12:19:14 +00:00
|
|
|
id: showcaseDelegateRoot
|
|
|
|
|
|
|
|
required property var model
|
|
|
|
required property int index
|
|
|
|
readonly property int visualIndex: index
|
2024-03-04 22:07:09 +00:00
|
|
|
readonly property bool isHiddenShowcaseItem: !model.showcaseVisibility || model.showcaseVisibility === Constants.ShowcaseVisibility.NoOne
|
2024-02-28 12:19:14 +00:00
|
|
|
|
|
|
|
function handleEntered(drag) {
|
|
|
|
if (!showcaseDelegateRoot.isHiddenShowcaseItem) {
|
|
|
|
var from = drag.source.visualIndex
|
|
|
|
var to = visualIndex
|
|
|
|
if (to === from)
|
|
|
|
return
|
2024-04-19 09:46:23 +00:00
|
|
|
|
|
|
|
const sourceIndex = inShowcaseSFPM.mapToSource(visibleModel.order()[from])
|
|
|
|
const targetPosition = showcaseDelegateRoot.model.showcasePosition
|
|
|
|
visibleModel.move(from, to)
|
|
|
|
root.changePositionRequested(sourceIndex, targetPosition)
|
2024-02-28 12:19:14 +00:00
|
|
|
}
|
|
|
|
drag.accept()
|
|
|
|
}
|
|
|
|
function handleDropped(drop) {
|
|
|
|
if (showcaseDelegateRoot.isHiddenShowcaseItem) {
|
2024-03-03 11:02:30 +00:00
|
|
|
d.setVisibilityInternalRequested(drop.source.key, Constants.ShowcaseVisibility.NoOne)
|
2024-02-28 12:19:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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: showcaseDraggableDelegateLoader.item ? showcaseDraggableDelegateLoader.item.height : 0
|
|
|
|
keys: d.dragShowcaseItemKey
|
|
|
|
|
|
|
|
onEntered: handleEntered(drag)
|
|
|
|
onDropped: handleDropped(drop)
|
|
|
|
|
|
|
|
// In showcase delegate item container:
|
|
|
|
Loader {
|
|
|
|
id: showcaseDraggableDelegateLoader
|
|
|
|
|
|
|
|
property var modelData: showcaseDelegateRoot.model
|
|
|
|
property var dragParentData: root
|
|
|
|
property int visualIndexData: showcaseDelegateRoot.index
|
|
|
|
property var dragKeysData: showcaseDelegateRoot.isHiddenShowcaseItem ?
|
2024-03-03 11:02:30 +00:00
|
|
|
d.dragHiddenItemKey : d.dragShowcaseItemKey
|
2024-02-28 12:19:14 +00:00
|
|
|
|
|
|
|
width: parent.width
|
|
|
|
sourceComponent: root.delegate
|
2024-02-29 09:07:35 +00:00
|
|
|
onItemChanged: {
|
|
|
|
if (item) {
|
2024-03-03 11:02:30 +00:00
|
|
|
item.showcaseVisibilityRequested.connect((toVisibility) => d.setVisibilityInternalRequested(showcaseDelegateRoot.model.showcaseKey, toVisibility))
|
2024-02-29 09:07:35 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-28 12:19:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Binding {
|
2024-03-03 11:02:30 +00:00
|
|
|
when: showcaseDelegateRoot.isHiddenShowcaseItem ? d.isAnyShowcaseDragActive : (d.isAnyHiddenDragActive ||
|
|
|
|
(d.isAnyHiddenDragActive && d.limitReached))
|
|
|
|
target: showcaseDraggableDelegateLoader.item
|
|
|
|
property: "blurState"
|
|
|
|
value: true
|
|
|
|
restoreMode: Binding.RestoreBindingOrValue
|
|
|
|
}
|
|
|
|
|
|
|
|
Binding {
|
2024-02-28 12:19:14 +00:00
|
|
|
when: showcaseShadow.visible
|
|
|
|
target: d
|
|
|
|
property: showcaseDelegateRoot.isHiddenShowcaseItem ? "isAnyHiddenDragActive" : "isAnyShowcaseDragActive"
|
|
|
|
value: true
|
|
|
|
restoreMode: Binding.RestoreBindingOrValue
|
2024-03-03 11:02:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Binding {
|
|
|
|
when: showcaseDelegateRoot.isHiddenShowcaseItem && d.limitReached
|
|
|
|
target: showcaseDraggableDelegateLoader.item
|
|
|
|
property: "contextMenuEnabled"
|
|
|
|
value: false
|
|
|
|
restoreMode: Binding.RestoreBindingOrValue
|
|
|
|
}
|
|
|
|
|
|
|
|
Binding {
|
2024-10-15 19:26:12 +00:00
|
|
|
when: showcaseDelegateRoot.isHiddenShowcaseItem && d.limitReached
|
2024-03-03 11:02:30 +00:00
|
|
|
target: showcaseDraggableDelegateLoader.item
|
|
|
|
property: "tooltipTextWhenContextMenuDisabled"
|
|
|
|
value: qsTr("Showcase limit of %1 reached. <br>Remove item from showcase to add more.").arg(root.showcaseLimit)
|
|
|
|
restoreMode: Binding.RestoreBindingOrValue
|
|
|
|
}
|
2024-02-28 12:19:14 +00:00
|
|
|
|
2024-03-10 21:31:48 +00:00
|
|
|
Binding {
|
|
|
|
when: showcaseDraggableDelegateLoader.item && showcaseDraggableDelegateLoader.item.dragActive
|
|
|
|
target: d
|
|
|
|
property: "dragItem"
|
|
|
|
value: showcaseDraggableDelegateLoader.item
|
|
|
|
restoreMode: Binding.RestoreBindingOrValue
|
|
|
|
}
|
|
|
|
|
2024-02-28 12:19:14 +00:00
|
|
|
// Delegate shadow background when dragging:
|
|
|
|
ShadowDelegate {
|
|
|
|
id: showcaseShadow
|
|
|
|
|
|
|
|
visible: showcaseDraggableDelegateLoader.item && showcaseDraggableDelegateLoader.item.dragActive
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-03-20 12:29:05 +00:00
|
|
|
}
|