chore(WalletSettings): Use DoubleFlickable for assets/collectibles tabs in manage tokens

It provides visual alignments to the current design and also
significantly improves performance because ListView components
are not "unrolled" causing instantiation of too many delegates.

Closes: #12703
Closes: #13043
This commit is contained in:
Michał Cieślak 2024-01-26 15:39:42 +00:00 committed by Michał
parent 8509dd9c67
commit 2e29e847ac
15 changed files with 639 additions and 501 deletions

View File

@ -24,13 +24,12 @@ SplitView {
assetsWithFilteredBalances: groupedAccountsAssetsModel assetsWithFilteredBalances: groupedAccountsAssetsModel
} }
StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml
SplitView.fillWidth: true
SplitView.fillHeight: true
Component.onCompleted: forceActiveFocus()
ManageAssetsPanel { ManageAssetsPanel {
id: showcasePanel id: showcasePanel
width: 500
SplitView.fillWidth: true
SplitView.fillHeight: true
getCurrencyAmount: function (balance, symbol) { getCurrencyAmount: function (balance, symbol) {
return ({ return ({
amount: balance, amount: balance,
@ -47,12 +46,12 @@ SplitView {
stripTrailingZeroes: false stripTrailingZeroes: false
}) })
} }
controller: ManageTokensController { controller: ManageTokensController {
sourceModel: ctrlEmptyModel.checked ? null : walletAssetStore.groupedAccountAssetsModel sourceModel: ctrlEmptyModel.checked ? null : walletAssetStore.groupedAccountAssetsModel
settingsKey: "WalletAssets" settingsKey: "WalletAssets"
} }
} }
}
LogsAndControlsPanel { LogsAndControlsPanel {
id: logsAndControlsPanel id: logsAndControlsPanel

View File

@ -35,19 +35,17 @@ SplitView {
] ]
} }
StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml
SplitView.fillWidth: true
SplitView.fillHeight: true
Component.onCompleted: forceActiveFocus()
ManageCollectiblesPanel { ManageCollectiblesPanel {
id: showcasePanel id: showcasePanel
width: 500
SplitView.fillWidth: true
SplitView.fillHeight: true
controller: ManageTokensController { controller: ManageTokensController {
sourceModel: renamedModel sourceModel: renamedModel
settingsKey: "WalletCollectibles" settingsKey: "WalletCollectibles"
} }
} }
}
LogsAndControlsPanel { LogsAndControlsPanel {
id: logsAndControlsPanel id: logsAndControlsPanel
@ -94,7 +92,4 @@ SplitView {
} }
// category: Panels // category: Panels
// https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?type=design&node-id=19341-250476&mode=design&t=jR53lJ7aDzVHE4hZ-0 // https://www.figma.com/file/eM26pyHZUeAwMLviaS1KJn/%E2%9A%99%EF%B8%8F-Wallet-Settings%3A-Manage-Tokens
// https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?type=design&node-id=19655-204534&mode=design&t=jR53lJ7aDzVHE4hZ-0
// https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?type=design&node-id=19622-173583&mode=design&t=jR53lJ7aDzVHE4hZ-0
// https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?type=design&node-id=19622-179146&mode=design&t=jR53lJ7aDzVHE4hZ-0

View File

@ -52,14 +52,12 @@ SplitView {
settingsKey: "WalletCollectibles" settingsKey: "WalletCollectibles"
} }
StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml
SplitView.fillWidth: true
SplitView.fillHeight: true
Component.onCompleted: forceActiveFocus()
ManageHiddenPanel { ManageHiddenPanel {
id: showcasePanel id: showcasePanel
width: 500
SplitView.fillWidth: true
SplitView.fillHeight: true
assetsController: assetsController assetsController: assetsController
collectiblesController: collectiblesController collectiblesController: collectiblesController
@ -80,7 +78,6 @@ SplitView {
}) })
} }
} }
}
LogsAndControlsPanel { LogsAndControlsPanel {
id: logsAndControlsPanel id: logsAndControlsPanel

View File

@ -12,7 +12,7 @@ import utils 1.0
Item { Item {
id: root id: root
width: 600 width: 600
height: 400 height: 2000
ManageCollectiblesModel { ManageCollectiblesModel {
id: collectiblesModel id: collectiblesModel
@ -33,6 +33,7 @@ Item {
id: componentUnderTest id: componentUnderTest
ManageCollectiblesPanel { ManageCollectiblesPanel {
width: 500 width: 500
height: contentItem.contentHeight
controller: ManageTokensController { controller: ManageTokensController {
sourceModel: renamedModel sourceModel: renamedModel
settingsKey: "WalletCollectibles" settingsKey: "WalletCollectibles"
@ -59,7 +60,7 @@ Item {
property ManageCollectiblesPanel controlUnderTest: null property ManageCollectiblesPanel controlUnderTest: null
function findDelegateIndexWithTitle(listview, title) { function findDelegateIndexWithTitle(listview, title) {
waitForItemPolished(listview) waitForRendering(listview)
const count = listview.count const count = listview.count
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const item = listview.itemAtIndex(i) const item = listview.itemAtIndex(i)
@ -74,9 +75,12 @@ Item {
verify(!!token) verify(!!token)
const delegateBtn = findChild(token, "btnManageTokenMenu-%1".arg(index)) const delegateBtn = findChild(token, "btnManageTokenMenu-%1".arg(index))
verify(!!delegateBtn) verify(!!delegateBtn)
waitForItemPolished(delegateBtn)
mouseClick(delegateBtn) mouseClick(delegateBtn)
const btnMenuLoader = findChild(delegateBtn, "manageTokensContextMenuLoader") const btnMenuLoader = findChild(delegateBtn, "manageTokensContextMenuLoader")
verify(!!btnMenuLoader) verify(!!btnMenuLoader)
tryCompare(btnMenuLoader, "active", true) tryCompare(btnMenuLoader, "active", true)
const btnMenu = btnMenuLoader.item const btnMenu = btnMenuLoader.item
verify(!!btnMenu) verify(!!btnMenu)
@ -92,105 +96,120 @@ Item {
function init() { function init() {
controlUnderTest = createTemporaryObject(componentUnderTest, root) controlUnderTest = createTemporaryObject(componentUnderTest, root)
controlUnderTest.clearSettings()
notificationSpy.clear() notificationSpy.clear()
} }
function cleanup() {
controlUnderTest.clearSettings()
}
function test_showHideSingleToken() { function test_showHideSingleToken() {
waitForItemPolished(controlUnderTest)
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
const lvRegular = findChild(controlUnderTest, "lvRegularTokens") const lvOther = findChild(controlUnderTest, "otherTokensListView")
verify(!!lvRegular) verify(!!lvOther)
const lvRegularCount = lvRegular.count
verify(lvRegularCount === 7)
const delegate0 = findChild(lvRegular, "manageTokensDelegate-0") tryCompare(lvOther, "count", 7)
const delegate0 = findChild(lvOther, "manageTokensDelegate-0")
verify(!!delegate0) verify(!!delegate0)
const title = delegate0.title const title = delegate0.title
tryCompare(notificationSpy, "count", 0) tryCompare(notificationSpy, "count", 0)
triggerDelegateMenuAction(lvRegular, 0, "miHideCollectionToken") triggerDelegateMenuAction(lvOther, 0, "miHideCollectionToken")
// verify the signal to show the notification toast got fired // verify the signal to show the notification toast got fired
tryCompare(notificationSpy, "count", 1) tryCompare(notificationSpy, "count", 1)
// verify we now have -1 regular tokens after the "hide" operation // verify we now have -1 regular tokens after the "hide" operation
tryCompare(lvRegular, "count", lvRegularCount-1) tryCompare(lvOther, "count", 6)
} }
function test_showHideCommunityGroup() { function test_showHideCommunityGroup() {
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
const loaderCommunityTokens = findChild(controlUnderTest, "loaderCommunityTokens") const communityHeader = findChild(controlUnderTest, "communityHeader")
verify(!!loaderCommunityTokens) verify(!!communityHeader)
tryCompare(loaderCommunityTokens, "active", true) const switchArrangeByCommunity = findChild(communityHeader, "switch")
const switchArrangeByCommunity = findChild(controlUnderTest, "switchArrangeByCommunity")
verify(!!switchArrangeByCommunity) verify(!!switchArrangeByCommunity)
switchArrangeByCommunity.toggle()
const lvCommunityTokenGroups = findChild(loaderCommunityTokens, "lvCommunityTokenGroups") waitForRendering(switchArrangeByCommunity)
verify(!!lvCommunityTokenGroups) mouseClick(switchArrangeByCommunity)
tryCompare(switchArrangeByCommunity, "checked", true)
tryCompare(controlUnderTest.controller, "arrangeByCommunity", true)
waitForRendering(controlUnderTest)
const lvCommunity = findChild(controlUnderTest, "communityTokensListView")
verify(!!lvCommunity)
// verify we have 2 community collectible groups // verify we have 2 community collectible groups
tryCompare(lvCommunityTokenGroups, "count", 3) tryCompare(lvCommunity, "count", 3)
tryCompare(notificationSpy, "count", 0) tryCompare(notificationSpy, "count", 0)
triggerDelegateMenuAction(lvCommunityTokenGroups, 0, "miHideTokenGroup", true) triggerDelegateMenuAction(lvCommunity, 0, "miHideTokenGroup", true)
// verify the signal to show the notification toast got fired // verify the signal to show the notification toast got fired
tryCompare(notificationSpy, "count", 1) tryCompare(notificationSpy, "count", 1)
// verify we have one less group // verify we have one less group
waitForItemPolished(lvCommunityTokenGroups) waitForItemPolished(lvCommunity)
tryCompare(lvCommunityTokenGroups, "count", 2) tryCompare(lvCommunity, "count", 2)
} }
function test_dnd() { function test_dnd() {
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
const lvRegular = findChild(controlUnderTest, "lvRegularTokens") const lvOther = findChild(controlUnderTest, "otherTokensListView")
verify(!!lvRegular) verify(!!lvOther)
verify(lvRegular.count !== 0) verify(lvOther.count !== 0)
const delegate0 = findChild(lvRegular, "manageTokensDelegate-0") const delegate0 = findChild(lvOther, "manageTokensDelegate-0")
verify(!!delegate0) verify(!!delegate0)
const title0 = delegate0.title const title0 = delegate0.title
verify(!!title0) verify(!!title0)
const title1 = findChild(lvRegular, "manageTokensDelegate-1").title const delegate1 = findChild(lvOther, "manageTokensDelegate-1")
const title1 = delegate1.title
verify(!!title1) verify(!!title1)
// DND one item down (~80px in height) waitForRendering(delegate1)
mouseDrag(delegate0, delegate0.width/2, delegate0.height/2, 0, 80)
// DND one item up
mouseDrag(delegate1, delegate1.width/2, delegate1.height/2, 0, -delegate1.height)
// cross compare the titles // cross compare the titles
tryCompare(findChild(lvRegular, "manageTokensDelegate-0"), "title", title1) tryCompare(findChild(lvOther, "manageTokensDelegate-0"), "title", title1)
tryCompare(findChild(lvRegular, "manageTokensDelegate-1"), "title", title0) tryCompare(findChild(lvOther, "manageTokensDelegate-1"), "title", title0)
verify(controlUnderTest.dirty) verify(controlUnderTest.dirty)
} }
function test_group_dnd() { function test_group_dnd() {
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
const switchArrangeByCommunity = findChild(controlUnderTest, "switchArrangeByCommunity") const communityHeader = findChild(controlUnderTest, "communityHeader")
verify(!!communityHeader)
const switchArrangeByCommunity = findChild(communityHeader, "switch")
verify(!!switchArrangeByCommunity) verify(!!switchArrangeByCommunity)
waitForItemPolished(switchArrangeByCommunity)
mouseClick(switchArrangeByCommunity) mouseClick(switchArrangeByCommunity)
const loaderCommunityTokens = findChild(controlUnderTest, "loaderCommunityTokens") const lvCommunity = findChild(controlUnderTest, "communityTokensListView")
verify(!!loaderCommunityTokens) verify(!!lvCommunity)
tryCompare(loaderCommunityTokens, "active", true) waitForItemPolished(lvCommunity)
const lvCommunityTokenGroups = findChild(loaderCommunityTokens, "lvCommunityTokenGroups") tryCompare(lvCommunity, "count", 3)
verify(!!lvCommunityTokenGroups)
waitForItemPolished(lvCommunityTokenGroups)
tryCompare(lvCommunityTokenGroups, "count", 3)
const group0 = findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-0") const group0 = findChild(lvCommunity, "manageTokensGroupDelegate-0")
const title0 = group0.title const title0 = group0.title
verify(!!title0) verify(!!title0)
const title1 = findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-1").title const group1 = findChild(lvCommunity, "manageTokensGroupDelegate-1")
const title1 = group1.title
verify(!!title1) verify(!!title1)
verify(title0 !== title1) verify(title0 !== title1)
// DND one group down (~80px in height) waitForRendering(group1)
mouseDrag(group0, group0.width/2, group0.height/2, 0, 80)
mouseDrag(group1, group1.width/2, group1.height/2, 0, -group1.height)
// cross compare the titles // cross compare the titles
tryCompare(findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-0"), "title", title1) tryCompare(findChild(lvCommunity, "manageTokensGroupDelegate-0"), "title", title1)
tryCompare(findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-1"), "title", title0) tryCompare(findChild(lvCommunity, "manageTokensGroupDelegate-1"), "title", title0)
verify(controlUnderTest.dirty) verify(controlUnderTest.dirty)
} }
@ -199,101 +218,101 @@ Item {
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
const titleToTest = "Bearz" const titleToTest = "Bearz"
const switchArrangeByCommunity = findChild(controlUnderTest, "switchArrangeByCommunity") const communityHeader = findChild(controlUnderTest, "communityHeader")
verify(!!communityHeader)
const switchArrangeByCommunity = findChild(communityHeader, "switch")
verify(!!switchArrangeByCommunity) verify(!!switchArrangeByCommunity)
waitForRendering(switchArrangeByCommunity)
mouseClick(switchArrangeByCommunity) mouseClick(switchArrangeByCommunity)
const loaderCommunityTokens = findChild(controlUnderTest, "loaderCommunityTokens") const lvCommunity = findChild(controlUnderTest, "communityTokensListView")
verify(!!loaderCommunityTokens) verify(!!lvCommunity)
tryCompare(loaderCommunityTokens, "active", true) waitForItemPolished(lvCommunity)
const lvCommunityTokenGroups = findChild(loaderCommunityTokens, "lvCommunityTokenGroups") tryCompare(lvCommunity, "count", 3)
verify(!!lvCommunityTokenGroups)
waitForItemPolished(lvCommunityTokenGroups)
tryCompare(lvCommunityTokenGroups, "count", 3)
// get the "Bearz" group at index 1 // get the "Bearz" group at index 1
var bearzGroupTokenDelegate = findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-1") var bearzGroupTokenDelegate = findChild(lvCommunity, "manageTokensGroupDelegate-1")
const bearzTitle = bearzGroupTokenDelegate.title const bearzTitle = bearzGroupTokenDelegate.title
compare(bearzTitle, titleToTest) compare(bearzTitle, titleToTest)
verify(!!bearzGroupTokenDelegate) verify(!!bearzGroupTokenDelegate)
waitForItemPolished(bearzGroupTokenDelegate) waitForItemPolished(bearzGroupTokenDelegate)
// now move the Bearz group up so that it's first (ends up at index 0) // now move the Bearz group up so that it's first (ends up at index 0)
waitForItemPolished(lvCommunityTokenGroups) waitForItemPolished(lvCommunity)
triggerDelegateMenuAction(lvCommunityTokenGroups, 1, "miMoveUp", true) triggerDelegateMenuAction(lvCommunity, 1, "miMoveUp", true)
verify(controlUnderTest.dirty) verify(controlUnderTest.dirty)
bearzGroupTokenDelegate = findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-0") bearzGroupTokenDelegate = findChild(lvCommunity, "manageTokensGroupDelegate-0")
verify(!!bearzGroupTokenDelegate) verify(!!bearzGroupTokenDelegate)
// finally verify that the Bearz group is still at top // finally verify that the Bearz group is still at top
waitForItemPolished(lvCommunityTokenGroups) waitForItemPolished(lvCommunity)
tryCompare(findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-0"), "title", titleToTest) tryCompare(findChild(lvCommunity, "manageTokensGroupDelegate-0"), "title", titleToTest)
} }
function test_moveOperations() { function test_moveOperations() {
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
const lvRegular = findChild(controlUnderTest, "lvRegularTokens") const lvOther = findChild(controlUnderTest, "otherTokensListView")
verify(!!lvRegular) verify(!!lvOther)
verify(lvRegular.count !== 0) verify(lvOther.count !== 0)
var delegate0 = findChild(lvRegular, "manageTokensDelegate-0") var delegate0 = findChild(lvOther, "manageTokensDelegate-0")
verify(!!delegate0) verify(!!delegate0)
const title = delegate0.title const title = delegate0.title
// verify moveUp and moveToTop is not available for the first item // verify moveUp and moveToTop is not available for the first item
const moveUpAction = findDelegateMenuAction(lvRegular, 0, "miMoveUp") const moveUpAction = findDelegateMenuAction(lvOther, 0, "miMoveUp")
tryCompare(moveUpAction, "enabled", false) tryCompare(moveUpAction, "enabled", false)
const moveTopAction = findDelegateMenuAction(lvRegular, 0, "miMoveToTop") const moveTopAction = findDelegateMenuAction(lvOther, 0, "miMoveToTop")
tryCompare(moveTopAction, "enabled", false) tryCompare(moveTopAction, "enabled", false)
// trigger move to bottom // trigger move to bottom
triggerDelegateMenuAction(lvRegular, 0, "miMoveToBottom") waitForItemPolished(lvOther)
waitForItemPolished(lvRegular) triggerDelegateMenuAction(lvOther, 0, "miMoveToBottom")
verify(controlUnderTest.dirty) verify(controlUnderTest.dirty)
// verify the previous first and current last are actually the same item // verify the previous first and current last are actually the same item
const delegateN = findChild(lvRegular, "manageTokensDelegate-%1".arg(lvRegular.count-1)) const delegateN = findChild(lvOther, "manageTokensDelegate-%1".arg(lvOther.count-1))
verify(!!delegateN) verify(!!delegateN)
const titleN = delegateN.title const titleN = delegateN.title
compare(title, titleN) compare(title, titleN)
// verify move down and to bottom is not available for the last item // verify move down and to bottom is not available for the last item
const moveDownAction = findDelegateMenuAction(lvRegular, lvRegular.count-1, "miMoveDown") const moveDownAction = findDelegateMenuAction(lvOther, lvOther.count-1, "miMoveDown")
tryCompare(moveDownAction, "enabled", false) tryCompare(moveDownAction, "enabled", false)
const moveBottomAction = findDelegateMenuAction(lvRegular, lvRegular.count-1, "miMoveToBottom") const moveBottomAction = findDelegateMenuAction(lvOther, lvOther.count-1, "miMoveToBottom")
tryCompare(moveBottomAction, "enabled", false) tryCompare(moveBottomAction, "enabled", false)
// trigger move to top and verify we got the same title (item) again // trigger move to top and verify we got the same title (item) again
triggerDelegateMenuAction(lvRegular, lvRegular.count-1, "miMoveToTop") triggerDelegateMenuAction(lvOther, lvOther.count-1, "miMoveToTop")
waitForItemPolished(lvRegular) waitForItemPolished(lvOther)
tryCompare(findChild(lvRegular, "manageTokensDelegate-0"), "title", title) tryCompare(findChild(lvOther, "manageTokensDelegate-0"), "title", title)
// trigger move down and verify we got the same title (item) again // trigger move down and verify we got the same title (item) again
triggerDelegateMenuAction(lvRegular, 0, "miMoveDown") triggerDelegateMenuAction(lvOther, 0, "miMoveDown")
tryCompare(findChild(lvRegular, "manageTokensDelegate-1"), "title", title) tryCompare(findChild(lvOther, "manageTokensDelegate-1"), "title", title)
// trigger move up and verify we got the same title (item) again // trigger move up and verify we got the same title (item) again
triggerDelegateMenuAction(lvRegular, 1, "miMoveUp") triggerDelegateMenuAction(lvOther, 1, "miMoveUp")
tryCompare(findChild(lvRegular, "manageTokensDelegate-0"), "title", title) tryCompare(findChild(lvOther, "manageTokensDelegate-0"), "title", title)
} }
function test_saveLoad() { function test_saveLoad() {
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
const titleToTest = "Big Kitty" const titleToTest = "Big Kitty"
let lvRegular = findChild(controlUnderTest, "lvRegularTokens") let lvOther = findChild(controlUnderTest, "otherTokensListView")
verify(!!lvRegular) verify(!!lvOther)
const bigKittyIndex = findDelegateIndexWithTitle(lvRegular, titleToTest) const bigKittyIndex = findDelegateIndexWithTitle(lvOther, titleToTest)
verify(bigKittyIndex !== -1) verify(bigKittyIndex !== -1)
const title0 = findChild(lvRegular, "manageTokensDelegate-0").title const title0 = findChild(lvOther, "manageTokensDelegate-0").title
verify(!!title0) verify(!!title0)
verify(title0 !== titleToTest) verify(title0 !== titleToTest)
// trigger move to top and verify we got the correct title // trigger move to top and verify we got the correct title
triggerDelegateMenuAction(lvRegular, bigKittyIndex, "miMoveToTop") triggerDelegateMenuAction(lvOther, bigKittyIndex, "miMoveToTop")
waitForItemPolished(lvRegular) waitForItemPolished(lvOther)
tryCompare(findChild(lvRegular, "manageTokensDelegate-0"), "title", titleToTest) tryCompare(findChild(lvOther, "manageTokensDelegate-0"), "title", titleToTest)
// save // save
verify(controlUnderTest.dirty) verify(controlUnderTest.dirty)
@ -303,11 +322,11 @@ Item {
// load the settings and check BigKitty is still on top // load the settings and check BigKitty is still on top
controlUnderTest.revert() controlUnderTest.revert()
verify(!controlUnderTest.dirty) verify(!controlUnderTest.dirty)
lvRegular = findChild(controlUnderTest, "lvRegularTokens") lvOther = findChild(controlUnderTest, "otherTokensListView")
verify(!!lvRegular) verify(!!lvOther)
waitForItemPolished(lvRegular) waitForItemPolished(lvOther)
tryVerify(() => lvRegular.count > 0) tryVerify(() => lvOther.count > 0)
const topItem = findChild(lvRegular, "manageTokensDelegate-0") const topItem = findChild(lvOther, "manageTokensDelegate-0")
verify(!!topItem) verify(!!topItem)
tryCompare(topItem, "title", titleToTest) tryCompare(topItem, "title", titleToTest)
} }

View File

@ -23,9 +23,9 @@ Switch {
implicitWidth: 52 implicitWidth: 52
implicitHeight: 28 implicitHeight: 28
anchors.left: parent.left anchors.left: root.left
anchors.leftMargin: root.leftPadding anchors.leftMargin: root.leftPadding
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: root.verticalCenter
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
@ -45,8 +45,8 @@ Switch {
color: Theme.palette.white color: Theme.palette.white
layer.enabled: true layer.enabled: true
layer.effect: DropShadow { layer.effect: DropShadow {
width: parent.width width: circle.width
height: parent.height height: circle.height
visible: true visible: true
verticalOffset: 1 verticalOffset: 1
fast: true fast: true

View File

@ -28,6 +28,10 @@ FocusScope {
property bool saveChangesButtonEnabled: false property bool saveChangesButtonEnabled: false
readonly property alias toast: settingsDirtyToastMessage readonly property alias toast: settingsDirtyToastMessage
readonly property real availableHeight:
scrollView.availableHeight - settingsDirtyToastMessagePlaceholder.height
- Style.current.bigPadding
signal baseAreaClicked() signal baseAreaClicked()
signal saveChangesClicked() signal saveChangesClicked()
signal saveForLaterClicked() signal saveForLaterClicked()
@ -118,7 +122,8 @@ FocusScope {
} }
Item { Item {
// This is a settingsDirtyToastMessage placeholder id: settingsDirtyToastMessagePlaceholder
width: settingsDirtyToastMessage.implicitWidth width: settingsDirtyToastMessage.implicitWidth
height: settingsDirtyToastMessage.active && !root.ignoreDirty ? settingsDirtyToastMessage.implicitHeight : 0 height: settingsDirtyToastMessage.active && !root.ignoreDirty ? settingsDirtyToastMessage.implicitHeight : 0

View File

@ -305,6 +305,10 @@ SettingsContentBase {
ManageTokensView { ManageTokensView {
id: manageTokensView id: manageTokensView
implicitHeight: root.availableHeight
Layout.fillWidth: true
sourcesOfTokensModel: tokensStore.sourcesOfTokensModel sourcesOfTokensModel: tokensStore.sourcesOfTokensModel
tokensListModel: tokensStore.extendedFlatTokensModel tokensListModel: tokensStore.extendedFlatTokensModel
baseWalletAssetsModel: RootStore.walletAssetsStore.groupedAccountAssetsModel baseWalletAssetsModel: RootStore.walletAssetsStore.groupedAccountAssetsModel

View File

@ -17,7 +17,7 @@ import utils 1.0
import AppLayouts.Profile.panels 1.0 import AppLayouts.Profile.panels 1.0
import AppLayouts.Wallet.panels 1.0 import AppLayouts.Wallet.panels 1.0
ColumnLayout { Item {
id: root id: root
required property var sourcesOfTokensModel // Expected roles: key, name, updatedAt, source, version, tokensCount, image required property var sourcesOfTokensModel // Expected roles: key, name, updatedAt, source, version, tokensCount, image
@ -121,6 +121,9 @@ ColumnLayout {
} }
} }
ColumnLayout {
anchors.fill: parent
StatusTabBar { StatusTabBar {
id: tabBar id: tabBar
@ -176,6 +179,7 @@ ColumnLayout {
getCurrentCurrencyAmount: function (balance) { getCurrentCurrencyAmount: function (balance) {
return root.getCurrentCurrencyAmount(balance) return root.getCurrentCurrencyAmount(balance)
} }
controller: d.assetsController controller: d.assetsController
} }
} }
@ -275,4 +279,5 @@ ColumnLayout {
} }
} }
} }
}
} }

View File

@ -47,13 +47,14 @@ DropArea {
keys: isCommunityToken ? ["x-status-draggable-community-token-item"] : ["x-status-draggable-regular-token-item"] keys: isCommunityToken ? ["x-status-draggable-community-token-item"] : ["x-status-draggable-regular-token-item"]
width: ListView.view ? ListView.view.width : 0 width: ListView.view ? ListView.view.width : 0
height: visible ? delegate.height : 0 height: delegate.height
onEntered: function(drag) { onEntered: function(drag) {
const from = drag.source.visualIndex const from = drag.source.visualIndex
const to = delegate.visualIndex const to = delegate.visualIndex
if (to === from) if (to === from)
return return
ListView.view.model.moveItem(from, to) ListView.view.model.moveItem(from, to)
drag.accept() drag.accept()
} }

View File

@ -35,7 +35,7 @@ DropArea {
keys: isCollection ? ["x-status-draggable-collection-group-item"] : ["x-status-draggable-community-group-item"] keys: isCollection ? ["x-status-draggable-collection-group-item"] : ["x-status-draggable-community-group-item"]
width: ListView.view ? ListView.view.width : 0 width: ListView.view ? ListView.view.width : 0
height: visible ? groupedCommunityTokenDelegate.implicitHeight : 0 height: groupedCommunityTokenDelegate.implicitHeight
onEntered: function(drag) { onEntered: function(drag) {
const from = drag.source.visualIndex const from = drag.source.visualIndex

View File

@ -1,17 +1,22 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import QtQml.Models 2.15
import QtQml 2.15
import StatusQ.Core 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Models 0.1 import StatusQ.Models 0.1
import utils 1.0 import shared.controls 1.0
import AppLayouts.Wallet.controls 1.0 import AppLayouts.Wallet.controls 1.0
import "internals"
Control { Control {
id: root id: root
@ -37,18 +42,35 @@ Control {
root.controller.clearSettings(); root.controller.clearSettings();
} }
QtObject {
id: d
contentItem: ColumnLayout { readonly property int sectionHeight: 64
spacing: Style.current.padding }
StatusListView { contentItem: DoubleFlickableWithFolding {
Layout.fillWidth: true id: doubleFlickable
clip: true
ScrollBar.vertical: StatusScrollBar {
policy: ScrollBar.AsNeeded
visible: resolveVisibility(policy, doubleFlickable.height,
doubleFlickable.contentHeight)
}
flickable1: ManageTokensListViewBase {
model: root.controller.regularTokensModel model: root.controller.regularTokensModel
implicitHeight: contentHeight width: doubleFlickable.width
interactive: false
displaced: Transition { ScrollBar.vertical: null
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }
header: FoldableHeader {
width: ListView.view.width
title: qsTr("Assets")
folded: doubleFlickable.flickable1Folded
onToggleFolding: doubleFlickable.flip1Folding()
} }
delegate: ManageTokensDelegate { delegate: ManageTokensDelegate {
@ -63,45 +85,38 @@ Control {
return root.getCurrentCurrencyAmount(balance) return root.getCurrentCurrencyAmount(balance)
} }
} }
placeholderText: qsTr("Your assets will appear here")
} }
RowLayout { flickable2: ManageTokensListViewBase {
Layout.fillWidth: true width: doubleFlickable.width
Layout.topMargin: Style.current.padding
visible: root.controller.communityTokensModel.count model: root.controller.arrangeByCommunity ? communityGroupedModel
StatusBaseText { : communityNonGroupedModel
Layout.fillWidth: true
text: qsTr("Community") header: FoldableHeader {
} width: ListView.view.width
StatusSwitch { title: qsTr("Community minted")
LayoutMirroring.enabled: true switchText: qsTr("Arrange by community")
LayoutMirroring.childrenInherit: true folded: doubleFlickable.flickable2Folded
id: switchArrangeByCommunity
textColor: Theme.palette.baseColor1
font.pixelSize: 13
text: qsTr("Arrange by community")
checked: root.controller.arrangeByCommunity checked: root.controller.arrangeByCommunity
onToggled: root.controller.arrangeByCommunity = checked
onToggleFolding: doubleFlickable.flip2Folding()
onToggleSwitch: root.controller.arrangeByCommunity = checked
}
placeholderText: qsTr("Your community minted assets will appear here")
} }
} }
Loader { DelegateModel {
Layout.fillWidth: true id: communityNonGroupedModel
active: root.controller.communityTokensModel.count
visible: active
sourceComponent: switchArrangeByCommunity.checked ? cmpCommunityTokenGroups : cmpCommunityTokens
}
}
Component {
id: cmpCommunityTokens
StatusListView {
model: root.controller.communityTokensModel model: root.controller.communityTokensModel
implicitHeight: contentHeight
interactive: false
displaced: Transition { function moveItem(from, to) {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } model.moveItem(from, to)
} }
delegate: ManageTokensDelegate { delegate: ManageTokensDelegate {
@ -117,24 +132,22 @@ Control {
} }
} }
} }
}
Component { DelegateModel {
id: cmpCommunityTokenGroups id: communityGroupedModel
StatusListView {
model: root.controller.communityTokenGroupsModel model: root.controller.communityTokenGroupsModel
implicitHeight: contentHeight
interactive: false
displaced: Transition { function moveItem(from, to) {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } model.moveItem(from, to)
} }
delegate: ManageTokensGroupDelegate { delegate: ManageTokensGroupDelegate {
height: 76
controller: root.controller controller: root.controller
dragParent: root dragParent: root
dragEnabled: root.controller.communityTokenGroupsModel.count > 1 dragEnabled: root.controller.communityTokenGroupsModel.count > 1
} }
} }
}
} }

View File

@ -1,19 +1,16 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import QtQml.Models 2.15
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Models 0.1 import StatusQ.Core.Utils 0.1
import utils 1.0
import shared.controls 1.0
import AppLayouts.Wallet.controls 1.0 import AppLayouts.Wallet.controls 1.0
import "internals"
Control { Control {
id: root id: root
@ -36,84 +33,73 @@ Control {
root.controller.clearSettings(); root.controller.clearSettings();
} }
contentItem: ColumnLayout { contentItem: DoubleFlickableWithFolding {
spacing: Style.current.padding id: doubleFlickable
ShapeRectangle { clip: true
Layout.fillWidth: true
Layout.margins: 2 ScrollBar.vertical: StatusScrollBar {
visible: !root.controller.regularTokensModel.count && !root.controller.communityTokensModel.count policy: ScrollBar.AsNeeded
text: qsTr("Youll be able to manage the display of your collectibles here") visible: resolveVisibility(policy, doubleFlickable.height,
doubleFlickable.contentHeight)
} }
RowLayout { flickable1: ManageTokensListViewBase {
Layout.fillWidth: true objectName: "communityTokensListView"
Layout.topMargin: Style.current.padding
visible: root.controller.communityTokensModel.count width: doubleFlickable.width
StatusBaseText {
Layout.fillWidth: true model: root.controller.arrangeByCommunity
text: qsTr("Community minted") ? communityGroupedModel : communityNonGroupedModel
}
StatusSwitch { header: FoldableHeader {
objectName: "switchArrangeByCommunity" objectName: "communityHeader"
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true width: ListView.view.width
id: switchArrangeByCommunity title: qsTr("Community minted")
textColor: Theme.palette.baseColor1 switchText: qsTr("Arrange by community")
font.pixelSize: 13 folded: doubleFlickable.flickable1Folded
text: qsTr("Arrange by community")
checked: root.controller.arrangeByCommunity checked: root.controller.arrangeByCommunity
onToggled: root.controller.arrangeByCommunity = checked
} onToggleFolding: doubleFlickable.flip1Folding()
onToggleSwitch: root.controller.arrangeByCommunity = checked
} }
Loader { placeholderText: qsTr("Your community minted collectibles will appear here")
objectName: "loaderCommunityTokens"
Layout.fillWidth: true
active: root.controller.communityTokensModel.count
visible: active
sourceComponent: switchArrangeByCommunity.checked ? cmpCommunityTokenGroups : cmpCommunityTokens
} }
RowLayout { flickable2: ManageTokensListViewBase {
Layout.fillWidth: true objectName: "otherTokensListView"
Layout.topMargin: Style.current.padding
visible: root.controller.regularTokensModel.count width: doubleFlickable.width
StatusBaseText {
Layout.fillWidth: true model: root.controller.arrangeByCollection
text: qsTr("Other") ? otherGroupedModel : otherNonGroupedModel
}
StatusSwitch { header: FoldableHeader {
LayoutMirroring.enabled: true objectName: "nonCommunityHeader"
LayoutMirroring.childrenInherit: true
id: switchArrangeByCollection width: ListView.view.width
textColor: Theme.palette.baseColor1 title: qsTr("Other")
font.pixelSize: 13 switchText: qsTr("Arrange by collection")
text: qsTr("Arrange by collection") folded: doubleFlickable.flickable2Folded
checked: root.controller.arrangeByCollection checked: root.controller.arrangeByCollection
onToggled: root.controller.arrangeByCollection = checked
onToggleFolding: doubleFlickable.flip2Folding()
onToggleSwitch: root.controller.arrangeByCollection = checked
}
placeholderText: qsTr("Your other collectibles will appear here")
} }
} }
Loader { DelegateModel {
objectName: "loaderRegularTokens" id: communityNonGroupedModel
Layout.fillWidth: true
active: root.controller.regularTokensModel.count
visible: active
sourceComponent: switchArrangeByCollection.checked ? cmpCollectionTokenGroups : cmpRegularTokens
}
}
Component {
id: cmpCommunityTokens
StatusListView {
objectName: "lvCommunityTokens"
model: root.controller.communityTokensModel model: root.controller.communityTokensModel
implicitHeight: contentHeight
interactive: false
displaced: Transition { function moveItem(from, to) {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } model.moveItem(from, to)
} }
delegate: ManageTokensDelegate { delegate: ManageTokensDelegate {
@ -124,18 +110,14 @@ Control {
dragEnabled: count > 1 dragEnabled: count > 1
} }
} }
}
Component { DelegateModel {
id: cmpCommunityTokenGroups id: communityGroupedModel
StatusListView {
objectName: "lvCommunityTokenGroups"
model: root.controller.communityTokenGroupsModel model: root.controller.communityTokenGroupsModel
implicitHeight: contentHeight
interactive: false
displaced: Transition { function moveItem(from, to) {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } model.moveItem(from, to)
} }
delegate: ManageTokensGroupDelegate { delegate: ManageTokensGroupDelegate {
@ -145,18 +127,14 @@ Control {
dragEnabled: root.controller.communityTokenGroupsModel.count > 1 dragEnabled: root.controller.communityTokenGroupsModel.count > 1
} }
} }
}
Component { DelegateModel {
id: cmpRegularTokens id: otherNonGroupedModel
StatusListView {
objectName: "lvRegularTokens"
model: root.controller.regularTokensModel model: root.controller.regularTokensModel
implicitHeight: contentHeight
interactive: false
displaced: Transition { function moveItem(from, to) {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } model.moveItem(from, to)
} }
delegate: ManageTokensDelegate { delegate: ManageTokensDelegate {
@ -167,18 +145,14 @@ Control {
dragEnabled: count > 1 dragEnabled: count > 1
} }
} }
}
Component { DelegateModel {
id: cmpCollectionTokenGroups id: otherGroupedModel
StatusListView {
objectName: "lvCollectionTokenGroups"
model: root.controller.collectionGroupsModel model: root.controller.collectionGroupsModel
implicitHeight: contentHeight
interactive: false
displaced: Transition { function moveItem(from, to) {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } model.moveItem(from, to)
} }
delegate: ManageTokensGroupDelegate { delegate: ManageTokensGroupDelegate {
@ -188,5 +162,4 @@ Control {
dragEnabled: root.controller.collectionGroupsModel.count > 1 dragEnabled: root.controller.collectionGroupsModel.count > 1
} }
} }
}
} }

View File

@ -184,6 +184,8 @@ Control {
ColumnLayout { // no assets placeholder ColumnLayout { // no assets placeholder
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: false
spacing: 0 spacing: 0
visible: !d.assetsCount visible: !d.assetsCount
SectionDelegate { SectionDelegate {
@ -196,9 +198,11 @@ Control {
} }
StatusListView { StatusListView {
id: listView
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: contentHeight
Layout.fillHeight: true Layout.fillHeight: true
model: d.sfpm model: d.sfpm
displaced: Transition { displaced: Transition {
@ -221,12 +225,14 @@ Control {
isCollectible: section == "true" isCollectible: section == "true"
} }
section.labelPositioning: ViewSection.InlineLabels | ViewSection.CurrentLabelAtStart section.labelPositioning: ViewSection.InlineLabels | ViewSection.CurrentLabelAtStart
}
ColumnLayout { // no collectibles placeholder footer: ColumnLayout { // no collectibles placeholder
Layout.fillWidth: true width: ListView.view.width
spacing: 0 spacing: 0
visible: !d.collectiblesCount visible: !d.collectiblesCount
height: visible ? implicitHeight : 0
SectionDelegate { SectionDelegate {
Layout.fillWidth: true Layout.fillWidth: true
isCollectible: true isCollectible: true
@ -238,4 +244,10 @@ Control {
} }
} }
} }
Item {
Layout.fillHeight: true
visible: listView.count === 0
}
}
} }

View File

@ -0,0 +1,64 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
Rectangle {
id: root
property bool folded: false
property alias title: label.text
property alias switchText: modeSwitch.text
property alias checked: modeSwitch.checked
signal toggleFolding
signal toggleSwitch
height: headerContent.height
z: 1
color: Theme.palette.statusListItem.backgroundColor
QtObject {
id: d
readonly property int sectionHeight: 64
}
RowLayout {
id: headerContent
width: parent.width
height: d.sectionHeight
StatusFlatButton {
checkable: true
size: StatusBaseButton.Size.Small
icon.name: checked ? "chevron-down" : "next"
textColor: Theme.palette.baseColor1
textHoverColor: Theme.palette.directColor1
checked: !root.folded
onToggled: root.toggleFolding()
}
StatusBaseText {
id: label
Layout.fillWidth: true
}
StatusSwitch {
id: modeSwitch
objectName: "switch"
visible: !!text
LayoutMirroring.enabled: true
LayoutMirroring.childrenInherit: true
textColor: Theme.palette.baseColor1
font.pixelSize: 13
onToggled: root.toggleSwitch()
}
}
}

View File

@ -0,0 +1,51 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQml 2.15
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import QtQuick.Controls 2.15
import StatusQ.Core.Theme 0.1
import shared.controls 1.0
StatusListView {
id: root
property string placeholderText
ScrollBar.vertical: null
QtObject {
id: d
readonly property int placeholderHeight: 44
}
Binding {
when: root.model && root.count === 0
target: root
property: "footer"
restoreMode: Binding.RestoreBindingOrValue
value: Component {
Item {
height: d.placeholderHeight
width: root.width
ShapeRectangle {
id: shapeRectangle
text: root.placeholderText
anchors.fill: parent
anchors.margins: 1
}
}
}
}
displaced: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }
}
}