2024-01-16 16:22:05 +00:00
import QtQuick 2.15
import QtQuick . Controls 2.15
import QtQuick . Layouts 1.15
import StatusQ 0.1
import StatusQ . Core 0.1
import StatusQ . Components 0.1
import StatusQ . Controls 0.1
import StatusQ . Core . Theme 0.1
import StatusQ . Models 0.1
import utils 1.0
import shared . controls 1.0
import AppLayouts . Wallet . controls 1.0
import SortFilterProxyModel 0.2
Control {
id: root
required property var assetsController
required property var collectiblesController
2024-01-25 18:53:09 +00:00
property var getCurrencyAmount: function ( balance , symbol ) { }
property var getCurrentCurrencyAmount: function ( balance ) { }
2024-01-16 16:22:05 +00:00
readonly property bool dirty: false // never dirty, the "show xxx" actions are immediate
readonly property bool hasSettings: root . assetsController . hasSettings || root . collectiblesController . hasSettings
background: null
function clearSettings ( ) {
2024-03-01 02:04:36 +00:00
root . assetsController . requestClearSettings ( ) ;
root . collectiblesController . requestClearSettings ( ) ;
2024-01-16 16:22:05 +00:00
}
QtObject {
id: d
property bool assetsExpanded: true
property bool collectiblesExpanded: true
readonly property int assetsCount: root . assetsController . hiddenTokensModel . count + root . assetsController . hiddenCommunityTokenGroupsModel . count
readonly property int collectiblesCount: root . collectiblesController . hiddenTokensModel . count + root . collectiblesController . hiddenCommunityTokenGroupsModel . count // + TODO collection groups
readonly property var filteredHiddenAssets: SortFilterProxyModel {
sourceModel: root . assetsController . hiddenTokensModel
filters: FastExpressionFilter {
expression: {
root . assetsController . hiddenCommunityGroups
return ! root . assetsController . hiddenCommunityGroups . includes ( model . communityId )
}
expectedRoles: [ "communityId" ]
}
}
readonly property var filteredHiddenCollectibles: SortFilterProxyModel {
sourceModel: root . collectiblesController . hiddenTokensModel
filters: FastExpressionFilter {
expression: {
root . collectiblesController . hiddenCommunityGroups
2024-01-19 09:53:32 +00:00
root . collectiblesController . hiddenCollectionGroups
return ! root . collectiblesController . hiddenCommunityGroups . includes ( model . communityId ) &&
! root . collectiblesController . hiddenCollectionGroups . includes ( model . collectionUid )
2024-01-16 16:22:05 +00:00
}
2024-01-19 09:53:32 +00:00
expectedRoles: [ "communityId" , "collectionUid" ]
2024-01-16 16:22:05 +00:00
}
}
readonly property var combinedModel: ConcatModel {
sources: [
2024-01-19 09:53:32 +00:00
// assets
2024-01-16 16:22:05 +00:00
SourceModel { // single hidden assets (not belonging to a group)
model: d . filteredHiddenAssets
markerRoleValue: "asset"
} ,
SourceModel { // community asset groups
model: root . assetsController . hiddenCommunityTokenGroupsModel
markerRoleValue: "assetGroup"
} ,
2024-01-19 09:53:32 +00:00
// collectibles
SourceModel { // single hidden collectibles (not belonging to any group)
2024-01-16 16:22:05 +00:00
model: d . filteredHiddenCollectibles
markerRoleValue: "collectible"
} ,
SourceModel { // community collectible groups
model: root . collectiblesController . hiddenCommunityTokenGroupsModel
markerRoleValue: "collectibleGroup"
2024-01-19 09:53:32 +00:00
} ,
SourceModel { // collectible collection groups
model: root . collectiblesController . hiddenCollectionGroupsModel
markerRoleValue: "collectibleCollectionGroup"
2024-01-16 16:22:05 +00:00
}
]
markerRoleName: "tokenType"
}
readonly property var sfpm: SortFilterProxyModel {
sourceModel: d . combinedModel
proxyRoles: [
FastExpressionRole {
name: "isCollectible"
expression: model . tokenType . startsWith ( "collectible" )
expectedRoles: "tokenType"
} ,
FastExpressionRole {
name: "isGroup"
expression: model . tokenType . endsWith ( "Group" )
expectedRoles: "tokenType"
}
]
// TODO sort by recency/timestamp (newest first)
}
}
component SectionDelegate: Rectangle {
id: sectionDelegate
height: 64
color: Theme . palette . statusListItem . backgroundColor
property bool isCollectible
RowLayout {
anchors.fill: parent
StatusFlatButton {
size: StatusBaseButton . Size . Small
icon.name: checked ? "chevron-down" : "next"
checked: sectionDelegate . isCollectible ? d.collectiblesExpanded : d . assetsExpanded
textColor: Theme . palette . baseColor1
textHoverColor: Theme . palette . directColor1
onToggled: {
if ( sectionDelegate . isCollectible )
d . collectiblesExpanded = ! d . collectiblesExpanded
else
d . assetsExpanded = ! d . assetsExpanded
}
}
StatusBaseText {
Layout.fillWidth: true
text: sectionDelegate . isCollectible ? qsTr ( "Collectibles" ) : qsTr ( "Assets" )
elide: Text . ElideRight
}
}
}
component Placeholder: ShapeRectangle {
property bool isCollectible
text: isCollectible ? qsTr ( "Your hidden collectibles will appear here" ) : qsTr ( "Your hidden assets will appear here" )
}
Component {
id: tokenDelegate
ManageTokensDelegate {
isCollectible: model . isCollectible
controller: isCollectible ? root.collectiblesController : root . assetsController
dragParent: null
dragEnabled: false
isHidden: true
2024-01-25 18:53:09 +00:00
getCurrencyAmount: function ( balance , symbol ) {
return root . getCurrencyAmount ( balance , symbol )
}
getCurrentCurrencyAmount: function ( balance ) {
return root . getCurrentCurrencyAmount ( balance )
}
2024-01-16 16:22:05 +00:00
}
}
Component {
id: tokenGroupDelegate
ManageTokensGroupDelegate {
isCollectible: model . isCollectible
2024-01-19 09:53:32 +00:00
isCollection: model . tokenType === "collectibleCollectionGroup"
2024-01-16 16:22:05 +00:00
controller: isCollectible ? root.collectiblesController : root . assetsController
dragParent: null
dragEnabled: false
isHidden: true
}
}
contentItem: ColumnLayout {
spacing: 2 // subtle spacing for the dashed placeholders to be fully visible
ColumnLayout { // no assets placeholder
Layout.fillWidth: true
2024-01-26 15:39:42 +00:00
Layout.fillHeight: false
2024-01-16 16:22:05 +00:00
spacing: 0
visible: ! d . assetsCount
SectionDelegate {
Layout.fillWidth: true
}
Placeholder {
Layout.fillWidth: true
visible: d . assetsExpanded
}
}
StatusListView {
2024-01-26 15:39:42 +00:00
id: listView
2024-01-16 16:22:05 +00:00
Layout.fillWidth: true
Layout.fillHeight: true
2024-01-26 15:39:42 +00:00
2024-01-16 16:22:05 +00:00
model: d . sfpm
2024-02-06 16:12:45 +00:00
// For some reason displaced transition doesn't work correctly in
// combination of delegate using Loader and leads to improper
// delegates positioning when the top-most item from the list is
// removed.
//displaced: Transition {
// NumberAnimation { properties: "x,y" }
//}
2024-01-16 16:22:05 +00:00
delegate: Loader {
required property var model
required property int index
width: ListView . view . width
height: visible ? 76 : 0
sourceComponent: model . isGroup ? tokenGroupDelegate : tokenDelegate
visible: ( ! model . isCollectible && d . assetsExpanded ) || ( model . isCollectible && d . collectiblesExpanded )
}
section.property: "isCollectible"
section.delegate: SectionDelegate {
width: ListView . view . width
isCollectible: section == "true"
}
section.labelPositioning: ViewSection . InlineLabels | ViewSection . CurrentLabelAtStart
2024-01-26 15:39:42 +00:00
footer: ColumnLayout { // no collectibles placeholder
width: ListView . view . width
spacing: 0
visible: ! d . collectiblesCount
height: visible ? implicitHeight : 0
SectionDelegate {
Layout.fillWidth: true
isCollectible: true
}
Placeholder {
Layout.fillWidth: true
isCollectible: true
visible: d . collectiblesExpanded
}
2024-01-16 16:22:05 +00:00
}
}
2024-01-26 15:39:42 +00:00
Item {
Layout.fillHeight: true
visible: listView . count === 0
}
2024-01-16 16:22:05 +00:00
}
}