diff --git a/storybook/pages/ProfileShowcaseAccountsPanelPage.qml b/storybook/pages/ProfileShowcaseAccountsPanelPage.qml index a6170f2b99..6b62c3340e 100644 --- a/storybook/pages/ProfileShowcaseAccountsPanelPage.qml +++ b/storybook/pages/ProfileShowcaseAccountsPanelPage.qml @@ -5,7 +5,6 @@ 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 shared.stores 1.0 @@ -21,91 +20,76 @@ SplitView { orientation: Qt.Vertical - Popups { - popupParent: root - rootStore: QtObject {} - communityTokensStore: CommunityTokensStore {} + readonly property string currentWallet: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7420" + + ListModel { + id: hiddenModelItem + ListElement { + name: "My Status Account" + key: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7420" + colorId: "primary" + emoji: "πŸ‡¨πŸ‡Ώ" + walletType: "" + visibility: 0 + } + ListElement { + name: "testing (no emoji, colored, seed)" + key: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7000" + colorId: "" + emoji: "" + walletType: "seed" + visibility: 0 + } + ListElement { + name: "My Bro's Account" + key: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7421" + colorId: "orange" + emoji: "πŸ‡ΈπŸ‡°" + walletType: "watch" + visibility: 0 + } } - readonly property string currentWallet: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7420" + ListModel { + id: inShowcaseModelItem + + ListElement { + name: "My Status Account" + key: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7420" + colorId: "primary" + emoji: "πŸ‡¨πŸ‡Ώ" + walletType: "" + visibility: 1 + } + ListElement { + name: "testing (no emoji, colored, seed)" + key: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7000" + colorId: "" + emoji: "" + walletType: "seed" + visibility: 1 + } + ListElement { + name: "My Bro's Account" + key: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7421" + colorId: "orange" + emoji: "πŸ‡ΈπŸ‡°" + walletType: "watch" + visibility: 1 + } + } ListModel { id: emptyModel } - ListModel { - id: accountsModel - - ListElement { - name: "My Status Account" - address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7420" - colorId: "primary" - emoji: "πŸ‡¨πŸ‡Ώ" - walletType: "" - } - ListElement { - name: "testing (no emoji, colored, seed)" - address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7000" - colorId: "" - emoji: "" - walletType: "seed" - } - ListElement { - name: "My Bro's Account" - address: "0xcdc2ea3b6ba8fed3a3402f8db8b2fab53e7b7421" - colorId: "orange" - emoji: "πŸ‡ΈπŸ‡°" - walletType: "watch" - } - } - - ListModel { - id: inShowcaseAccountsModel - - property int hiddenCount: emptyModelChecker.checked ? 0 : accountsModel.count - count - - signal baseModelFilterConditionsMayHaveChanged() - - function setVisibilityByIndex(index, visibility) { - if (visibility === Constants.ShowcaseVisibility.NoOne) { - remove(index) - } else { - get(index).showcaseVisibility = visibility - } - } - - function setVisibility(address, visibility) { - for (let i = 0; i < count; ++i) { - if (get(i).address === address) { - setVisibilityByIndex(i, visibility) - } - } - } - - function hasItemInShowcase(address) { - for (let i = 0; i < count; ++i) { - if (get(i).address === address) { - return true - } - } - return false - } - - function upsertItemJson(item) { - append(JSON.parse(item)) - } - } - - StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml + ProfileShowcaseAccountsPanel { + id: showcasePanel SplitView.fillWidth: true SplitView.preferredHeight: 500 - ProfileShowcaseAccountsPanel { - id: showcasePanel - width: 500 - baseModel: emptyModelChecker.checked ? emptyModel : accountsModel - showcaseModel: inShowcaseAccountsModel - currentWallet: root.currentWallet - } + inShowcaseModel: emptyModelChecker.checked ? emptyModel : inShowcaseModelItem + hiddenModel: emptyModelChecker.checked ? emptyModel : hiddenModelItem + currentWallet: root.currentWallet } LogsAndControlsPanel { @@ -117,9 +101,8 @@ SplitView { logsView.logText: logs.logText ColumnLayout { - Button { - text: "Reset (clear settings)" - onClicked: showcasePanel.reset() + Label { + text: "β“˜ Shwcase interaction implemented in ProfileShowcasePanelPage" } CheckBox { @@ -127,8 +110,6 @@ SplitView { text: "Empty model" checked: false - - onClicked: showcasePanel.reset() } } } diff --git a/storybook/pages/ProfileShowcaseAssetsPanelPage.qml b/storybook/pages/ProfileShowcaseAssetsPanelPage.qml index c4be7ef0c7..ff20b68907 100644 --- a/storybook/pages/ProfileShowcaseAssetsPanelPage.qml +++ b/storybook/pages/ProfileShowcaseAssetsPanelPage.qml @@ -2,9 +2,12 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 import QtQuick.Layouts 1.15 +import StatusQ 0.1 import StatusQ.Core 0.1 import StatusQ.Core.Utils 0.1 as CoreUtils +import SortFilterProxyModel 0.2 + import mainui 1.0 import AppLayouts.Profile.panels 1.0 import shared.stores 1.0 @@ -23,77 +26,58 @@ SplitView { orientation: Qt.Vertical - Popups { - popupParent: root - rootStore: QtObject {} - communityTokensStore: CommunityTokensStore {} - } - readonly property WalletAssetsStore walletAssetStore: WalletAssetsStore { assetsWithFilteredBalances: walletAssetStore.groupedAccountsAssetsModel } - ListModel { - id: emptyModel + SortFilterProxyModel { + id: inShowcaseModelItem + sourceModel: !emptyModelChecker.checked ? walletAssetStore.groupedAccountAssetsModel : null + proxyRoles: [ + FastExpressionRole { + name: "key" + expression: "Asset 1" + index + }, + FastExpressionRole { + name: "visibility" + expression: 1 + } + ] } - ListModel { - id: inShowcaseAssetsModel - - property int hiddenCount: emptyModelChecker.checked ? 0 : walletAssetStore.groupedAccountsAssetsModel.count - count - - signal baseModelFilterConditionsMayHaveChanged() - - function setVisibilityByIndex(index, visibility) { - if (visibility === Constants.ShowcaseVisibility.NoOne) { - remove(index) - } else { - get(index).showcaseVisibility = visibility + SortFilterProxyModel { + id: hiddenShowcaseModelItem + sourceModel: !emptyModelChecker.checked ? walletAssetStore.groupedAccountAssetsModel : null + proxyRoles: [ + FastExpressionRole { + name: "key" + expression: "Asset 2" + index + }, + FastExpressionRole { + name: "visibility" + expression: 0 } - } - - function setVisibility(symbol, visibility) { - for (let i = 0; i < count; ++i) { - if (get(i).symbol === symbol) { - setVisibilityByIndex(i, visibility) - } - } - } - - function hasItemInShowcase(symbol) { - for (let i = 0; i < count; ++i) { - if (get(i).symbol === symbol) { - return true - } - } - return false - } - - function upsertItemJson(item) { - append(JSON.parse(item)) - } + ] } - StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml + ProfileShowcaseAssetsPanel { + id: showcasePanel SplitView.fillWidth: true SplitView.preferredHeight: 500 + inShowcaseModel: inShowcaseModelItem + hiddenModel: hiddenShowcaseModelItem - ProfileShowcaseAssetsPanel { - id: showcasePanel - width: 500 - baseModel: emptyModelChecker.checked ? emptyModel : walletAssetStore.groupedAccountAssetsModel - showcaseModel: inShowcaseAssetsModel - addAccountsButtonVisible: !hasAllAccountsChecker.checked + addAccountsButtonVisible: !hasAllAccountsChecker.checked - formatCurrencyAmount: function (amount, symbol) { - return ({amount: amount, - symbol: symbol.toUpperCase(), - displayDecimals: 4, - stripTrailingZeroes: false}) - } - - onNavigateToAccountsTab: logs.logEvent("ProfileShowcaseAssetsPanel::onNavigateToAccountsTab") + formatCurrencyAmount: function (amount, symbol) { + const currencyAmount = ({amount: amount, + symbol: symbol.toUpperCase(), + displayDecimals: 4, + stripTrailingZeroes: false}) + return LocaleUtils.currencyAmountToLocaleString(currencyAmount) } + + onNavigateToAccountsTab: logs.logEvent("ProfileShowcaseAssetsPanel::onNavigateToAccountsTab") } LogsAndControlsPanel { @@ -123,8 +107,6 @@ SplitView { text: "Empty model" checked: false - - onClicked: showcasePanel.reset() } } } diff --git a/storybook/pages/ProfileShowcaseCollectiblesPanelPage.qml b/storybook/pages/ProfileShowcaseCollectiblesPanelPage.qml index 82a578c9cd..a9d92c2269 100644 --- a/storybook/pages/ProfileShowcaseCollectiblesPanelPage.qml +++ b/storybook/pages/ProfileShowcaseCollectiblesPanelPage.qml @@ -23,71 +23,132 @@ SplitView { orientation: Qt.Vertical - Popups { - popupParent: root - rootStore: QtObject {} - communityTokensStore: CommunityTokensStore {} - } - ListModel { - id: emptyModel - } - - ListModel { - id: collectiblesModel - + id: hiddenModelItem readonly property var data: [ { - uid: "123", - name: "SNT", + key: "1234", + name: "SNTT", collectionName: "Super Nitro Toluen (with pink bg)", backgroundColor: "pink", imageUrl: ModelsData.collectibles.custom, isLoading: false, - communityId: "ddls" + communityId: "ddls", + visibility: Constants.ShowcaseVisibility.NoOne }, { - uid: "34545656768", - name: "Kitty 1", + key: "3454565676", + name: "Kitty 3", collectionName: "Kitties", backgroundColor: "", imageUrl: ModelsData.collectibles.kitty1Big, - isLoading: false + isLoading: false, + visibility: Constants.ShowcaseVisibility.NoOne }, { - uid: "123456", - name: "Kitty 2", + key: "12345", + name: "Kitty 4", collectionName: "", backgroundColor: "", imageUrl: ModelsData.collectibles.kitty2Big, isLoading: false, - communityId: "sox" + communityId: "sox", + visibility: Constants.ShowcaseVisibility.NoOne }, { - uid: "12345645459537432", + key: "123456454595374", name: "", collectionName: "Super Kitties", backgroundColor: "oink", imageUrl: ModelsData.collectibles.kitty3Big, isLoading: false, - communityId: "ast" + communityId: "ast", + visibility: Constants.ShowcaseVisibility.NoOne }, { - uid: "691", + key: "6912", name: "KILLABEAR", collectionName: "KILLABEARS", backgroundColor: "#807c56", imageUrl: "https://assets.killabears.com/content/killabears/img/691-e81f892696a8ae700e0dbc62eb072060679a2046d1ef5eb2671bdb1fad1f68e3.png", - isLoading: true + isLoading: true, + visibility: Constants.ShowcaseVisibility.NoOne }, { - uid: "8876", + key: "8876", name: "AIORBIT", description: "", collectionName: "AIORBIT (Animated SVG)", backgroundColor: "", imageUrl: "https://dl.openseauserdata.com/cache/originImage/files/8b14ef530b28853445c27d6693c4e805.svg", - isLoading: false + isLoading: false, + visibility: Constants.ShowcaseVisibility.NoOne + } + ] + Component.onCompleted: append(data) + } + + ListModel { + id: inShowcaseModelItem + + readonly property var data: [ + { + key: "123", + name: "SNT", + collectionName: "Super Nitro Toluen (with pink bg)", + backgroundColor: "pink", + imageUrl: ModelsData.collectibles.custom, + isLoading: false, + communityId: "ddls", + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "34545656768", + name: "Kitty 1", + collectionName: "Kitties", + backgroundColor: "", + imageUrl: ModelsData.collectibles.kitty1Big, + isLoading: false, + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "123456", + name: "Kitty 2", + collectionName: "", + backgroundColor: "", + imageUrl: ModelsData.collectibles.kitty2Big, + isLoading: false, + communityId: "sox", + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "12345645459537432", + name: "", + collectionName: "Super Kitties", + backgroundColor: "oink", + imageUrl: ModelsData.collectibles.kitty3Big, + isLoading: false, + communityId: "ast", + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "691", + name: "KILLABEAR", + collectionName: "KILLABEARS", + backgroundColor: "#807c56", + imageUrl: "https://assets.killabears.com/content/killabears/img/691-e81f892696a8ae700e0dbc62eb072060679a2046d1ef5eb2671bdb1fad1f68e3.png", + isLoading: true, + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "8876", + name: "AIORBIT", + description: "", + collectionName: "AIORBIT (Animated SVG)", + backgroundColor: "", + imageUrl: "https://dl.openseauserdata.com/cache/originImage/files/8b14ef530b28853445c27d6693c4e805.svg", + isLoading: false, + visibility: Constants.ShowcaseVisibility.Everyone } ] Component.onCompleted: append(data) @@ -117,63 +178,37 @@ SplitView { } LeftJoinModel { - id: leftJoinModel + id: joinedInShowcase - leftModel: collectiblesModel + leftModel: inShowcaseModelItem rightModel: communityModel joinRole: "communityId" } ListModel { - id: inShowcaseCollectiblesModel - - property int hiddenCount: emptyModelChecker.checked ? 0 : collectiblesModel.count - count - - signal baseModelFilterConditionsMayHaveChanged() - - function setVisibilityByIndex(index, visibility) { - if (visibility === Constants.ShowcaseVisibility.NoOne) { - remove(index) - } else { - get(index).showcaseVisibility = visibility - } - } - - function setVisibility(uid, visibility) { - for (let i = 0; i < count; ++i) { - if (get(i).uid === uid) { - setVisibilityByIndex(i, visibility) - } - } - } - - function hasItemInShowcase(uid) { - for (let i = 0; i < count; ++i) { - if (get(i).uid === uid) { - return true - } - } - return false - } - - function upsertItemJson(item) { - append(JSON.parse(item)) - } + id: emptyModelItem } - StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml + LeftJoinModel { + id: joinedHiddenModel + + leftModel: hiddenModelItem + rightModel: communityModel + + joinRole: "communityId" + } + + ProfileShowcaseCollectiblesPanel { + id: showcasePanel SplitView.fillWidth: true SplitView.preferredHeight: 500 - ProfileShowcaseCollectiblesPanel { - id: showcasePanel - width: 500 - baseModel: emptyModelChecker.checked ? emptyModel : leftJoinModel - showcaseModel: inShowcaseCollectiblesModel - addAccountsButtonVisible: !hasAllAccountsChecker.checked + inShowcaseModel: emptyModelChecker.checked ? emptyModelItem : joinedInShowcase + hiddenModel: emptyModelChecker.checked ? emptyModelItem : joinedHiddenModel - onNavigateToAccountsTab: logs.logEvent("ProfileShowcaseCollectiblesPanel::onNavigateToAccountsTab") - } + addAccountsButtonVisible: !hasAllAccountsChecker.checked + + onNavigateToAccountsTab: logs.logEvent("ProfileShowcaseCollectiblesPanel::onNavigateToAccountsTab") } LogsAndControlsPanel { @@ -185,12 +220,10 @@ SplitView { logsView.logText: logs.logText ColumnLayout { - Button { - text: "Reset (clear settings)" - - onClicked: showcasePanel.settings.reset() + Label { + text: "β“˜ Shwcase interaction implemented in ProfileShowcasePanelPage" } - + CheckBox { id: hasAllAccountsChecker @@ -203,10 +236,7 @@ SplitView { text: "Empty model" checked: false - - onClicked: showcasePanel.reset() } - } } } diff --git a/storybook/pages/ProfileShowcaseCommunitiesPanelPage.qml b/storybook/pages/ProfileShowcaseCommunitiesPanelPage.qml index 736844b3b3..a16e06bd01 100644 --- a/storybook/pages/ProfileShowcaseCommunitiesPanelPage.qml +++ b/storybook/pages/ProfileShowcaseCommunitiesPanelPage.qml @@ -5,7 +5,6 @@ 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 @@ -22,106 +21,110 @@ SplitView { orientation: Qt.Vertical - Popups { - popupParent: root - rootStore: QtObject {} - communityTokensStore: CommunityTokensStore {} + ListModel { + id: hiddenModelItem + Component.onCompleted: + append([{ + key: "0x0006", + name: "Test community 6", + joined: true, + memberRole: Constants.memberRole.owner, + isControlNode: true, + image: ModelsData.icons.dribble, + color: "yellow", + visibility: Constants.ShowcaseVisibility.NoOne + }, + { + key: "0x0007", + name: "Test community 7", + joined: true, + memberRole: Constants.memberRole.none, + isControlNode: false, + image: ModelsData.collectibles.custom, + color: "peach", + visibility: Constants.ShowcaseVisibility.NoOne + }, + { + key: "0x0008", + name: "Test community 8", + joined: true, + memberRole: Constants.memberRole.none, + isControlNode: false, + image: "", + color: "whitesmoke", + visibility: Constants.ShowcaseVisibility.NoOne + }, + { + key: "0x0009", + name: "Test community 9", + joined: true, + memberRole: Constants.memberRole.admin, + isControlNode: false, + image: ModelsData.icons.spotify, + color: "green", + visibility: Constants.ShowcaseVisibility.NoOne + }, + ]) + } + + ListModel { + id: inShowcaseModelItem + + Component.onCompleted: + append([{ + key: "0x0001", + name: "Test community", + joined: true, + memberRole: Constants.memberRole.owner, + isControlNode: true, + image: ModelsData.icons.dribble, + color: "yellow", + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "0x0002", + name: "Test community 2", + joined: true, + memberRole: Constants.memberRole.none, + isControlNode: false, + image: ModelsData.collectibles.custom, + color: "peach", + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "0x0004", + name: "Test community 3", + joined: true, + memberRole: Constants.memberRole.none, + isControlNode: false, + image: "", + color: "whitesmoke", + visibility: Constants.ShowcaseVisibility.Everyone + }, + { + key: "0x0005", + name: "Test community 4", + joined: true, + memberRole: Constants.memberRole.admin, + isControlNode: false, + image: ModelsData.icons.spotify, + color: "green", + visibility: Constants.ShowcaseVisibility.Everyone + }, + ]) } ListModel { id: emptyModel } - ListModel { - id: communitiesModel - - Component.onCompleted: - append([{ - id: "0x0001", - name: "Test community", - joined: true, - memberRole: Constants.memberRole.owner, - isControlNode: true, - image: ModelsData.icons.dribble, - color: "yellow" - }, - { - id: "0x0002", - name: "Test community 2", - joined: true, - memberRole: Constants.memberRole.none, - isControlNode: false, - image: ModelsData.collectibles.custom, - color: "peach" - }, - { - id: "0x0004", - name: "Test community 3", - joined: true, - memberRole: Constants.memberRole.none, - isControlNode: false, - image: "", - color: "whitesmoke" - }, - { - id: "0x0005", - name: "Test community 4", - joined: true, - memberRole: Constants.memberRole.admin, - isControlNode: false, - image: ModelsData.icons.spotify, - color: "green" - }, - ]) - } - - 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 - } - } - - function setVisibility(id, visibility) { - for (let i = 0; i < count; ++i) { - if (get(i).id === id) { - setVisibilityByIndex(i, visibility) - } - } - } - - function hasItemInShowcase(id) { - for (let i = 0; i < count; ++i) { - if (get(i).id === id) { - return true - } - } - return false - } - - function upsertItemJson(item) { - append(JSON.parse(item)) - } - } - - StatusScrollView { // wrapped in a ScrollView on purpose; to simulate SettingsContentBase.qml + ProfileShowcaseCommunitiesPanel { + id: showcasePanel SplitView.fillWidth: true SplitView.preferredHeight: 500 - ProfileShowcaseCommunitiesPanel { - id: showcasePanel - width: 500 - baseModel: emptyModelChecker.checked ? emptyModel : communitiesModel - showcaseModel: inShowcaseCommunitiesModel - } + inShowcaseModel: emptyModelChecker.checked ? emptyModel : inShowcaseModelItem + hiddenModel: emptyModelChecker.checked ? emptyModel : hiddenModelItem } LogsAndControlsPanel { @@ -133,9 +136,8 @@ SplitView { logsView.logText: logs.logText ColumnLayout { - Button { - text: "Reset (clear settings)" - onClicked: showcasePanel.reset() + Label { + text: "β“˜ Shwcase interaction implemented in ProfileShowcasePanelPage" } CheckBox { @@ -143,11 +145,10 @@ SplitView { text: "Empty model" checked: false - - onClicked: showcasePanel.reset() } } } + } // category: Panels diff --git a/storybook/pages/ProfileShowcasePanelPage.qml b/storybook/pages/ProfileShowcasePanelPage.qml new file mode 100644 index 0000000000..82e4ad5fa7 --- /dev/null +++ b/storybook/pages/ProfileShowcasePanelPage.qml @@ -0,0 +1,222 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import AppLayouts.Profile.panels 1.0 +import AppLayouts.Profile.controls 1.0 +import StatusQ.Components 0.1 + +import utils 1.0 + +import Storybook 1.0 + +SplitView { + //id: root + + property int inShowcaseModelCount: inShowcaseCounter.value + property int hiddenModelCount: hiddenCounter.value + + orientation: Qt.Vertical + + Logs { id: logs } + + ListModel { + id: inShowcaseModelItem + ListElement { + key: 1 + title: "Item 1" + secondaryTitle: "Description 1" + hasImage: true + image: "https://picsum.photos/200/300?random=1" + iconName: "https://picsum.photos/40/40?random=1" + visibility: 1 + name: "Test community" + joined: true + isControlNode: true + color: "yellow" + hasTag: true + tagText: "New" + tagAsset: "https://picsum.photos/40/40?random=1" + tagLoading: true + } + } + + ListModel { + id: hiddenModelItem + ListElement { + key: 2 + title: "Item 1" + secondaryTitle: "Description 1" + hasImage: true + image: "https://picsum.photos/200/300?random=1" + iconName: "https://picsum.photos/40/40?random=1" + visibility: 0 + name: "Test community" + joined: true + isControlNode: true + color: "yellow" + tagVisible: true + tagText: "New" + tagAsset: "https://picsum.photos/40/40?random=1" + tagLoading: true + } + } + + ProfileShowcasePanel { + id: root + inShowcaseModel: inShowcaseModelItem + hiddenModel: hiddenModelItem + SplitView.fillWidth: true + SplitView.fillHeight: true + emptyInShowcasePlaceholderText: "No items in showcase" + emptyHiddenPlaceholderText: "No hidden items" + onChangePositionRequested: function (key, to) { + for (var i = 0; i < inShowcaseModelItem.count; i++) { + if (inShowcaseModelItem.get(i).key === key) { + inShowcaseModelItem.move(i, to, 1) + break + } + } + + for (var i = 0; i < hiddenModelItem.count; i++) { + if (hiddenModelItem.get(i).key === key) { + hiddenModelItem.move(from, to, 1) + break + } + } + } + onSetVisibilityRequested: function (key, toVisibility) { + for (var i = 0; i < inShowcaseModelItem.count; i++) { + if (inShowcaseModelItem.get(i).key === key) { + inShowcaseModelItem.setProperty(i, "visibility", toVisibility) + if(toVisibility === 0) { + let item = inShowcaseModelItem.get(i) + hiddenModelItem.append(item) + inShowcaseModelItem.remove(i, 1) + } + return + } + } + + for (var i = 0; i < hiddenModelItem.count; i++) { + if (hiddenModelItem.get(i).key === key) { + hiddenModelItem.setProperty(i, "visibility", toVisibility) + if(toVisibility !== 0) { + let item = hiddenModelItem.get(i) + inShowcaseModelItem.append(item) + hiddenModelItem.remove(i, 1) + } + return + } + } + } + + delegate: ProfileShowcasePanel.Delegate { + title: model ? model.title : "" + secondaryTitle: model ? model.secondaryTitle : "" + hasImage: model ? model.hasImage : false + icon.name: model ? model.iconName : "" + icon.source: model ? model.image : "" + icon.color: model ? model.color : "" + + tag.visible: model ? model.hasTag : false + tag.text: model ? model.tagText : "" + tag.asset.name: model ? model.tagAsset : "" + tag.loading: model ? model.tagLoading : false + } + } + + LogsAndControlsPanel { + id: logsAndControlsPanel + SplitView.fillWidth: true + SplitView.preferredHeight: 200 + + RowLayout { + anchors.fill: parent + spacing: 10 + + ColumnLayout { + Label { + text: "In showcase: " + inShowcaseCounter.value + } + Slider { + id: inShowcaseCounter + from: 0 + to: 200 + stepSize: 1 + value: 25 + } + + Label { + text: "Hidden: " + hiddenCounter.value + } + Slider { + id: hiddenCounter + from: 0 + to: 200 + stepSize: 1 + value: 25 + } + } + } + } + + onInShowcaseModelCountChanged: { + let count = inShowcaseModelCount - inShowcaseModelItem.count; + let operation = count > 0 ? (i) =>{ + inShowcaseModelItem.append({ + key: Math.random() * Math.random() * Math.random() * 1000, + title: "Item " + i, + secondaryTitle: "Description " + i, + hasImage: true, + image: "https://picsum.photos/200/300?random=" + i, + iconName: "https://picsum.photos/40/40?random=" + i, + visibility: Math.ceil(Math.random() * 3), + name: "Test community", + joined: true, + isControlNode: true, + color: "yellow", + hasTag: Math.random() > 0.5, + tagText: "New " + 1, + tagAsset: "https://picsum.photos/40/40?random=" + i, + tagLoading: Math.random() > 0.5 + })} : (i) => { + inShowcaseModelItem.remove(inShowcaseModelItem.count - 1); + } + + for (var i = 0; i < Math.abs(count); i++) { + operation(i) + } + } + + onHiddenModelCountChanged: { + let count = hiddenModelCount - hiddenModelItem.count; + let operation = count > 0 ? (i) =>{ + hiddenModelItem.append({ + key: Math.random() * Math.random() * Math.random() * 1000, + title: "Item " + i, + secondaryTitle: "Description " + i, + hasImage: true, + image: "https://picsum.photos/200/300?random=" + i, + iconName: "https://picsum.photos/40/40?random=" + i, + visibility: 0, + name: "Test community", + joined: true, + memberRole: Constants.memberRole.owner, + isControlNode: true, + color: "yellow", + hasTag: Math.random() > 0.5, + tagText: "New " + i, + tagAsset: "https://picsum.photos/40/40?random=" + i, + tagLoading: Math.random() > 0.8 + })} : (i) => { + hiddenModelItem.remove(hiddenModelItem.count - 1); + } + + for (var i = 0; i < Math.abs(count); i++) { + operation(i) + } + } +} + +// category: Panels diff --git a/ui/StatusQ/src/statusq.qrc b/ui/StatusQ/src/statusq.qrc index c41eef1ea5..18680190dd 100644 --- a/ui/StatusQ/src/statusq.qrc +++ b/ui/StatusQ/src/statusq.qrc @@ -191,6 +191,7 @@ StatusQ/Core/Utils/ModelUtils.qml StatusQ/Core/Utils/ModelsComparator.qml StatusQ/Core/Utils/OperatorsUtils.qml + StatusQ/Core/Utils/QObject.qml StatusQ/Core/Utils/StackViewStates.qml StatusQ/Core/Utils/StatesStack.qml StatusQ/Core/Utils/StringUtils.qml diff --git a/ui/app/AppLayouts/Profile/controls/AccountShowcaseDelegate.qml b/ui/app/AppLayouts/Profile/controls/AccountShowcaseDelegate.qml deleted file mode 100644 index a6a1d21590..0000000000 --- a/ui/app/AppLayouts/Profile/controls/AccountShowcaseDelegate.qml +++ /dev/null @@ -1,16 +0,0 @@ -import QtQuick 2.15 - -import StatusQ.Core.Theme 0.1 - -import AppLayouts.Wallet 1.0 - -import utils 1.0 - -ShowcaseDelegate { - title: !!showcaseObj && !!showcaseObj.name ? showcaseObj.name : "" - secondaryTitle: WalletUtils.addressToDisplay(!!showcaseObj && !!showcaseObj.address ? showcaseObj.address : "", "", true, containsMouse) - hasEmoji: !!showcaseObj && !!showcaseObj.emoji - hasIcon: !hasEmoji - icon.name: hasEmoji ? showcaseObj.emoji : "filled-account" - icon.color: !!showcaseObj && showcaseObj.colorId ? Utils.getColorForId(showcaseObj.colorId) : Theme.palette.primaryColor3 -} diff --git a/ui/app/AppLayouts/Profile/controls/AssetShowcaseDelegate.qml b/ui/app/AppLayouts/Profile/controls/AssetShowcaseDelegate.qml deleted file mode 100644 index 4f9d0473a9..0000000000 --- a/ui/app/AppLayouts/Profile/controls/AssetShowcaseDelegate.qml +++ /dev/null @@ -1,26 +0,0 @@ -import QtQuick 2.15 - -import StatusQ 0.1 -import StatusQ.Core 0.1 - -import utils 1.0 - -ShowcaseDelegate { - id: root - - property var formatCurrencyAmount: function(amount, symbol){} - property double totalValue: !!showcaseObj && !!showcaseObj.decimals ? balancesAggregator.value/(10 ** showcaseObj.decimals): 0 - - title: !!showcaseObj && !!showcaseObj.name ? showcaseObj.name : "" - secondaryTitle: !!showcaseObj && !!showcaseObj.enabledNetworkBalance ? - LocaleUtils.currencyAmountToLocaleString(showcaseObj.enabledNetworkBalance) : - !!showcaseObj && !!showcaseObj.symbol ? formatCurrencyAmount(totalValue, showcaseObj.symbol): Qt.locale().zeroDigit - hasImage: true - icon.source: !!showcaseObj ? Constants.tokenIcon(showcaseObj.symbol) : "" - - SumAggregator { - id: balancesAggregator - model: !!showcaseObj && !!showcaseObj.balances ? showcaseObj.balances: null - roleName: "balance" - } -} diff --git a/ui/app/AppLayouts/Profile/controls/CollectibleShowcaseDelegate.qml b/ui/app/AppLayouts/Profile/controls/CollectibleShowcaseDelegate.qml deleted file mode 100644 index 2c4a7227bf..0000000000 --- a/ui/app/AppLayouts/Profile/controls/CollectibleShowcaseDelegate.qml +++ /dev/null @@ -1,13 +0,0 @@ -import QtQuick 2.15 - -import utils 1.0 - -ShowcaseDelegate { - title: !!showcaseObj ? `${showcaseObj.name}` || `#${showcaseObj.id}` : "" - secondaryTitle: !!showcaseObj && !!showcaseObj.collectionName ? showcaseObj.collectionName : "" - hasImage: !!showcaseObj && !!showcaseObj.imageUrl - - icon.source: hasImage ? showcaseObj.imageUrl : "" - bgRadius: Style.current.radius - assetBgColor: !!showcaseObj && !!showcaseObj.backgroundColor ? showcaseObj.backgroundColor : "transparent" -} diff --git a/ui/app/AppLayouts/Profile/controls/CommunityShowcaseDelegate.qml b/ui/app/AppLayouts/Profile/controls/CommunityShowcaseDelegate.qml deleted file mode 100644 index 590301ea86..0000000000 --- a/ui/app/AppLayouts/Profile/controls/CommunityShowcaseDelegate.qml +++ /dev/null @@ -1,15 +0,0 @@ -import QtQuick 2.15 - -import utils 1.0 - -ShowcaseDelegate { - title: !!showcaseObj && !!showcaseObj.name ? showcaseObj.name : "" - secondaryTitle: !!showcaseObj && (showcaseObj.memberRole === Constants.memberRole.owner || - showcaseObj.memberRole === Constants.memberRole.admin || - showcaseObj.memberRole === Constants.memberRole.tokenMaster) ? qsTr("Admin") : qsTr("Member") - hasImage: !!showcaseObj && !!showcaseObj.image - - icon.name: !!showcaseObj ? showcaseObj.name : "" - icon.source: !!showcaseObj ? showcaseObj.image : "" - icon.color: !!showcaseObj ? showcaseObj.color : "transparent" -} diff --git a/ui/app/AppLayouts/Profile/controls/ShowcaseDelegate.qml b/ui/app/AppLayouts/Profile/controls/ShowcaseDelegate.qml index 4ecde5b80e..553c0ca0bc 100644 --- a/ui/app/AppLayouts/Profile/controls/ShowcaseDelegate.qml +++ b/ui/app/AppLayouts/Profile/controls/ShowcaseDelegate.qml @@ -17,7 +17,7 @@ import utils 1.0 StatusDraggableListItem { id: root - property var showcaseObj + property alias tag: tagItem property int showcaseVisibility: Constants.ShowcaseVisibility.NoOne property bool blurState: false @@ -46,10 +46,9 @@ StatusDraggableListItem { actions: [ ManageTokensCommunityTag { + id: tagItem Layout.maximumWidth: root.width *.4 - visible: showcaseObj && !!showcaseObj.communityId - text: showcaseObj && !! showcaseObj.communityName ? showcaseObj.communityName : "" - asset.name: showcaseObj && !!showcaseObj.communityImage ? showcaseObj.communityImage : "" + visible: false }, StatusRoundButton { icon.name: ProfileUtils.visibilityIcon(root.showcaseVisibility) diff --git a/ui/app/AppLayouts/Profile/controls/qmldir b/ui/app/AppLayouts/Profile/controls/qmldir index f32d2b8c09..ffc5eb10b5 100644 --- a/ui/app/AppLayouts/Profile/controls/qmldir +++ b/ui/app/AppLayouts/Profile/controls/qmldir @@ -1,8 +1,5 @@ AddMoreAccountsLink 1.0 AddMoreAccountsLink.qml -CommunityShowcaseDelegate 1.0 CommunityShowcaseDelegate.qml -CollectibleShowcaseDelegate 1.0 CollectibleShowcaseDelegate.qml -AccountShowcaseDelegate 1.0 AccountShowcaseDelegate.qml -AssetShowcaseDelegate 1.0 AssetShowcaseDelegate.qml WalletAccountDelegate 1.0 WalletAccountDelegate.qml +ShowcaseDelegate 1.0 ShowcaseDelegate.qml StaticSocialLinkInput 1.0 StaticSocialLinkInput.qml WalletKeyPairDelegate 1.0 WalletKeyPairDelegate.qml diff --git a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAccountsPanel.qml b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAccountsPanel.qml index 920b85b34d..c439806054 100644 --- a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAccountsPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAccountsPanel.qml @@ -3,43 +3,25 @@ import QtQuick 2.15 import utils 1.0 import AppLayouts.Profile.controls 1.0 +import AppLayouts.Wallet 1.0 + +import StatusQ.Core.Theme 0.1 ProfileShowcasePanel { id: root property string currentWallet - keyRole: "address" - roleNames: ["address", "name", "walletType", "emoji", "colorId"].concat(showcaseRoles) - filterFunc: (modelData) => modelData.walletType !== Constants.keyWalletType && !showcaseModel.hasItemInShowcase(modelData.address) emptyInShowcasePlaceholderText: qsTr("Accounts here will show on your profile") emptyHiddenPlaceholderText: qsTr("Accounts here will be hidden from your profile") - hiddenDraggableDelegateComponent: AccountShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item-hidden"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - highlighted: !!modelData && modelData.address === root.currentWallet - onShowcaseVisibilityRequested: { - var tmpObj = Object() - root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role]) - tmpObj.showcaseVisibility = value - showcaseModel.upsertItemJson(JSON.stringify(tmpObj)) - root.showcaseEntryChanged() - } - } - showcaseDraggableDelegateComponent: AccountShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - highlighted: !!modelData && modelData.address === root.currentWallet - dragAxis: Drag.YAxis - showcaseVisibility: !!modelData ? modelData.showcaseVisibility : Constants.ShowcaseVisibility.NoOne - onShowcaseVisibilityRequested: { - showcaseModel.setVisibility(showcaseObj.address, value) - root.showcaseEntryChanged() - } + delegate: ProfileShowcasePanel.Delegate { + title: model ? model.name : "" + secondaryTitle: WalletUtils.addressToDisplay(model ? model.key : "", "", true, containsMouse) + hasEmoji: model && !!model.emoji + hasIcon: !hasEmoji + icon.name: hasEmoji ? model.emoji : "filled-account" + icon.color: model && model.colorId ? Utils.getColorForId(model.colorId) : Theme.palette.primaryColor3 + highlighted: model ? model.key === root.currentWallet : false } } diff --git a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAssetsPanel.qml b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAssetsPanel.qml index 3093363aee..c78393d454 100644 --- a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAssetsPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseAssetsPanel.qml @@ -1,6 +1,7 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 +import StatusQ 0.1 import StatusQ.Core 0.1 import StatusQ.Controls 0.1 @@ -18,40 +19,28 @@ ProfileShowcasePanel { signal navigateToAccountsTab() - keyRole: "symbol" - roleNames: ["symbol", "name", "address", "communityId", "enabledNetworkBalance", "decimals"].concat(showcaseRoles) - filterFunc: (modelData) => modelData.symbol !== "" && !showcaseModel.hasItemInShowcase(modelData.symbol) emptyInShowcasePlaceholderText: qsTr("Assets here will show on your profile") emptyHiddenPlaceholderText: qsTr("Assets here will be hidden from your profile") - hiddenDraggableDelegateComponent: AssetShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item-hidden"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - formatCurrencyAmount: function(amount, symbol) { - return root.formatCurrencyAmount(amount, symbol) - } - onShowcaseVisibilityRequested: { - var tmpObj = Object() - root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role]) - tmpObj.showcaseVisibility = value - showcaseModel.upsertItemJson(JSON.stringify(tmpObj)) - root.showcaseEntryChanged() - } - } - showcaseDraggableDelegateComponent: AssetShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - dragAxis: Drag.YAxis - showcaseVisibility: !!modelData ? modelData.showcaseVisibility : Constants.ShowcaseVisibility.NoOne - onShowcaseVisibilityRequested: { - showcaseModel.setVisibility(showcaseObj.symbol, value) - root.showcaseEntryChanged() + delegate: ProfileShowcasePanel.Delegate { + + property double totalValue: !!model && !!model.decimals ? balancesAggregator.value/(10 ** model.decimals): 0 + + title: !!model && !!model.name ? model.name : "" + secondaryTitle: !!model && !!model.enabledNetworkBalance ? + LocaleUtils.currencyAmountToLocaleString(model.enabledNetworkBalance) : + !!model && !!model.symbol ? root.formatCurrencyAmount(totalValue, model.symbol) : Qt.locale().zeroDigit + + hasImage: true + icon.source: !!model ? Constants.tokenIcon(model.symbol) : "" + + SumAggregator { + id: balancesAggregator + model: !!model && !!model.balances ? model.balances: null + roleName: "balance" } } + additionalFooterComponent: root.addAccountsButtonVisible ? addMoreAccountsComponent : null Component { diff --git a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCollectiblesPanel.qml b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCollectiblesPanel.qml index e535be7720..63f661a93d 100644 --- a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCollectiblesPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCollectiblesPanel.qml @@ -16,39 +16,26 @@ ProfileShowcasePanel { signal navigateToAccountsTab() - keyRole: "uid" - roleNames: ["uid", "chainId", "tokenId", "contractAddress", "communityId", "name", "collectionName", "backgroundColor", "imageUrl"].concat(showcaseRoles) - filterFunc: (modelData) => !showcaseModel.hasItemInShowcase(modelData.uid) emptyInShowcasePlaceholderText: qsTr("Collectibles here will show on your profile") emptyHiddenPlaceholderText: qsTr("Collectibles here will be hidden from your profile") - hiddenDraggableDelegateComponent: CollectibleShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item-hidden"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - onShowcaseVisibilityRequested: { - var tmpObj = Object() - root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role]) - tmpObj.showcaseVisibility = value - showcaseModel.upsertItemJson(JSON.stringify(tmpObj)) - root.showcaseEntryChanged() - } - } - showcaseDraggableDelegateComponent: CollectibleShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - dragAxis: Drag.YAxis - showcaseVisibility: !!modelData ? modelData.showcaseVisibility : Constants.ShowcaseVisibility.NoOne - onShowcaseVisibilityRequested: { - showcaseModel.setVisibility(showcaseObj.uid, value) - root.showcaseEntryChanged() - } - } additionalFooterComponent: root.addAccountsButtonVisible ? addMoreAccountsComponent : null + delegate: ProfileShowcasePanel.Delegate { + title: !!model ? `${model.name}` || `#${model.id}` : "" + secondaryTitle: !!model && !!model.collectionName ? model.collectionName : "" + hasImage: !!model && !!model.imageUrl + + icon.source: hasImage ? model.imageUrl : "" + bgRadius: Style.current.radius + assetBgColor: !!model && !!model.backgroundColor ? model.backgroundColor : "transparent" + + tag.visible: model && !!model.communityId + tag.text: model && !!model.communityName ? model.communityName : "" + tag.asset.name: model && !!model.communityImage ? model.communityImage : "" + tag.loading: model && !!model.communityImageLoading ? model.communityImageLoading : false + } + Component { id: addMoreAccountsComponent diff --git a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCommunitiesPanel.qml b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCommunitiesPanel.qml index bc53c6fe73..fee577182a 100644 --- a/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCommunitiesPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ProfileShowcaseCommunitiesPanel.qml @@ -7,35 +7,18 @@ import AppLayouts.Profile.controls 1.0 ProfileShowcasePanel { id: root - keyRole: "id" - roleNames: ["id", "name", "memberRole", "image", "color"].concat(showcaseRoles) - 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") - hiddenDraggableDelegateComponent: CommunityShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item-hidden"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - onShowcaseVisibilityRequested: { - var tmpObj = Object() - root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role]) - tmpObj.showcaseVisibility = value - root.showcaseModel.upsertItemJson(JSON.stringify(tmpObj)) - root.showcaseEntryChanged() - } - } - showcaseDraggableDelegateComponent: CommunityShowcaseDelegate { - Drag.keys: ["x-status-draggable-showcase-item"] - showcaseObj: modelData - dragParent: dragParentData - visualIndex: visualIndexData - dragAxis: Drag.YAxis - showcaseVisibility: !!modelData ? modelData.showcaseVisibility : Constants.ShowcaseVisibility.NoOne - onShowcaseVisibilityRequested: { - root.showcaseModel.setVisibility(showcaseObj.id, value) - root.showcaseEntryChanged() - } + delegate: ProfileShowcasePanel.Delegate { + title: model ? model.name : "" + secondaryTitle: model && (model.memberRole === Constants.memberRole.owner || + model.memberRole === Constants.memberRole.admin || + model.memberRole === Constants.memberRole.tokenMaster) ? qsTr("Admin") : qsTr("Member") + hasImage: model && !!model.image + + icon.name: model ? model.name : "" + icon.source: model ? model.image : "" + icon.color: model ? model.color : "" } } diff --git a/ui/app/AppLayouts/Profile/panels/ProfileShowcasePanel.qml b/ui/app/AppLayouts/Profile/panels/ProfileShowcasePanel.qml index 2efc1ac665..f05515513f 100644 --- a/ui/app/AppLayouts/Profile/panels/ProfileShowcasePanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ProfileShowcasePanel.qml @@ -2,6 +2,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import QtQml 2.15 +import QtQml.Models 2.15 import StatusQ.Controls 0.1 import StatusQ.Core 0.1 @@ -16,44 +17,51 @@ import AppLayouts.Profile.controls 1.0 DoubleFlickableWithFolding { id: root - readonly property var showcaseRoles: ["showcaseVisibility", "order"] + property Component delegate: Delegate {} - required property string keyRole - required property var roleNames - required property var filterFunc - - property var baseModel - property var showcaseModel - - property Component showcaseDraggableDelegateComponent - property Component hiddenDraggableDelegateComponent + // Expected roles: + // - visibility: int + property var inShowcaseModel + property var hiddenModel property Component additionalFooterComponent + // Placeholder text to be shown when the list is empty property string emptyInShowcasePlaceholderText property string emptyHiddenPlaceholderText - readonly property Connections showcaseUpdateConnections: Connections { - target: root.showcaseModel + // Signal to requst position change of the visible items + signal changePositionRequested(var key, int to) + // Signal to request visibility change of the items + signal setVisibilityRequested(var key, int toVisibility) - function onBaseModelFilterConditionsMayHaveChanged() { - root.updateBaseModelFilters() + // Public delegate component. Implements the minimal ShowcaseDelegate interface needed for DND + component Delegate: ShowcaseDelegate { + id: showcaseDelegate + + property var model: modelData + property var dragKeys: dragKeysData + + readonly property var key: model ? model.key : null + + Drag.keys: dragKeys + + dragParent: root + visualIndex: visualIndexData + dragAxis: Drag.YAxis + showcaseVisibility: model ? model.visibility ?? Constants.ShowcaseVisibility.NoOne : + Constants.ShowcaseVisibility.NoOne + + onShowcaseVisibilityRequested: function (toVisibility){ + root.setVisibilityRequested(key, toVisibility) } } - function reset() { - root.showcaseModel.clear() - updateBaseModelFilters() + ScrollBar.vertical: StatusScrollBar { + policy: ScrollBar.AsNeeded + visible: resolveVisibility(policy, root.height, root.contentHeight) } - function updateBaseModelFilters() { - // Reset base model to update filter conditions - hiddenListView.model = null - hiddenListView.model = root.baseModel - } - - signal showcaseEntryChanged() - QtObject { id: d @@ -69,20 +77,16 @@ DoubleFlickableWithFolding { clip: true - ScrollBar.vertical: StatusScrollBar { - policy: ScrollBar.AsNeeded - visible: resolveVisibility(policy, root.height, root.contentHeight) - } - flickable1: EmptyShapeRectangleFooterListView { id: inShowcaseListView - model: root.showcaseModel width: root.width placeholderText: root.emptyInShowcasePlaceholderText footerHeight: ProfileUtils.defaultDelegateHeight footerContentVisible: !dropAreaRow.visible spacing: Style.current.halfPadding + delegate: delegateWrapper + model: root.inShowcaseModel header: FoldableHeader { width: ListView.view.width @@ -101,66 +105,7 @@ DoubleFlickableWithFolding { } onToggleFolding: root.flip1Folding() - } - - delegate: DropArea { - id: showcaseDelegateRoot - - property int visualIndex: index - - width: ListView.view.width - height: visible && showcaseDraggableDelegateLoader.item ? showcaseDraggableDelegateLoader.item.height : 0 - - keys: d.dragShowcaseItemKey - visible: model.showcaseVisibility !== Constants.ShowcaseVisibility.NoOne - - onEntered: function(drag) { - const from = drag.source.visualIndex - const to = showcaseDraggableDelegateLoader.item.visualIndex - if (to === from) - return - root.showcaseEntryChanged() - root.showcaseModel.move(from, to, 1) - drag.accept() - } - - // TODO: - // This animation is causing issues when there are no elements in the showcase list. - // Reenable it once the refactor of the models and delegates is done (simplified): #13498 - // ListView.onRemove: SequentialAnimation { - // PropertyAction { target: showcaseDelegateRoot; property: "ListView.delayRemove"; value: true } - // NumberAnimation { target: showcaseDelegateRoot; property: "scale"; to: 0; easing.type: Easing.InOutQuad } - // PropertyAction { target: showcaseDelegateRoot; property: "ListView.delayRemove"; value: false } - // } - - // In showcase delegate item container: - Loader { - id: showcaseDraggableDelegateLoader - - property var modelData: model - property var dragParentData: root - property int visualIndexData: index - - width: parent.width - sourceComponent: root.showcaseDraggableDelegateComponent - } - - // Delegate shadow background when dragging: - ShadowDelegate { - id: showcaseShadow - - visible: showcaseDraggableDelegateLoader.item && showcaseDraggableDelegateLoader.item.dragActive - onVisibleChanged: d.isAnyShowcaseDragActive = visible - } - - Binding { - when: dropAreaRow.visible - target: showcaseDraggableDelegateLoader.item - property: "blurState" - value: true - restoreMode: Binding.RestoreBindingOrValue - } - } + } // Overlaid showcase listview content drop area: DropArea { @@ -188,14 +133,14 @@ DoubleFlickableWithFolding { flickable2: EmptyShapeRectangleFooterListView { id: hiddenListView - model: root.baseModel width: root.width placeholderText: root.emptyHiddenPlaceholderText footerHeight: ProfileUtils.defaultDelegateHeight footerContentVisible: !hiddenDropAreaButton.visible - empty: root.showcaseModel.hiddenCount === 0 && !root.flickable2Folded // TO BE REMOVE: #13498 additionalFooterComponent: root.additionalFooterComponent spacing: Style.current.halfPadding + delegate: delegateWrapper + model: root.hiddenModel header: FoldableHeader { width: ListView.view.width @@ -209,64 +154,12 @@ DoubleFlickableWithFolding { text: qsTr("Hide") dropAreaKeys: d.dragShowcaseItemKey - onDropped: { - root.showcaseModel.setVisibilityByIndex(drop.source.visualIndex, visibility) - root.showcaseEntryChanged() - } + onDropped: root.setVisibilityRequested(drop.source.key, visibility) } onToggleFolding: root.flip2Folding() } - delegate: DropArea { - id: hiddenDelegateRoot - - property int visualIndex: index - - visible: root.filterFunc(model) - width: ListView.view.width - height: visible && hiddenDraggableDelegateLoader.item ? hiddenDraggableDelegateLoader.item.height : 0 - - keys: d.dragShowcaseItemKey - - onEntered: function(drag) { - drag.accept() - } - - onDropped: function(drop) { - root.showcaseModel.setVisibilityByIndex(drop.source.visualIndex, Constants.ShowcaseVisibility.NoOne) - root.showcaseEntryChanged() - } - - // Hidden delegate item container: - Loader { - id: hiddenDraggableDelegateLoader - - property var modelData: model - property var dragParentData: root - property int visualIndexData: hiddenDelegateRoot.visualIndex - - width: parent.width - sourceComponent: root.hiddenDraggableDelegateComponent - } - - // Delegate shadow background when dragging: - ShadowDelegate { - id: hiddenShadow - - visible: hiddenDraggableDelegateLoader.item && hiddenDraggableDelegateLoader.item.dragActive - onVisibleChanged: d.isAnyHiddenDragActive = visible - } - - Binding { - when: hiddenDropAreaButton.visible - target: hiddenDraggableDelegateLoader.item - property: "blurState" - value: true - restoreMode: Binding.RestoreBindingOrValue - } - } - // Overlaid hidden listview content drop area: DropArea { anchors.top: parent.top @@ -288,11 +181,7 @@ DoubleFlickableWithFolding { text: qsTr("Hide") dropAreaKeys: d.dragShowcaseItemKey - onDropped: { - root.showcaseModel.setVisibilityByIndex(drop.source.visualIndex, visibility) - root.showcaseEntryChanged() - root.updateBaseModelFilters() - } + onDropped: root.setVisibilityRequested(drop.source.key, visibility) } } } @@ -366,18 +255,7 @@ DoubleFlickableWithFolding { property int margins: Style.current.halfPadding function dropped(drop, visibility) { - var showcaseObj = drop.source.showcaseObj - - // need to set total balance for an asset - if (drop.source.totalValue !== undefined) { - showcaseObj.enabledNetworkBalance = drop.source.totalValue - } - - var tmpObj = Object() - root.roleNames.forEach(role => tmpObj[role] = showcaseObj[role]) - tmpObj.showcaseVisibility = visibility - root.showcaseModel.upsertItemJson(JSON.stringify(tmpObj)) - root.showcaseEntryChanged() + root.setVisibilityRequested(drop.source.key, visibility) } RowLayout { @@ -427,4 +305,92 @@ DoubleFlickableWithFolding { color: Theme.palette.baseColor5 radius: Style.current.radius } + + Component { + id: delegateWrapper + DropArea { + id: showcaseDelegateRoot + + required property var model + required property int index + readonly property int visualIndex: index + readonly property bool isHiddenShowcaseItem: !model.visibility || model.visibility === Constants.ShowcaseVisibility.NoOne + + function handleEntered(drag) { + if (!showcaseDelegateRoot.isHiddenShowcaseItem) { + var from = drag.source.visualIndex + var to = visualIndex + if (to === from) + return + root.changePositionRequested(drag.source.key, to) + } + drag.accept() + } + function handleDropped(drop) { + if (showcaseDelegateRoot.isHiddenShowcaseItem) { + root.setVisibilityRequested(drop.source.key, Constants.ShowcaseVisibility.NoOne) + } + } + + 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 ? + d.dragHiddenItemKey : d.dragShowcaseItemKey + + width: parent.width + sourceComponent: root.delegate + } + + Binding { + when: showcaseDelegateRoot.isHiddenShowcaseItem ? d.isAnyShowcaseDragActive : d.isAnyHiddenDragActive + target: showcaseDraggableDelegateLoader.item + property: "blurState" + value: true + restoreMode: Binding.RestoreBindingOrValue + } + + Binding { + when: showcaseShadow.visible + target: d + property: showcaseDelegateRoot.isHiddenShowcaseItem ? "isAnyHiddenDragActive" : "isAnyShowcaseDragActive" + value: true + restoreMode: Binding.RestoreBindingOrValue + } + + // Delegate shadow background when dragging: + ShadowDelegate { + id: showcaseShadow + + visible: showcaseDraggableDelegateLoader.item && showcaseDraggableDelegateLoader.item.dragActive + } + + // Delegate shadow background when dragging: + Rectangle { + width: parent.width + height: d.defaultDelegateHeight + anchors.centerIn: parent + color: Theme.palette.baseColor5 + radius: Style.current.radius + visible: showcaseShadow.visible + } + } + } } diff --git a/ui/app/AppLayouts/Profile/panels/qmldir b/ui/app/AppLayouts/Profile/panels/qmldir index 0349907e16..3ec7580ea9 100644 --- a/ui/app/AppLayouts/Profile/panels/qmldir +++ b/ui/app/AppLayouts/Profile/panels/qmldir @@ -1,7 +1,8 @@ ProfileDescriptionPanel 1.0 ProfileDescriptionPanel.qml -ProfileSocialLinksPanel 1.0 ProfileSocialLinksPanel.qml -ProfileShowcaseCommunitiesPanel 1.0 ProfileShowcaseCommunitiesPanel.qml -ProfileShowcaseCollectiblesPanel 1.0 ProfileShowcaseCollectiblesPanel.qml ProfileShowcaseAccountsPanel 1.0 ProfileShowcaseAccountsPanel.qml ProfileShowcaseAssetsPanel 1.0 ProfileShowcaseAssetsPanel.qml +ProfileShowcaseCollectiblesPanel 1.0 ProfileShowcaseCollectiblesPanel.qml +ProfileShowcaseCommunitiesPanel 1.0 ProfileShowcaseCommunitiesPanel.qml +ProfileShowcasePanel 1.0 ProfileShowcasePanel.qml +ProfileSocialLinksPanel 1.0 ProfileSocialLinksPanel.qml SupportedTokenListsPanel 1.0 SupportedTokenListsPanel.qml diff --git a/ui/app/AppLayouts/Profile/views/MyProfileView.qml b/ui/app/AppLayouts/Profile/views/MyProfileView.qml index 3febe4302c..c5e29fa0b3 100644 --- a/ui/app/AppLayouts/Profile/views/MyProfileView.qml +++ b/ui/app/AppLayouts/Profile/views/MyProfileView.qml @@ -16,9 +16,11 @@ import "./profile" import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 +import StatusQ.Core.Utils 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 +import AppLayouts.Profile.helpers 1.0 import AppLayouts.Profile.panels 1.0 import AppLayouts.Wallet.stores 1.0 @@ -113,7 +115,18 @@ SettingsContentBase { readonly property var priv: QtObject { id: priv - property bool hasAnyProfileShowcaseChanges: false + property bool hasAnyProfileShowcaseChanges: showcaseModels.dirty + + property ProfileShowcaseModels showcaseModels: ProfileShowcaseModels { + communitiesSourceModel: root.communitiesModel + communitiesShowcaseModel: root.profileStore.profileShowcaseCommunitiesModel + + accountsSourceModel: root.walletStore.accounts + accountsShowcaseModel: root.profileStore.profileShowcaseAccountsModel + + collectiblesSourceModel: root.profileStore.collectiblesModel + collectiblesShowcaseModel: root.profileStore.profileShowcaseCollectiblesModel + } function reset() { descriptionPanel.displayName.text = Qt.binding(() => { return profileStore.displayName }) @@ -121,33 +134,15 @@ SettingsContentBase { profileStore.resetSocialLinks() profileHeader.icon = Qt.binding(() => { return profileStore.profileLargeImage }) - profileShowcaseCommunitiesPanel.reset() - profileShowcaseAccountsPanel.reset() - profileShowcaseCollectiblesPanel.reset() - profileShowcaseAssetsPanel.reset() + priv.showcaseModels.revert() root.profileStore.requestProfileShowcasePreferences() - hasAnyProfileShowcaseChanges = false } function save() { if (hasAnyProfileShowcaseChanges) - profileStore.storeProfileShowcasePreferences() - - if (!descriptionPanel.isEnsName) - profileStore.setDisplayName(descriptionPanel.displayName.text) - profileStore.setBio(descriptionPanel.bio.text.trim()) - profileStore.saveSocialLinks() - if (profileHeader.icon === "") { - root.profileStore.removeImage() - } else { - profileStore.uploadImage(profileHeader.icon, - profileHeader.cropRect.x.toFixed(), - profileHeader.cropRect.y.toFixed(), - (profileHeader.cropRect.x + profileHeader.cropRect.width).toFixed(), - (profileHeader.cropRect.y + profileHeader.cropRect.height).toFixed()); - } - - reset() + print ("Profile showcase changes detected: SAVING") + //TODO: implement save as deschibed here + // https://github.com/status-im/status-desktop/pull/13708 } } @@ -206,32 +201,50 @@ SettingsContentBase { // communities ProfileShowcaseCommunitiesPanel { id: profileShowcaseCommunitiesPanel - baseModel: root.communitiesModel - showcaseModel: root.profileStore.profileShowcaseCommunitiesModel - onShowcaseEntryChanged: priv.hasAnyProfileShowcaseChanges = true + inShowcaseModel: priv.showcaseModels.communitiesVisibleModel + hiddenModel: priv.showcaseModels.communitiesHiddenModel + + onChangePositionRequested: function (key, to) { + priv.showcaseModels.changeCommunityPosition(key, to) + } + onSetVisibilityRequested: function (key, toVisibility) { + priv.showcaseModels.setCommunityVisibility(key, toVisibility) + } } // accounts ProfileShowcaseAccountsPanel { id: profileShowcaseAccountsPanel - baseModel: root.walletStore.accounts - showcaseModel: root.profileStore.profileShowcaseAccountsModel + inShowcaseModel: priv.showcaseModels.accountsVisibleModel + hiddenModel: priv.showcaseModels.accountsHiddenModel currentWallet: root.walletStore.overview.mixedcaseAddress - onShowcaseEntryChanged: priv.hasAnyProfileShowcaseChanges = true + + onChangePositionRequested: function (key, to) { + priv.showcaseModels.changeAccountPosition(key, to) + + } + onSetVisibilityRequested: function (key, toVisibility) { + priv.showcaseModels.setAccountVisibility(key, toVisibility) + } } // collectibles ProfileShowcaseCollectiblesPanel { id: profileShowcaseCollectiblesPanel - baseModel: root.profileStore.collectiblesModel - showcaseModel: root.profileStore.profileShowcaseCollectiblesModel - addAccountsButtonVisible: root.profileStore.profileShowcaseAccountsModel.hiddenCount > 0 - onShowcaseEntryChanged: priv.hasAnyProfileShowcaseChanges = true + addAccountsButtonVisible: priv.showcaseModels.accountsHiddenModel > 0 onNavigateToAccountsTab: profileTabBar.currentIndex = MyProfileView.TabIndex.Accounts + inShowcaseModel: priv.showcaseModels.collectiblesVisibleModel + hiddenModel: priv.showcaseModels.collectiblesHiddenModel + onChangePositionRequested: function (key, to) { + priv.showcaseModels.changeCollectiblePosition(key, to) + } + onSetVisibilityRequested: function (key, toVisibility) { + priv.showcaseModels.setCollectibleVisibility(key, toVisibility) + } } // web diff --git a/ui/imports/shared/controls/EmptyShapeRectangleFooterListView.qml b/ui/imports/shared/controls/EmptyShapeRectangleFooterListView.qml index c3ef835501..8ec46ea02e 100644 --- a/ui/imports/shared/controls/EmptyShapeRectangleFooterListView.qml +++ b/ui/imports/shared/controls/EmptyShapeRectangleFooterListView.qml @@ -15,10 +15,9 @@ StatusListView { property bool footerContentVisible: true property Component additionalFooterComponent - // TO BE REMOVE: #13498 - property bool empty: root.model && root.count === 0 - ScrollBar.vertical: null + footerPositioning: ListView.PullBackFooter + footer: ColumnLayout { width: root.width @@ -27,7 +26,7 @@ StatusListView { Layout.preferredHeight: root.footerHeight Layout.fillWidth: true - visible: root.empty// TO BE REPLACE root.empty in (#13498): root.empty = root.model && root.count === 0 + visible: root.model && root.count === 0 ShapeRectangle { id: shapeRectangle