feat(ProfileShowcase): Add foldable sections in profile showcase tabs

- Modified `ProfileShowcasePanel` with 2 foldable sections.
-  Modified api of `ProfileShowcaseCommunitiesPanel` with the new base component.
- Modified api of `ProfileShowcaseAccountsPanel` with the new base component.
- Modified api of `ProfileShowcaseAssetsPanel`  and `ProfileShowcaseCollectiblesPanel` with the new base component.
- Added needed `storybook` support.

Closes of #13504
This commit is contained in:
Noelia 2024-02-15 18:26:05 +01:00 committed by Noelia
parent 9c3159ecd1
commit 01095e0208
10 changed files with 359 additions and 325 deletions

View File

@ -1,5 +1,6 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1 as CoreUtils
@ -28,6 +29,10 @@ SplitView {
readonly property string currentWallet: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7420"
ListModel {
id: emptyModel
}
ListModel {
id: accountsModel
@ -52,18 +57,13 @@ SplitView {
emoji: "🇸🇰"
walletType: "watch"
}
ListElement {
name: "Keycard"
address: "0xdeadbeef"
colorId: "turquoise"
emoji: ""
walletType: "key"
}
}
ListModel {
id: inShowcaseAccountsModel
property int hiddenCount: emptyModelChecker.checked ? 0 : accountsModel.count - count
signal baseModelFilterConditionsMayHaveChanged()
function setVisibilityByIndex(index, visibility) {
@ -102,7 +102,7 @@ SplitView {
ProfileShowcaseAccountsPanel {
id: showcasePanel
width: 500
baseModel: accountsModel
baseModel: emptyModelChecker.checked ? emptyModel : accountsModel
showcaseModel: inShowcaseAccountsModel
currentWallet: root.currentWallet
}
@ -116,15 +116,25 @@ SplitView {
logsView.logText: logs.logText
Button {
text: "Reset (clear settings)"
onClicked: showcasePanel.settings.reset()
ColumnLayout {
Button {
text: "Reset (clear settings)"
onClicked: showcasePanel.reset()
}
CheckBox {
id: emptyModelChecker
text: "Empty model"
checked: false
onClicked: showcasePanel.reset()
}
}
}
}
// category: Panels
// https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=14580-339549&t=RkXAEv3G6mp3EUvl-0
// https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=14729-233846&t=RkXAEv3G6mp3EUvl-0
// https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=14609-237740&t=RkXAEv3G6mp3EUvl-0
// https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?type=design&node-id=2460%3A40333&mode=design&t=Zj3tcx9uj05XHYti-1
// https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?type=design&node-id=2460%3A40362&mode=design&t=Zj3tcx9uj05XHYti-1

View File

@ -33,9 +33,15 @@ SplitView {
assetsWithFilteredBalances: walletAssetStore.groupedAccountsAssetsModel
}
ListModel {
id: emptyModel
}
ListModel {
id: inShowcaseAssetsModel
property int hiddenCount: emptyModelChecker.checked ? 0 : walletAssetStore.groupedAccountsAssetsModel.count - count
signal baseModelFilterConditionsMayHaveChanged()
function setVisibilityByIndex(index, visibility) {
@ -75,7 +81,7 @@ SplitView {
ProfileShowcaseAssetsPanel {
id: showcasePanel
width: 500
baseModel: walletAssetStore.groupedAccountAssetsModel
baseModel: emptyModelChecker.checked ? emptyModel : walletAssetStore.groupedAccountAssetsModel
showcaseModel: inShowcaseAssetsModel
addAccountsButtonVisible: !hasAllAccountsChecker.checked
@ -111,6 +117,15 @@ SplitView {
text: "Has the user already shared all of their accounts"
checked: true
}
CheckBox {
id: emptyModelChecker
text: "Empty model"
checked: false
onClicked: showcasePanel.reset()
}
}
}
}

View File

@ -29,6 +29,10 @@ SplitView {
communityTokensStore: CommunityTokensStore {}
}
ListModel {
id: emptyModel
}
ListModel {
id: collectiblesModel
@ -124,6 +128,8 @@ SplitView {
ListModel {
id: inShowcaseCollectiblesModel
property int hiddenCount: emptyModelChecker.checked ? 0 : collectiblesModel.count - count
signal baseModelFilterConditionsMayHaveChanged()
function setVisibilityByIndex(index, visibility) {
@ -162,7 +168,7 @@ SplitView {
ProfileShowcaseCollectiblesPanel {
id: showcasePanel
width: 500
baseModel: leftJoinModel
baseModel: emptyModelChecker.checked ? emptyModel : leftJoinModel
showcaseModel: inShowcaseCollectiblesModel
addAccountsButtonVisible: !hasAllAccountsChecker.checked
@ -192,6 +198,15 @@ SplitView {
checked: true
}
CheckBox {
id: emptyModelChecker
text: "Empty model"
checked: false
onClicked: showcasePanel.reset()
}
}
}
}

View File

@ -1,11 +1,13 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1 as CoreUtils
import mainui 1.0
import AppLayouts.Profile.panels 1.0
import AppLayouts.Profile.controls 1.0
import shared.stores 1.0
import utils 1.0
@ -26,6 +28,10 @@ SplitView {
communityTokensStore: CommunityTokensStore {}
}
ListModel {
id: emptyModel
}
ListModel {
id: communitiesModel
@ -48,15 +54,6 @@ SplitView {
image: ModelsData.collectibles.custom,
color: "peach"
},
{
id: "0x0003",
name: "Test community invisible",
joined: false,
memberRole: Constants.memberRole.none,
isControlNode: false,
image: "",
color: "red"
},
{
id: "0x0004",
name: "Test community 3",
@ -81,13 +78,15 @@ SplitView {
ListModel {
id: inShowcaseCommunitiesModel
property int hiddenCount: emptyModelChecker.checked ? 0 : communitiesModel.count - count
signal baseModelFilterConditionsMayHaveChanged()
function setVisibilityByIndex(index, visibility) {
if (visibility === Constants.ShowcaseVisibility.NoOne) {
remove(index)
} else {
get(index).showcaseVisibility = visibility
get(index).showcaseVisibility = visibility
}
}
@ -116,10 +115,11 @@ SplitView {
StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml
SplitView.fillWidth: true
SplitView.preferredHeight: 500
ProfileShowcaseCommunitiesPanel {
id: showcasePanel
width: 500
baseModel: communitiesModel
baseModel: emptyModelChecker.checked ? emptyModel : communitiesModel
showcaseModel: inShowcaseCommunitiesModel
}
}
@ -132,9 +132,20 @@ SplitView {
logsView.logText: logs.logText
Button {
text: "Reset (clear settings)"
onClicked: showcasePanel.settings.reset()
ColumnLayout {
Button {
text: "Reset (clear settings)"
onClicked: showcasePanel.reset()
}
CheckBox {
id: emptyModelChecker
text: "Empty model"
checked: false
onClicked: showcasePanel.reset()
}
}
}
}

View File

@ -12,10 +12,10 @@ ProfileShowcasePanel {
keyRole: "address"
roleNames: ["address", "name", "walletType", "emoji", "colorId"].concat(showcaseRoles)
filterFunc: (modelData) => modelData.walletType !== Constants.keyWalletType && !showcaseModel.hasItemInShowcase(modelData.address)
hiddenPlaceholderBanner: qsTr("Accounts here will show on your profile")
showcasePlaceholderBanner: qsTr("Accounts here will be hidden from your profile")
emptyInShowcasePlaceholderText: qsTr("Accounts here will show on your profile")
emptyHiddenPlaceholderText: qsTr("Accounts here will be hidden from your profile")
draggableDelegateComponent: AccountShowcaseDelegate {
hiddenDraggableDelegateComponent: AccountShowcaseDelegate {
Drag.keys: ["x-status-draggable-showcase-item-hidden"]
showcaseObj: modelData
dragParent: dragParentData

View File

@ -21,10 +21,10 @@ ProfileShowcasePanel {
keyRole: "symbol"
roleNames: ["symbol", "name", "address", "communityId", "enabledNetworkBalance", "decimals"].concat(showcaseRoles)
filterFunc: (modelData) => modelData.symbol !== "" && !showcaseModel.hasItemInShowcase(modelData.symbol)
hiddenPlaceholderBanner: qsTr("Assets here will show on your profile")
showcasePlaceholderBanner: qsTr("Assets here will be hidden from your profile")
emptyInShowcasePlaceholderText: qsTr("Assets here will show on your profile")
emptyHiddenPlaceholderText: qsTr("Assets here will be hidden from your profile")
draggableDelegateComponent: AssetShowcaseDelegate {
hiddenDraggableDelegateComponent: AssetShowcaseDelegate {
Drag.keys: ["x-status-draggable-showcase-item-hidden"]
showcaseObj: modelData
dragParent: dragParentData
@ -52,15 +52,17 @@ ProfileShowcasePanel {
root.showcaseEntryChanged()
}
}
additionalComponent: root.addAccountsButtonVisible ? addMoreAccountsComponent : null
Component {
id: addMoreAccountsComponent
// TODO: Issue #13590
// additionalComponent: root.addAccountsButtonVisible ? addMoreAccountsComponent : null
AddMoreAccountsLink {
visible: root.addAccountsButtonVisible
text: qsTr("Dont see some of your assets?")
onClicked: root.navigateToAccountsTab()
}
}
// Component {
// id: addMoreAccountsComponent
// AddMoreAccountsLink {
// visible: root.addAccountsButtonVisible
// text: qsTr("Dont see some of your assets?")
// onClicked: root.navigateToAccountsTab()
// }
// }
}

View File

@ -19,10 +19,10 @@ ProfileShowcasePanel {
keyRole: "uid"
roleNames: ["uid", "chainId", "tokenId", "contractAddress", "communityId", "name", "collectionName", "backgroundColor", "imageUrl"].concat(showcaseRoles)
filterFunc: (modelData) => !showcaseModel.hasItemInShowcase(modelData.uid)
hiddenPlaceholderBanner: qsTr("Collectibles here will show on your profile")
showcasePlaceholderBanner: qsTr("Collectibles here will be hidden from your profile")
emptyInShowcasePlaceholderText: qsTr("Collectibles here will show on your profile")
emptyHiddenPlaceholderText: qsTr("Collectibles here will be hidden from your profile")
draggableDelegateComponent: CollectibleShowcaseDelegate {
hiddenDraggableDelegateComponent: CollectibleShowcaseDelegate {
Drag.keys: ["x-status-draggable-showcase-item-hidden"]
showcaseObj: modelData
dragParent: dragParentData
@ -47,15 +47,17 @@ ProfileShowcasePanel {
root.showcaseEntryChanged()
}
}
additionalComponent: root.addAccountsButtonVisible ? addMoreAccountsComponent : null
Component {
id: addMoreAccountsComponent
// TODO: Issue #13590
// additionalComponent: root.addAccountsButtonVisible ? addMoreAccountsComponent : null
AddMoreAccountsLink {
visible: root.addAccountsButtonVisible
text: qsTr("Dont see some of your collectibles?")
onClicked: root.navigateToAccountsTab()
}
}
// Component {
// id: addMoreAccountsComponent
// AddMoreAccountsLink {
// visible: root.addAccountsButtonVisible
// text: qsTr("Dont see some of your collectibles?")
// onClicked: root.navigateToAccountsTab()
// }
// }
}

View File

@ -9,11 +9,11 @@ ProfileShowcasePanel {
keyRole: "id"
roleNames: ["id", "name", "memberRole", "image", "color"].concat(showcaseRoles)
filterFunc: (modelData) => modelData.joined && !showcaseModel.hasItemInShowcase(modelData.id)
hiddenPlaceholderBanner: qsTr("Communities here will show on your profile")
showcasePlaceholderBanner: qsTr("Communities here will be hidden from your profile")
filterFunc: (modelData) => modelData.joined && !root.showcaseModel.hasItemInShowcase(modelData.id)
emptyInShowcasePlaceholderText: qsTr("Drag communities here to display in showcase")
emptyHiddenPlaceholderText: qsTr("Communities here will be hidden from your Profile")
draggableDelegateComponent: CommunityShowcaseDelegate {
hiddenDraggableDelegateComponent: CommunityShowcaseDelegate {
Drag.keys: ["x-status-draggable-showcase-item-hidden"]
showcaseObj: modelData
dragParent: dragParentData
@ -22,7 +22,7 @@ ProfileShowcasePanel {
var tmpObj = Object()
root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role])
tmpObj.showcaseVisibility = value
showcaseModel.upsertItemJson(JSON.stringify(tmpObj))
root.showcaseModel.upsertItemJson(JSON.stringify(tmpObj))
root.showcaseEntryChanged()
}
}
@ -34,7 +34,7 @@ ProfileShowcasePanel {
dragAxis: Drag.YAxis
showcaseVisibility: !!modelData ? modelData.showcaseVisibility : Constants.ShowcaseVisibility.NoOne
onShowcaseVisibilityRequested: {
showcaseModel.setVisibility(showcaseObj.id, value)
root.showcaseModel.setVisibility(showcaseObj.id, value)
root.showcaseEntryChanged()
}
}

View File

@ -1,60 +1,267 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQml 2.15
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Utils 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 {
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
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
property Component additionalComponent
property Component hiddenDraggableDelegateComponent
signal showcaseEntryChanged()
function reset() {
showcaseModel.clear()
updateBaseModelFilters()
}
function updateBaseModelFilters() {
// Reset base model to update filter conditions
hiddenItemsListView.model = null
hiddenItemsListView.model = baseModel
}
property string emptyInShowcasePlaceholderText
property string emptyHiddenPlaceholderText
readonly property Connections showcaseUpdateConnections: Connections {
target: showcaseModel
target: root.showcaseModel
function onBaseModelFilterConditionsMayHaveChanged() {
root.updateBaseModelFilters()
}
}
background: null
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 int defaultDelegateHeight: 60
readonly property int contentSpacing: 12
readonly property int strokeMargin: 2
readonly property int shapeRectangleHeight: 48
}
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
placeholderHeight: d.shapeRectangleHeight
header: FoldableHeader {
width: ListView.view.width
title: qsTr("In showcase")
folded: root.flickable1Folded
onToggleFolding: root.flip1Folding()
}
delegate: DropArea {
id: showcaseDelegateRoot
property int visualIndex: index
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()
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
width: parent.width
sourceComponent: root.showcaseDraggableDelegateComponent
property var modelData: model
property var dragParentData: root
property int visualIndexData: index
}
}
// TO BE REDEFINED (task #13509): Overlaid at the bottom of the listview
DropArea {
id: targetDropArea
width: parent.width
height: inShowcaseListView.count === 0 ? d.shapeRectangleHeight : d.defaultDelegateHeight
anchors.bottom: parent.bottom
anchors.bottomMargin: root.showcaseModel.count ? Style.current.halfPadding : 0
keys: ["x-status-draggable-showcase-item-hidden"]
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")
}
}
}
}
}
flickable2: EmptyShapeRectangleFooterListView {
id: hiddenListView
model: root.baseModel
width: root.width
placeholderText: root.emptyHiddenPlaceholderText
placeholderHeight: d.shapeRectangleHeight
empty: root.showcaseModel.hiddenCount === 0 && !root.flickable2Folded // TO BE REMOVE: #13498
header: FoldableHeader {
width: ListView.view.width
title: qsTr("Hidden")
folded: root.flickable2Folded
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: ["x-status-draggable-showcase-item"]
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
width: parent.width
sourceComponent: root.hiddenDraggableDelegateComponent
property var modelData: model
property var dragParentData: root
property int visualIndexData: hiddenDelegateRoot.visualIndex
}
// Delegate shadow background when dragging:
Rectangle {
width: parent.width
height: d.defaultDelegateHeight
anchors.centerIn: parent
color: Theme.palette.baseColor5
radius: Style.current.radius
visible: hiddenDraggableDelegateLoader.item && hiddenDraggableDelegateLoader.item.dragActive
}
}
// TO BE REDEFINED (task #13509): Overlaid at the top of the listview
DropArea {
id: hiddenTargetDropArea
width: root.width
height: hiddenListView.empty ? d.shapeRectangleHeight : d.defaultDelegateHeight
anchors.top: hiddenListView.top
anchors.topMargin: hiddenListView.empty ? hiddenListView.headerItem.height : hiddenListView.headerItem.height + Style.current.halfPadding
keys: ["x-status-draggable-showcase-item"]
ShapeRectangle {
width: parent.width
height: parent.height + d.strokeMargin
anchors.centerIn: parent
visible: parent.containsDrag
path.fillColor: Theme.palette.baseColor5
path.strokeColor: "transparent"
text: root.emptyHiddenPlaceholderText
}
onEntered: function(drag) {
drag.accept()
}
onDropped: function(drop) {
root.showcaseModel.setVisibilityByIndex(drop.source.visualIndex, Constants.ShowcaseVisibility.NoOne)
root.showcaseEntryChanged()
root.updateBaseModelFilters()
}
}
}
// TO BE REDEFINED (task #13509)
component VisibilityDropArea: AbstractButton {
id: visibilityDropAreaLocal
@ -89,7 +296,7 @@ Control {
var tmpObj = Object()
root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role])
tmpObj.showcaseVisibility = visibilityDropAreaLocal.showcaseVisibility
showcaseModel.upsertItemJson(JSON.stringify(tmpObj))
root.showcaseModel.upsertItemJson(JSON.stringify(tmpObj))
root.showcaseEntryChanged()
}
}
@ -100,12 +307,14 @@ Control {
width: Math.min(parent.width, implicitWidth)
anchors.centerIn: parent
spacing: visibilityDropAreaLocal.spacing
StatusIcon {
width: 20
height: 20
height: width
icon: ProfileUtils.visibilityIcon(visibilityDropAreaLocal.showcaseVisibility)
color: visibilityDropAreaLocal.icon.color
}
StatusBaseText {
Layout.fillWidth: true
font.pixelSize: 13
@ -117,234 +326,4 @@ Control {
}
}
}
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, 1)
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)
implicitHeight: contentHeight
interactive: false
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()
}
}
}
Loader {
id: additionalComponent
Layout.fillWidth: true
sourceComponent: root.additionalComponent
}
Item { Layout.fillHeight: true }
}
}

View File

@ -66,7 +66,7 @@ Shape {
id: description
color: root.textColor
text: root.text
font.pixelSize: 13
font.pixelSize: Style.current.additionalTextSize
visible: !!text
}
}