diff --git a/storybook/pages/ManageAssetsPanelPage.qml b/storybook/pages/ManageAssetsPanelPage.qml index 979f2ba7bb..652b189c57 100644 --- a/storybook/pages/ManageAssetsPanelPage.qml +++ b/storybook/pages/ManageAssetsPanelPage.qml @@ -74,12 +74,12 @@ SplitView { } Button { + enabled: showcasePanel.dirty text: "Save" onClicked: showcasePanel.saveSettings() } Button { - enabled: showcasePanel.dirty text: "Revert" onClicked: showcasePanel.revert() } diff --git a/storybook/pages/ManageCollectiblesPanelPage.qml b/storybook/pages/ManageCollectiblesPanelPage.qml index 15dad889e5..c67c7260fd 100644 --- a/storybook/pages/ManageCollectiblesPanelPage.qml +++ b/storybook/pages/ManageCollectiblesPanelPage.qml @@ -69,25 +69,16 @@ SplitView { } Button { + enabled: showcasePanel.dirty text: "Save" onClicked: showcasePanel.saveSettings() } Button { - enabled: showcasePanel.dirty text: "Revert" onClicked: showcasePanel.revert() } - Button { - enabled: false - text: "Random data (TODO)" - onClicked: { - collectiblesModel.clear() - collectiblesModel.randomizeData() - } - } - Button { enabled: showcasePanel.hasSettings text: "Clear settings" diff --git a/storybook/pages/ManageHiddenPanelPage.qml b/storybook/pages/ManageHiddenPanelPage.qml index 217f9b0199..9fcd0de6c2 100644 --- a/storybook/pages/ManageHiddenPanelPage.qml +++ b/storybook/pages/ManageHiddenPanelPage.qml @@ -95,6 +95,13 @@ SplitView { Label { text: assetsController.hiddenCommunityGroups.concat(collectiblesController.hiddenCommunityGroups).join() } + + Label { + text: "Hidden collection groups:" + } + Label { + text: assetsController.hiddenCollectionGroups.concat(collectiblesController.hiddenCollectionGroups).join() + } } } } diff --git a/storybook/qmlTests/tests/tst_ManageCollectiblesPanel.qml b/storybook/qmlTests/tests/tst_ManageCollectiblesPanel.qml index 3e02718202..92a3539135 100644 --- a/storybook/qmlTests/tests/tst_ManageCollectiblesPanel.qml +++ b/storybook/qmlTests/tests/tst_ManageCollectiblesPanel.qml @@ -1,5 +1,4 @@ import QtQuick 2.15 -import QtQuick.Controls 2.15 import QtTest 1.15 import StatusQ 0.1 @@ -7,7 +6,6 @@ import StatusQ.Models 0.1 import AppLayouts.Wallet.panels 1.0 -import Storybook 1.0 import Models 1.0 import utils 1.0 @@ -34,7 +32,6 @@ Item { Component { id: componentUnderTest ManageCollectiblesPanel { - id: showcasePanel width: 500 controller: ManageTokensController { sourceModel: renamedModel @@ -99,7 +96,7 @@ Item { notificationSpy.clear() } - function test_showHideToken() { + function test_showHideSingleToken() { verify(!controlUnderTest.dirty) const lvRegular = findChild(controlUnderTest, "lvRegularTokens") @@ -111,7 +108,7 @@ Item { verify(!!delegate0) const title = delegate0.title tryCompare(notificationSpy, "count", 0) - triggerDelegateMenuAction(lvRegular, 0, "miHideToken") + triggerDelegateMenuAction(lvRegular, 0, "miHideCollectionToken") // verify the signal to show the notification toast got fired tryCompare(notificationSpy, "count", 1) @@ -173,10 +170,6 @@ Item { verify(!!switchArrangeByCommunity) mouseClick(switchArrangeByCommunity) - const switchCollapseCommunityGroups = findChild(controlUnderTest, "switchCollapseCommunityGroups") - verify(!!switchCollapseCommunityGroups) - mouseClick(switchCollapseCommunityGroups) - const loaderCommunityTokens = findChild(controlUnderTest, "loaderCommunityTokens") verify(!!loaderCommunityTokens) tryCompare(loaderCommunityTokens, "active", true) @@ -225,18 +218,6 @@ Item { verify(!!bearzGroupTokenDelegate) waitForItemPolished(bearzGroupTokenDelegate) - // get the Bearz child listview - const bearzChildLV = findChild(bearzGroupTokenDelegate, "manageTokensGroupListView") - verify(!!bearzChildLV) - - // find the 2385 delegate from the Bearz group and hide it - const bear2385DelegateIdx = findDelegateIndexWithTitle(bearzChildLV, "KILLABEAR #2385") - verify(bear2385DelegateIdx !== -1) - tryCompare(notificationSpy, "count", 0) - triggerDelegateMenuAction(bearzChildLV, bear2385DelegateIdx, "miHideCommunityToken") - // verify the signal to show the notification toast got fired - tryCompare(notificationSpy, "count", 1) - // now move the Bearz group up so that it's first (ends up at index 0) waitForItemPolished(lvCommunityTokenGroups) triggerDelegateMenuAction(lvCommunityTokenGroups, 1, "miMoveUp", true) @@ -244,16 +225,6 @@ Item { bearzGroupTokenDelegate = findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-0") verify(!!bearzGroupTokenDelegate) - // get one of the other group's (Pandas) tokens and hide it - const pandasGroupTokenDelegate = findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-1") - verify(!!pandasGroupTokenDelegate) - const pandasChildLV = findChild(pandasGroupTokenDelegate, "manageTokensGroupListView") - verify(!!pandasChildLV) - const panda909DelegateIdx = findDelegateIndexWithTitle(pandasChildLV, "Frenly Panda #909") - triggerDelegateMenuAction(pandasChildLV, panda909DelegateIdx, "miHideCommunityToken") - // verify the signal to show the notification toast got fired - tryCompare(notificationSpy, "count", 2) - // finally verify that the Bearz group is still at top waitForItemPolished(lvCommunityTokenGroups) tryCompare(findChild(lvCommunityTokenGroups, "manageTokensGroupDelegate-0"), "title", titleToTest) @@ -278,7 +249,6 @@ Item { // trigger move to bottom triggerDelegateMenuAction(lvRegular, 0, "miMoveToBottom") - waitForItemPolished(lvRegular) verify(controlUnderTest.dirty) @@ -309,14 +279,10 @@ Item { } function test_saveLoad() { - // start with clear settings - controlUnderTest.clearSettings() - controlUnderTest.revert() - verify(!controlUnderTest.dirty) const titleToTest = "Big Kitty" - const lvRegular = findChild(controlUnderTest, "lvRegularTokens") + let lvRegular = findChild(controlUnderTest, "lvRegularTokens") verify(!!lvRegular) const bigKittyIndex = findDelegateIndexWithTitle(lvRegular, titleToTest) verify(bigKittyIndex !== -1) @@ -337,8 +303,13 @@ Item { // load the settings and check BigKitty is still on top controlUnderTest.revert() verify(!controlUnderTest.dirty) + lvRegular = findChild(controlUnderTest, "lvRegularTokens") + verify(!!lvRegular) waitForItemPolished(lvRegular) - tryCompare(findChild(lvRegular, "manageTokensDelegate-0"), "title", titleToTest) + tryVerify(() => lvRegular.count > 0) + const topItem = findChild(lvRegular, "manageTokensDelegate-0") + verify(!!topItem) + tryCompare(topItem, "title", titleToTest) } } } diff --git a/storybook/src/Models/ManageCollectiblesModel.qml b/storybook/src/Models/ManageCollectiblesModel.qml index a2155dc13d..cf1c97d3ac 100644 --- a/storybook/src/Models/ManageCollectiblesModel.qml +++ b/storybook/src/Models/ManageCollectiblesModel.qml @@ -1,8 +1,6 @@ import QtQuick 2.15 import QtQml.Models 2.15 -import Models 1.0 - ListModel { property bool includeRegularCollectibles: true onIncludeRegularCollectiblesChanged: fillData() diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusRadioButton.qml b/ui/StatusQ/src/StatusQ/Controls/StatusRadioButton.qml index 37ad541965..74ce744e37 100644 --- a/ui/StatusQ/src/StatusQ/Controls/StatusRadioButton.qml +++ b/ui/StatusQ/src/StatusQ/Controls/StatusRadioButton.qml @@ -23,6 +23,7 @@ RadioButton { opacity: enabled ? 1.0 : 0.3 font.family: Theme.palette.baseFont.name + font.pixelSize: Theme.primaryTextFontSize indicator: Rectangle { implicitWidth: root.size === StatusRadioButton.Size.Large ? 20 : 14 diff --git a/ui/StatusQ/src/StatusQ/Controls/StatusSwitch.qml b/ui/StatusQ/src/StatusQ/Controls/StatusSwitch.qml index 5daef05b8c..4a2cf76b09 100644 --- a/ui/StatusQ/src/StatusQ/Controls/StatusSwitch.qml +++ b/ui/StatusQ/src/StatusQ/Controls/StatusSwitch.qml @@ -10,6 +10,9 @@ Switch { property color textColor: Theme.palette.directColor1 + font.family: Theme.palette.baseFont.name + font.pixelSize: Theme.primaryTextFontSize + background: MouseArea { cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor acceptedButtons: Qt.NoButton @@ -75,6 +78,7 @@ Switch { text: root.text opacity: enabled ? 1.0 : 0.3 color: root.textColor + font: root.font verticalAlignment: Text.AlignVCenter leftPadding: root.mirrored ? 0 : !!root.text ? root.indicator.width + root.spacing : root.indicator.width rightPadding: root.mirrored ? !!root.text ? root.indicator.width + root.spacing : root.indicator.width : 0 diff --git a/ui/StatusQ/src/wallet/managetokenscontroller.cpp b/ui/StatusQ/src/wallet/managetokenscontroller.cpp index 991b705165..b9d2758c27 100644 --- a/ui/StatusQ/src/wallet/managetokenscontroller.cpp +++ b/ui/StatusQ/src/wallet/managetokenscontroller.cpp @@ -6,11 +6,12 @@ ManageTokensController::ManageTokensController(QObject* parent) : QObject(parent) , m_regularTokensModel(new ManageTokensModel(this)) - , m_regularTokenGroupsModel(new ManageTokensModel(this)) + , m_collectionGroupsModel(new ManageTokensModel(this)) , m_communityTokensModel(new ManageTokensModel(this)) , m_communityTokenGroupsModel(new ManageTokensModel(this)) , m_hiddenTokensModel(new ManageTokensModel(this)) , m_hiddenCommunityTokenGroupsModel(new ManageTokensModel(this)) + , m_hiddenCollectionGroupsModel(new ManageTokensModel(this)) { for (auto model : m_allModels) { connect(model, &ManageTokensModel::dirtyChanged, this, &ManageTokensController::dirtyChanged); @@ -31,12 +32,18 @@ ManageTokensController::ManageTokensController(QObject* parent) #endif for (int i = first; i <= last; i++) addItem(i); - reloadCommunityIds(); - m_communityTokensModel->setCommunityIds(m_communityIds); - m_communityTokensModel->saveCustomSortOrder(); + rebuildCommunityTokenGroupsModel(); rebuildHiddenCommunityTokenGroupsModel(); - rebuildRegularTokenGroupsModel(); + reloadCommunityIds(); + m_communityTokensModel->setCommunityIds(m_communityIds); + rebuildCollectionGroupsModel(); + rebuildHiddenCollectionGroupsModel(); + + for (auto model: m_allModels) { + model->applySort(); + model->saveCustomSortOrder(); + } #ifdef QT_DEBUG qCDebug(manageTokens) << "!!! ADDING NEW SOURCE DATA TOOK" << t.nsecsElapsed()/1'000'000.f << "ms"; #endif @@ -51,7 +58,7 @@ ManageTokensController::ManageTokensController(QObject* parent) m_communityTokensModel->saveCustomSortOrder(); }); connect(m_communityTokenGroupsModel, &ManageTokensModel::rowsMoved, this, [this](const QModelIndex &parent, int start, int end, const QModelIndex &destination, int toRow) { - qCDebug(manageTokens) << "!!! GROUP MOVED FROM" << start << "TO" << toRow; + qCDebug(manageTokens) << "!!! COMMUNITY GROUP MOVED FROM" << start << "TO" << toRow; reloadCommunityIds(); m_communityTokensModel->setCommunityIds(m_communityIds); m_communityTokensModel->saveCustomSortOrder(); @@ -131,21 +138,46 @@ void ManageTokensController::showHideGroup(const QString& groupId, bool flag) emit hiddenCommunityGroupsChanged(); } } - m_communityTokensModel->setCommunityIds(m_communityIds); - m_communityTokensModel->saveCustomSortOrder(); rebuildCommunityTokenGroupsModel(); rebuildHiddenCommunityTokenGroupsModel(); } +void ManageTokensController::showHideCollectionGroup(const QString& groupId, bool flag) +{ + if (flag) { // show + const auto tokens = m_hiddenTokensModel->takeAllItems(groupId); + if (!tokens.isEmpty()) { + for (const auto& token: tokens) { + m_regularTokensModel->addItem(token); + } + emit collectionTokenGroupShown(tokens.constFirst().collectionName); + } + if (m_hiddenCollectionGroups.remove(groupId)) { + emit hiddenCollectionGroupsChanged(); + } + } else { // hide + const auto tokens = m_regularTokensModel->takeAllItems(groupId); + if (!tokens.isEmpty()) { + for (const auto& token: tokens) { + m_hiddenTokensModel->addItem(token, false /*prepend*/); + } + emit collectionTokenGroupHidden(tokens.constFirst().collectionName); + } + if (!m_hiddenCollectionGroups.contains(groupId)) { + m_hiddenCollectionGroups.insert(groupId); + emit hiddenCollectionGroupsChanged(); + } + } + rebuildCollectionGroupsModel(); + rebuildHiddenCollectionGroupsModel(); +} + void ManageTokensController::saveSettings(bool reuseCurrent) { Q_ASSERT(!m_settingsKey.isEmpty()); setSettingsDirty(true); - if (m_arrangeByCommunity) - m_communityTokensModel->applySort(); - // gather the data to save SerializedTokenData result; if (reuseCurrent) { @@ -159,6 +191,11 @@ void ManageTokensController::saveSettings(bool reuseCurrent) // save to QSettings m_settings.beginGroup(settingsGroupName()); + // arrange by + m_settings.setValue(QStringLiteral("ArrangeByCommunity"), m_arrangeByCommunity); + m_settings.setValue(QStringLiteral("ArrangeByCollection"), m_arrangeByCollection); + + // data m_settings.beginWriteArray(m_settingsKey); SerializedTokenData::const_key_value_iterator it = result.constKeyValueBegin(); for (auto i = 0; it != result.constKeyValueEnd() && i < result.size(); it++, i++) { @@ -171,8 +208,9 @@ void ManageTokensController::saveSettings(bool reuseCurrent) } m_settings.endArray(); - // hidden community groups + // hidden groups m_settings.setValue(QStringLiteral("HiddenCommunityGroups"), hiddenCommunityGroups()); + m_settings.setValue(QStringLiteral("HiddenCollectionGroups"), hiddenCollectionGroups()); m_settings.endGroup(); m_settings.sync(); @@ -206,6 +244,7 @@ void ManageTokensController::loadSettings() // load from QSettings m_settings.beginGroup(settingsGroupName()); + const auto size = m_settings.beginReadArray(m_settingsKey); for (auto i = 0; i < size; i++) { m_settings.setArrayIndex(i); @@ -221,12 +260,21 @@ void ManageTokensController::loadSettings() } m_settings.endArray(); - // hidden community groups + // hidden groups const auto groups = m_settings.value(QStringLiteral("HiddenCommunityGroups")).toStringList(); if (!groups.isEmpty()) { m_hiddenCommunityGroups = {groups.constBegin(), groups.constEnd()}; emit hiddenCommunityGroupsChanged(); } + const auto collections = m_settings.value(QStringLiteral("HiddenCollectionGroups")).toStringList(); + if (!collections.isEmpty()) { + m_hiddenCollectionGroups = {collections.constBegin(), collections.constEnd()}; + emit hiddenCollectionGroupsChanged(); + } + + // arrange by + setArrangeByCommunity(m_settings.value(QStringLiteral("ArrangeByCommunity"), false).toBool()); + setArrangeByCollection(m_settings.value(QStringLiteral("ArrangeByCollection"), false).toBool()); m_settings.endGroup(); setSettingsDirty(false); @@ -244,6 +292,11 @@ QStringList ManageTokensController::hiddenCommunityGroups() const return {m_hiddenCommunityGroups.constBegin(), m_hiddenCommunityGroups.constEnd()}; } +QStringList ManageTokensController::hiddenCollectionGroups() const +{ + return {m_hiddenCollectionGroups.constBegin(), m_hiddenCollectionGroups.constEnd()}; +} + void ManageTokensController::revert() { parseSourceModel(); @@ -274,22 +327,21 @@ void ManageTokensController::settingsHideToken(const QString& symbol) saveSettings(true); } -void ManageTokensController::settingsHideCommunityTokens(const QString& communityId, const QStringList& symbols) +void ManageTokensController::settingsHideGroupTokens(const QString& groupId, const QStringList& symbols) { QMutableHashIterator> i(m_settingsData); bool found = false; while (i.hasNext()) { i.next(); - const auto groupID = std::get<2>(i.value()); - if (groupID == communityId) { + if (groupId == std::get<2>(i.value())) { found = true; - i.setValue({0, false, communityId}); + i.setValue({0, false, groupId}); } } if (!found) { for (const auto& symbol: symbols) - m_settingsData.insert(symbol, {0, false, communityId}); + m_settingsData.insert(symbol, {0, false, groupId}); } saveSettings(true); @@ -339,6 +391,9 @@ void ManageTokensController::setSourceModel(QAbstractItemModel* newSourceModel) model->clear(); m_settingsData.clear(); m_communityIds.clear(); + m_hiddenCommunityGroups.clear(); + m_hiddenCollectionGroups.clear(); + setSettingsDirty(false); m_sourceModel = newSourceModel; emit sourceModelChanged(); return; @@ -372,8 +427,6 @@ void ManageTokensController::parseSourceModel() // clear all the models for (auto model: m_allModels) model->clear(); - m_communityIds.clear(); - m_hiddenCommunityGroups.clear(); // load settings loadSettings(); @@ -392,7 +445,8 @@ void ManageTokensController::parseSourceModel() m_communityTokensModel->setCommunityIds(m_communityIds); // build collections - rebuildRegularTokenGroupsModel(); + rebuildCollectionGroupsModel(); + rebuildHiddenCollectionGroupsModel(); // (pre)sort for (auto model: m_allModels) { @@ -426,7 +480,6 @@ void ManageTokensController::addItem(int index) const auto visible = m_settingsData.contains(symbol) ? std::get<1>(m_settingsData.value(symbol)) : true; const auto bgColor = dataForIndex(srcIndex, kBackgroundColorRoleName).value(); const auto collectionUid = dataForIndex(srcIndex, kCollectionUidRoleName).toString(); - const auto collectionName = dataForIndex(srcIndex, kCollectionNameRoleName).toString(); TokenData token; token.symbol = symbol; @@ -437,8 +490,8 @@ void ManageTokensController::addItem(int index) token.communityId = communityId; token.communityName = !communityName.isEmpty() ? communityName : communityId; token.communityImage = dataForIndex(srcIndex, kCommunityImageRoleName).toString(); - token.collectionUid = collectionUid; - token.collectionName = !collectionName.isEmpty() ? collectionName : collectionUid; + token.collectionUid = !collectionUid.isEmpty() ? collectionUid : symbol; + token.collectionName = dataForIndex(srcIndex, kCollectionNameRoleName).toString(); token.balance = dataForIndex(srcIndex, kEnabledNetworkBalanceRoleName); token.currencyBalance = dataForIndex(srcIndex, kEnabledNetworkCurrencyBalanceRoleName); token.balances = dataForIndex(srcIndex, kBalancesRoleName); @@ -472,13 +525,31 @@ void ManageTokensController::setArrangeByCommunity(bool newArrangeByCommunity) { if(m_arrangeByCommunity == newArrangeByCommunity) return; m_arrangeByCommunity = newArrangeByCommunity; - if (!m_arrangeByCommunity) - m_communityTokensModel->applySort(); - else + if (m_arrangeByCommunity) { rebuildCommunityTokenGroupsModel(); + m_communityTokenGroupsModel->applySortByTokensAmount(); + m_communityTokenGroupsModel->setDirty(true); + } emit arrangeByCommunityChanged(); } +bool ManageTokensController::arrangeByCollection() const +{ + return m_arrangeByCollection; +} + +void ManageTokensController::setArrangeByCollection(bool newArrangeByCollection) +{ + if(m_arrangeByCollection == newArrangeByCollection) return; + m_arrangeByCollection = newArrangeByCollection; + if (m_arrangeByCollection) { + rebuildCollectionGroupsModel(); + m_collectionGroupsModel->applySortByTokensAmount(); + m_collectionGroupsModel->setDirty(true); + } + emit arrangeByCollectionChanged(); +} + void ManageTokensController::reloadCommunityIds() { m_communityIds.clear(); @@ -568,7 +639,7 @@ void ManageTokensController::rebuildHiddenCommunityTokenGroupsModel() qCDebug(manageTokens) << "!!! HIDDEN GROUPS MODEL REBUILT WITH GROUPS:" << communityIds; } -void ManageTokensController::rebuildRegularTokenGroupsModel() +void ManageTokensController::rebuildCollectionGroupsModel() { QStringList collectionIds; QList result; @@ -576,15 +647,15 @@ void ManageTokensController::rebuildRegularTokenGroupsModel() const auto count = m_regularTokensModel->count(); for (auto i = 0; i < count; i++) { const auto& collectionToken = m_regularTokensModel->itemAt(i); - const auto collectionId = collectionToken.collectionUid; - if (collectionId.isEmpty()) - continue; + auto collectionId = collectionToken.collectionUid; if (!collectionIds.contains(collectionId)) { // insert into groups collectionIds.append(collectionId); + const auto collectionName = !collectionToken.collectionName.isEmpty() ? collectionToken.collectionName : collectionToken.name; + TokenData tokenGroup; tokenGroup.collectionUid = collectionId; - tokenGroup.collectionName = collectionToken.collectionName; + tokenGroup.collectionName = collectionName; tokenGroup.image = collectionToken.image; tokenGroup.balance = 1; result.append(tokenGroup); @@ -600,13 +671,52 @@ void ManageTokensController::rebuildRegularTokenGroupsModel() } } - m_regularTokenGroupsModel->clear(); + m_collectionGroupsModel->clear(); for (const auto& group: std::as_const(result)) - m_regularTokenGroupsModel->addItem(group); + m_collectionGroupsModel->addItem(group); qCDebug(manageTokens) << "!!! COLLECTION MODEL REBUILT WITH GROUPS:" << collectionIds; } +void ManageTokensController::rebuildHiddenCollectionGroupsModel() +{ + QStringList collectionIds; + QList result; + + const auto count = m_hiddenTokensModel->count(); + for (auto i = 0; i < count; i++) { + const auto& collectionToken = m_hiddenTokensModel->itemAt(i); + auto collectionId = collectionToken.collectionUid; + if (!collectionIds.contains(collectionId) && m_hiddenCollectionGroups.contains(collectionId)) { // insert into groups + collectionIds.append(collectionId); + + const auto collectionName = !collectionToken.collectionName.isEmpty() ? collectionToken.collectionName : collectionToken.name; + + TokenData tokenGroup; + tokenGroup.collectionUid = collectionId; + tokenGroup.collectionName = collectionName; + tokenGroup.image = collectionToken.image; + tokenGroup.balance = 1; + result.append(tokenGroup); + } else { // update group's childCount + const auto tokenGroup = std::find_if(result.cbegin(), result.cend(), [collectionId](const auto& item) { + return collectionId == item.collectionUid; + }); + if (tokenGroup != result.cend()) { + const auto row = std::distance(result.cbegin(), tokenGroup); + TokenData& updTokenGroup = result[row]; + updTokenGroup.balance = updTokenGroup.balance.toInt() + 1; + } + } + } + + m_hiddenCollectionGroupsModel->clear(); + for (const auto& group: std::as_const(result)) + m_hiddenCollectionGroupsModel->addItem(group); + + qCDebug(manageTokens) << "!!! HIDDEN COLLECTION GROUPS MODEL REBUILT WITH GROUPS:" << collectionIds; +} + QString ManageTokensController::settingsKey() const { return m_settingsKey; diff --git a/ui/StatusQ/src/wallet/managetokenscontroller.h b/ui/StatusQ/src/wallet/managetokenscontroller.h index 262c19e5d2..aea5206ef6 100644 --- a/ui/StatusQ/src/wallet/managetokenscontroller.h +++ b/ui/StatusQ/src/wallet/managetokenscontroller.h @@ -16,19 +16,21 @@ class ManageTokensController : public QObject, public QQmlParserStatus // input properties Q_PROPERTY(QAbstractItemModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged FINAL) Q_PROPERTY(QString settingsKey READ settingsKey WRITE setSettingsKey NOTIFY settingsKeyChanged FINAL REQUIRED) - Q_PROPERTY(bool arrangeByCommunity READ arrangeByCommunity WRITE setArrangeByCommunity NOTIFY arrangeByCommunityChanged FINAL) // TODO persist in settings? - // TODO arrangeByCollection for collectibles + + Q_PROPERTY(bool arrangeByCommunity READ arrangeByCommunity WRITE setArrangeByCommunity NOTIFY arrangeByCommunityChanged FINAL) + Q_PROPERTY(bool arrangeByCollection READ arrangeByCollection WRITE setArrangeByCollection NOTIFY arrangeByCollectionChanged FINAL) // output properties Q_PROPERTY(QAbstractItemModel* regularTokensModel READ regularTokensModel CONSTANT FINAL) - Q_PROPERTY(QAbstractItemModel* regularTokenGroupsModel READ regularTokenGroupsModel CONSTANT FINAL) + Q_PROPERTY(QAbstractItemModel* collectionGroupsModel READ collectionGroupsModel CONSTANT FINAL) Q_PROPERTY(QAbstractItemModel* communityTokensModel READ communityTokensModel CONSTANT FINAL) Q_PROPERTY(QAbstractItemModel* communityTokenGroupsModel READ communityTokenGroupsModel CONSTANT FINAL) Q_PROPERTY(QAbstractItemModel* hiddenTokensModel READ hiddenTokensModel CONSTANT FINAL) - // TODO track hidden collection groups Q_PROPERTY(QStringList hiddenCommunityGroups READ hiddenCommunityGroups NOTIFY hiddenCommunityGroupsChanged FINAL) Q_PROPERTY(QAbstractItemModel* hiddenCommunityTokenGroupsModel READ hiddenCommunityTokenGroupsModel CONSTANT FINAL) + Q_PROPERTY(QStringList hiddenCollectionGroups READ hiddenCollectionGroups NOTIFY hiddenCollectionGroupsChanged FINAL) + Q_PROPERTY(QAbstractItemModel* hiddenCollectionGroupsModel READ hiddenCollectionGroupsModel CONSTANT FINAL) Q_PROPERTY(bool dirty READ dirty NOTIFY dirtyChanged FINAL) Q_PROPERTY(bool hasSettings READ hasSettings NOTIFY settingsDirtyChanged FINAL) @@ -40,6 +42,7 @@ public: Q_INVOKABLE void showHideRegularToken(const QString& symbol, bool flag); Q_INVOKABLE void showHideCommunityToken(const QString& symbol, bool flag); Q_INVOKABLE void showHideGroup(const QString& groupId, bool flag); + Q_INVOKABLE void showHideCollectionGroup(const QString& groupId, bool flag); Q_INVOKABLE void loadSettings(); Q_INVOKABLE void saveSettings(bool reuseCurrent = false); @@ -47,8 +50,7 @@ public: Q_INVOKABLE void revert(); Q_INVOKABLE void settingsHideToken(const QString& symbol); - Q_INVOKABLE void settingsHideCommunityTokens(const QString& communityId, const QStringList& symbols); - // TODO settingHideCollectionTokens + Q_INVOKABLE void settingsHideGroupTokens(const QString& groupId, const QStringList& symbols); Q_INVOKABLE bool lessThan(const QString& lhsSymbol, const QString& rhsSymbol) const; Q_INVOKABLE bool filterAcceptsSymbol(const QString& symbol) const; @@ -61,6 +63,7 @@ signals: void sourceModelChanged(); void dirtyChanged(); void arrangeByCommunityChanged(); + void arrangeByCollectionChanged(); void settingsKeyChanged(); void settingsDirtyChanged(bool dirty); @@ -68,9 +71,11 @@ signals: void tokenShown(const QString& symbol, const QString& name); void communityTokenGroupHidden(const QString& communityName); void communityTokenGroupShown(const QString& communityName); - // TODO collectionTokenGroupHidden(const QString& collectionName); + void collectionTokenGroupHidden(const QString& communityName); + void collectionTokenGroupShown(const QString& communityName); void hiddenCommunityGroupsChanged(); + void hiddenCollectionGroupsChanged(); private: QAbstractItemModel* m_sourceModel{nullptr}; @@ -83,8 +88,8 @@ private: ManageTokensModel* m_regularTokensModel{nullptr}; QAbstractItemModel* regularTokensModel() const { return m_regularTokensModel; } - ManageTokensModel* m_regularTokenGroupsModel{nullptr}; - QAbstractItemModel* regularTokenGroupsModel() const { return m_regularTokenGroupsModel; } + ManageTokensModel* m_collectionGroupsModel{nullptr}; + QAbstractItemModel* collectionGroupsModel() const { return m_collectionGroupsModel; } ManageTokensModel* m_communityTokensModel{nullptr}; QAbstractItemModel* communityTokensModel() const { return m_communityTokensModel; } @@ -98,20 +103,28 @@ private: ManageTokensModel* m_hiddenCommunityTokenGroupsModel{nullptr}; QAbstractItemModel* hiddenCommunityTokenGroupsModel() const { return m_hiddenCommunityTokenGroupsModel; } + ManageTokensModel* m_hiddenCollectionGroupsModel{nullptr}; + QAbstractItemModel* hiddenCollectionGroupsModel() const { return m_hiddenCollectionGroupsModel; } + bool dirty() const; bool m_arrangeByCommunity{false}; bool arrangeByCommunity() const; void setArrangeByCommunity(bool newArrangeByCommunity); + bool m_arrangeByCollection{false}; + bool arrangeByCollection() const; + void setArrangeByCollection(bool newArrangeByCollection); + QStringList m_communityIds; void reloadCommunityIds(); void rebuildCommunityTokenGroupsModel(); void rebuildHiddenCommunityTokenGroupsModel(); - void rebuildRegularTokenGroupsModel(); + void rebuildCollectionGroupsModel(); + void rebuildHiddenCollectionGroupsModel(); - const std::array m_allModels {m_regularTokensModel, m_regularTokenGroupsModel, m_communityTokensModel, m_communityTokenGroupsModel, m_hiddenTokensModel, - m_hiddenCommunityTokenGroupsModel}; + const std::array m_allModels {m_regularTokensModel, m_collectionGroupsModel, m_communityTokensModel, m_communityTokenGroupsModel, + m_hiddenTokensModel, m_hiddenCommunityTokenGroupsModel, m_hiddenCollectionGroupsModel}; QString m_settingsKey; QString settingsKey() const; @@ -130,4 +143,7 @@ private: // explicitely mass-hidden community asset/collectible groups QSet m_hiddenCommunityGroups; QStringList hiddenCommunityGroups() const; + + QSet m_hiddenCollectionGroups; + QStringList hiddenCollectionGroups() const; }; diff --git a/ui/StatusQ/src/wallet/managetokensmodel.cpp b/ui/StatusQ/src/wallet/managetokensmodel.cpp index e55f072288..89529861ab 100644 --- a/ui/StatusQ/src/wallet/managetokensmodel.cpp +++ b/ui/StatusQ/src/wallet/managetokensmodel.cpp @@ -54,14 +54,14 @@ std::optional ManageTokensModel::takeItem(const QString& symbol) return res; } -QList ManageTokensModel::takeAllItems(const QString& communityId) +QList ManageTokensModel::takeAllItems(const QString& groupId) { QList result; QList indexesToRemove; for (int i = 0; i < m_data.count(); i++) { const auto &token = m_data.at(i); - if (token.communityId == communityId) { + if (token.communityId == groupId || token.collectionUid == groupId) { result.append(token); indexesToRemove.append(i); } @@ -198,6 +198,18 @@ void ManageTokensModel::applySort() emit layoutChanged({}, QAbstractItemModel::VerticalSortHint); } +void ManageTokensModel::applySortByTokensAmount() +{ + emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint); + + // clazy:exclude=clazy-detaching-member + std::stable_sort(m_data.begin(), m_data.end(), [this](const TokenData& lhs, const TokenData& rhs) { + return lhs.balance.toLongLong() > rhs.balance.toLongLong(); + }); + + emit layoutChanged({}, QAbstractItemModel::VerticalSortHint); +} + bool ManageTokensModel::hasCommunityIdToken(const QString& communityId) const { return std::any_of(m_data.cbegin(), m_data.constEnd(), [communityId](const auto& token) { diff --git a/ui/StatusQ/src/wallet/managetokensmodel.h b/ui/StatusQ/src/wallet/managetokensmodel.h index f6c4fa5de7..2aa7a62cfe 100644 --- a/ui/StatusQ/src/wallet/managetokensmodel.h +++ b/ui/StatusQ/src/wallet/managetokensmodel.h @@ -72,7 +72,7 @@ public: void addItem(const TokenData& item, bool append = true); std::optional takeItem(const QString& symbol); - QList takeAllItems(const QString& communityId); + QList takeAllItems(const QString& groupId); void clear(); SerializedTokenData save(bool isVisible = true); @@ -82,13 +82,14 @@ public: void saveCustomSortOrder(); void applySort(); + void applySortByTokensAmount(); int count() const { return rowCount(); } const TokenData& itemAt(int row) const { return m_data.at(row); } TokenData& itemAt(int row) { return m_data[row]; } - void setCommunityIds(const QStringList& ids) { m_communityIds = ids; }; - bool hasCommunityIdToken(const QString& communityId) const; + void setCommunityIds(const QStringList& ids) { m_communityIds = ids; }; // FIXME remove; sort by number of tokens inside + bool hasCommunityIdToken(const QString& communityId) const; // FIXME remove int rowCount(const QModelIndex &parent = QModelIndex()) const override; QHash roleNames() const override; diff --git a/ui/app/AppLayouts/Wallet/controls/FilterComboBox.qml b/ui/app/AppLayouts/Wallet/controls/FilterComboBox.qml index abdd33e698..bed729098d 100644 --- a/ui/app/AppLayouts/Wallet/controls/FilterComboBox.qml +++ b/ui/app/AppLayouts/Wallet/controls/FilterComboBox.qml @@ -19,7 +19,7 @@ ComboBox { id: root required property var regularTokensModel // "uncategorized" collectibles (not grouped) - required property var regularTokenGroupsModel // collection groups + required property var collectionGroupsModel // collection groups required property var communityTokenGroupsModel // community groups property bool hasCommunityGroups @@ -57,7 +57,7 @@ ComboBox { markerRoleValue: "community" }, SourceModel { - model: root.regularTokenGroupsModel + model: root.collectionGroupsModel markerRoleValue: "collection" } ] diff --git a/ui/app/AppLayouts/Wallet/controls/ManageTokenMenuButton.qml b/ui/app/AppLayouts/Wallet/controls/ManageTokenMenuButton.qml index bd2d3a4fbd..c9e32795a8 100644 --- a/ui/app/AppLayouts/Wallet/controls/ManageTokenMenuButton.qml +++ b/ui/app/AppLayouts/Wallet/controls/ManageTokenMenuButton.qml @@ -15,8 +15,9 @@ StatusFlatButton { property bool inHidden property bool isGroup + property bool isCollection property string groupId - property bool isCommunityAsset + property bool isCommunityToken property bool isCollectible readonly property bool hideEnabled: model.symbol !== "ETH" @@ -78,7 +79,7 @@ StatusFlatButton { // any token StatusAction { objectName: "miHideToken" - enabled: !root.inHidden && root.hideEnabled && !root.isGroup && !root.isCommunityAsset + enabled: !root.inHidden && root.hideEnabled && !root.isGroup && !root.isCommunityToken && !root.isCollectible type: StatusAction.Type.Danger icon.name: "hide" text: root.isCollectible ? qsTr("Hide collectible") : qsTr("Hide asset") @@ -95,7 +96,7 @@ StatusFlatButton { // (hide) community tokens StatusMenu { id: communitySubmenu - enabled: !root.inHidden && root.isCommunityAsset + enabled: !root.inHidden && root.isCommunityToken title: qsTr("Hide") assetSettings.name: "hide" type: StatusAction.Type.Danger @@ -118,20 +119,56 @@ StatusFlatButton { } } + // (hide) collection tokens + StatusMenu { + id: collectionSubmenu + enabled: !root.inHidden && root.isCollectible && !root.isCommunityToken && !root.isGroup + title: qsTr("Hide") + assetSettings.name: "hide" + type: StatusAction.Type.Danger + + StatusAction { + objectName: "miHideCollectionToken" + text: qsTr("This collectible") + onTriggered: { + root.showHideRequested(model.symbol, false) + communitySubmenu.dismiss() + } + } + StatusAction { + objectName: "miHideAllCollectionTokens" + text: qsTr("All collectibles from this collection") + onTriggered: { + root.showHideGroupRequested(root.groupId, false) + communitySubmenu.dismiss() + } + } + } + // token group StatusAction { objectName: "miHideTokenGroup" enabled: !root.inHidden && root.isGroup type: StatusAction.Type.Danger icon.name: "hide" - text: root.isCollectible ? qsTr("Hide all collectibles from this community") : qsTr("Hide all assets from this community") + text: { + if (root.isCollection) + return qsTr("Hide all collectibles from this collection") + return root.isCollectible ? qsTr("Hide all collectibles from this community") + : qsTr("Hide all assets from this community") + } onTriggered: root.showHideGroupRequested(root.groupId, false) } StatusAction { objectName: "miShowTokenGroup" enabled: root.inHidden && root.groupId icon.name: "show" - text: root.isCollectible ? qsTr("Show all collectibles from this community") : qsTr("Show all assets from this community") + text: { + if (root.isCollection) + return qsTr("Show all collectibles from this collection") + return root.isCollectible ? qsTr("Show all collectibles from this community") + : qsTr("Show all assets from this community") + } onTriggered: root.showHideGroupRequested(root.groupId, true) } } diff --git a/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml b/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml index baec946d40..597e984d17 100644 --- a/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml +++ b/ui/app/AppLayouts/Wallet/controls/ManageTokensDelegate.qml @@ -14,23 +14,21 @@ DropArea { id: root objectName: "manageTokensDelegate-%1".arg(index) - // expected roles: symbol, name, communityId, communityName, communityImage, collectionName, imageUrl - // enabledNetworkCurrencyBalance -> TODO might get dropped/renamed in the future!!! + // expected roles: symbol, name, communityId, communityName, communityImage, collectionUid, collectionName, imageUrl + // + enabledNetworkBalance, enabledNetworkCurrencyBalance property var controller property int visualIndex: index property alias dragParent: delegate.dragParent property alias dragEnabled: delegate.dragEnabled property alias bgColor: delegate.bgColor - property alias topInset: delegate.topInset - property alias bottomInset: delegate.bottomInset - property bool isGrouped property bool isHidden // inside the "Hidden" section property int count property bool isCollectible readonly property alias title: delegate.title readonly property var balances: model.balances + readonly property bool isCommunityToken: !!model.communityId readonly property var priv: QtObject { id: priv @@ -47,6 +45,7 @@ DropArea { PropertyAction { target: root; property: "ListView.delayRemove"; value: false } } + keys: isCommunityToken ? ["x-status-draggable-community-token-item"] : ["x-status-draggable-regular-token-item"] width: ListView.view ? ListView.view.width : 0 height: visible ? delegate.height : 0 @@ -71,8 +70,10 @@ DropArea { width: root.width title: model.name + readonly property var totalBalance: aggregator.value/(10 ** model.decimals) - secondaryTitle: root.isCollectible ? (!!model.communityId ? qsTr("Community minted") : model.collectionName || model.symbol) : + + secondaryTitle: root.isCollectible ? (root.isCommunityToken ? qsTr("Community minted") : model.collectionName || model.collectionUid) : hovered || menuBtn.menuVisible ? "%1 • %2".arg(LocaleUtils.currencyAmountToLocaleString(root.getCurrencyAmount(totalBalance, model.symbol))) .arg(!model.communityId ? LocaleUtils.currencyAmountToLocaleString(root.getCurrentCurrencyAmount(totalBalance * model.marketDetails.currencyPrice.amount)): LocaleUtils.currencyAmountToLocaleString(root.getCurrentCurrencyAmount(0))) @@ -88,7 +89,7 @@ DropArea { actions: [ ManageTokensCommunityTag { Layout.maximumWidth: delegate.width *.4 - visible: !!model.communityId && !root.isGrouped + visible: !!model.communityId text: model.communityName asset.name: model && !!model.communityImage ? model.communityImage : "" }, @@ -98,19 +99,22 @@ DropArea { currentIndex: root.visualIndex count: root.count inHidden: root.isHidden - groupId: model.communityId - isCommunityAsset: !!model.communityId + groupId: model.communityId || model.collectionUid + isCommunityToken: root.isCommunityToken isCollectible: root.isCollectible onMoveRequested: (from, to) => root.ListView.view.model.moveItem(from, to) onShowHideRequested: function(symbol, flag) { - if (isCommunityAsset) + if (isCommunityToken) root.controller.showHideCommunityToken(symbol, flag) else root.controller.showHideRegularToken(symbol, flag) root.controller.saveSettings() } onShowHideGroupRequested: function(groupId, flag) { - root.controller.showHideGroup(groupId, flag) + if (isCommunityToken) + root.controller.showHideGroup(groupId, flag) + else + root.controller.showHideCollectionGroup(groupId, flag) root.controller.saveSettings() } } diff --git a/ui/app/AppLayouts/Wallet/controls/ManageTokensGroupDelegate.qml b/ui/app/AppLayouts/Wallet/controls/ManageTokensGroupDelegate.qml index 0e3918f5bd..a8badabe52 100644 --- a/ui/app/AppLayouts/Wallet/controls/ManageTokensGroupDelegate.qml +++ b/ui/app/AppLayouts/Wallet/controls/ManageTokensGroupDelegate.qml @@ -13,18 +13,18 @@ DropArea { id: root objectName: "manageTokensGroupDelegate-%1".arg(index) - // expected roles: communityId, communityName, communityImage + // expected roles: communityId, communityName, communityImage, collectionUid, collectionName, imageUrl // FIXME unify group image property int visualIndex: index property var controller - property bool communityGroupsExpanded property var dragParent property alias dragEnabled: groupedCommunityTokenDelegate.dragEnabled - property bool isCollectible + property bool isCollectible: isCollection + property bool isCollection property bool isHidden // inside the "Hidden" section - readonly property string communityId: model.communityId - readonly property int childCount: model.enabledNetworkBalance // NB using "balance" as "count" in m_communityTokenGroupsModel + readonly property string groupId: isCollection ? model.collectionUid : model.communityId + readonly property int childCount: model.enabledNetworkBalance // NB using "balance" as "count" in the grouped model readonly property alias title: groupedCommunityTokenDelegate.title property var getCurrencyAmount: function (balance, symbol) {} @@ -36,7 +36,7 @@ DropArea { PropertyAction { target: root; property: "ListView.delayRemove"; value: false } } - keys: ["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 height: visible ? groupedCommunityTokenDelegate.implicitHeight : 0 @@ -53,11 +53,10 @@ DropArea { id: groupedCommunityTokenDelegate width: parent.width height: dragActive ? implicitHeight : parent.height - horizontalPadding: root.isHidden ? 0 : Style.current.halfPadding draggable: true spacing: 12 bgColor: Theme.palette.baseColor4 - title: model.communityName + title: root.isCollection ? model.collectionName : model.communityName visualIndex: index dragParent: root.dragParent @@ -65,94 +64,59 @@ DropArea { Drag.hotSpot.x: root.width/2 Drag.hotSpot.y: root.height/2 - contentItem: ColumnLayout { - spacing: 12 + contentItem: RowLayout { + spacing: groupedCommunityTokenDelegate.spacing - RowLayout { - Layout.fillWidth: true - Layout.leftMargin: 12 - Layout.rightMargin: 12 - spacing: groupedCommunityTokenDelegate.spacing - - StatusIcon { - Layout.preferredWidth: 20 - Layout.preferredHeight: 20 - icon: "justify" - color: root.dragEnabled ? Theme.palette.baseColor1 : Theme.palette.baseColor2 - } - - StatusRoundedImage { - //radius: groupedCommunityTokenDelegate.bgRadius // TODO different for a collection - Layout.preferredWidth: root.isCollectible ? 44 : 32 - Layout.preferredHeight: root.isCollectible ? 44 : 32 - image.source: model.communityImage - showLoadingIndicator: true - image.fillMode: Image.PreserveAspectCrop - } - - StatusBaseText { - text: groupedCommunityTokenDelegate.title - elide: Text.ElideRight - maximumLineCount: 1 - font.weight: Font.Medium - } - - Item { Layout.fillWidth: true } - - ManageTokensCommunityTag { - text: root.childCount - asset.name: root.isCollectible ? "image" : "token" - asset.isImage: false - asset.color: Theme.palette.baseColor1 - enabled: false - } - - ManageTokenMenuButton { - objectName: "btnManageTokenMenu-%1".arg(currentIndex) - currentIndex: visualIndex - count: root.controller.communityTokenGroupsModel.count // FIXME collection - isGroup: true - isCollectible: root.isCollectible - groupId: model.communityId - inHidden: root.isHidden - onMoveRequested: (from, to) => root.controller.communityTokenGroupsModel.moveItem(from, to) // FIXME collection - onShowHideGroupRequested: function(groupId, flag) { - root.controller.showHideGroup(groupId, flag) - root.controller.saveSettings() - } - } + StatusIcon { + Layout.preferredWidth: 20 + Layout.preferredHeight: 20 + icon: "justify" + color: root.dragEnabled ? Theme.palette.baseColor1 : Theme.palette.baseColor2 } - StatusListView { - objectName: "manageTokensGroupListView" - Layout.fillWidth: true - Layout.preferredHeight: contentHeight - model: root.controller.communityTokensModel - interactive: false - visible: root.communityGroupsExpanded && !root.isHidden + StatusRoundedImage { + radius: root.isCollection ? Style.current.radius : height/2 + Layout.preferredWidth: root.isCollectible ? 44 : 32 + Layout.preferredHeight: root.isCollectible ? 44 : 32 + image.source: root.isCollection ? model.imageUrl : model.communityImage // FIXME unify group image + showLoadingIndicator: true + image.fillMode: Image.PreserveAspectCrop + } - displaced: Transition { - NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } - } + StatusBaseText { + text: groupedCommunityTokenDelegate.title + elide: Text.ElideRight + maximumLineCount: 1 + font.weight: Font.Medium + } - delegate: ManageTokensDelegate { - controller: root.controller - dragParent: root.dragParent - isGrouped: true - count: root.childCount - dragEnabled: count > 1 - keys: ["x-status-draggable-community-token-item-%1".arg(model.communityId)] - bgColor: Theme.palette.indirectColor4 - topInset: 2 // tighter "spacing" - bottomInset: 2 - visible: root.communityId === model.communityId - isCollectible: root.isCollectible - getCurrencyAmount: function (balance, symbol) { - return root.getCurrencyAmount(balance, symbol) - } - getCurrentCurrencyAmount: function (balance) { - return root.getCurrentCurrencyAmount(balance) - } + Item { Layout.fillWidth: true } + + ManageTokensCommunityTag { + text: root.childCount + asset.name: root.isCollectible ? "image" : "token" + asset.isImage: false + asset.color: Theme.palette.baseColor1 + enabled: false + } + + ManageTokenMenuButton { + objectName: "btnManageTokenMenu-%1".arg(currentIndex) + currentIndex: visualIndex + count: root.isCollection ? root.controller.collectionGroupsModel.count : + root.controller.communityTokenGroupsModel.count + isGroup: true + isCollection: root.isCollection + isCollectible: root.isCollectible + groupId: root.groupId + inHidden: root.isHidden + onMoveRequested: (from, to) => root.ListView.view.model.moveItem(from, to) + onShowHideGroupRequested: function(groupId, flag) { + if (root.isCollection) + root.controller.showHideCollectionGroup(groupId, flag) + else + root.controller.showHideGroup(groupId, flag) + root.controller.saveSettings() } } } diff --git a/ui/app/AppLayouts/Wallet/panels/ManageAssetsPanel.qml b/ui/app/AppLayouts/Wallet/panels/ManageAssetsPanel.qml index 866a38c5bb..81836791db 100644 --- a/ui/app/AppLayouts/Wallet/panels/ManageAssetsPanel.qml +++ b/ui/app/AppLayouts/Wallet/panels/ManageAssetsPanel.qml @@ -6,7 +6,6 @@ import StatusQ.Core 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 -import StatusQ.Popups 0.1 import StatusQ.Models 0.1 import utils 1.0 @@ -38,17 +37,6 @@ Control { root.controller.clearSettings(); } - QtObject { - id: d - - property bool communityGroupsExpanded: true - } - - Binding { - target: controller - property: "arrangeByCommunity" - value: switchArrangeByCommunity.checked - } contentItem: ColumnLayout { spacing: Style.current.padding @@ -68,7 +56,6 @@ Control { dragParent: root count: root.controller.regularTokensModel.count dragEnabled: count > 1 - keys: ["x-status-draggable-token-item"] getCurrencyAmount: function (balance, symbol) { return root.getCurrencyAmount(balance, symbol) } @@ -79,39 +66,25 @@ Control { } RowLayout { - id: communityTokensHeader Layout.fillWidth: true Layout.topMargin: Style.current.padding visible: root.controller.communityTokensModel.count StatusBaseText { - color: Theme.palette.baseColor1 + Layout.fillWidth: true text: qsTr("Community") } - Item { Layout.fillWidth: true } StatusSwitch { LayoutMirroring.enabled: true LayoutMirroring.childrenInherit: true id: switchArrangeByCommunity textColor: Theme.palette.baseColor1 + font.pixelSize: 13 text: qsTr("Arrange by community") + checked: root.controller.arrangeByCommunity + onToggled: root.controller.arrangeByCommunity = checked } } - StatusModalDivider { - Layout.fillWidth: true - Layout.topMargin: -Style.current.halfPadding - visible: communityTokensHeader.visible && switchArrangeByCommunity.checked - } - - StatusLinkText { - Layout.alignment: Qt.AlignTrailing - visible: communityTokensHeader.visible && switchArrangeByCommunity.checked - text: d.communityGroupsExpanded ? qsTr("Collapse all") : qsTr("Expand all") - normalColor: linkColor - font.weight: Font.Normal - onClicked: d.communityGroupsExpanded = !d.communityGroupsExpanded - } - Loader { Layout.fillWidth: true active: root.controller.communityTokensModel.count @@ -136,7 +109,6 @@ Control { dragParent: root count: root.controller.communityTokensModel.count dragEnabled: count > 1 - keys: ["x-status-draggable-community-token-item"] getCurrencyAmount: function (balance, symbol) { return root.getCurrencyAmount(balance, symbol) } @@ -153,7 +125,6 @@ Control { model: root.controller.communityTokenGroupsModel implicitHeight: contentHeight interactive: false - spacing: Style.current.halfPadding displaced: Transition { NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } @@ -163,7 +134,6 @@ Control { controller: root.controller dragParent: root dragEnabled: root.controller.communityTokenGroupsModel.count > 1 - communityGroupsExpanded: d.communityGroupsExpanded getCurrencyAmount: function (balance, symbol) { return root.getCurrencyAmount(balance, symbol) } diff --git a/ui/app/AppLayouts/Wallet/panels/ManageCollectiblesPanel.qml b/ui/app/AppLayouts/Wallet/panels/ManageCollectiblesPanel.qml index 6c547fb8b5..466f6b22fa 100644 --- a/ui/app/AppLayouts/Wallet/panels/ManageCollectiblesPanel.qml +++ b/ui/app/AppLayouts/Wallet/panels/ManageCollectiblesPanel.qml @@ -7,7 +7,6 @@ import StatusQ.Core 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 -import StatusQ.Popups 0.1 import StatusQ.Models 0.1 import utils 1.0 @@ -37,112 +36,37 @@ Control { root.controller.clearSettings(); } - QtObject { - id: d - - //property bool collectionGroupsExpanded: true - property bool communityGroupsExpanded: true - } - - Binding { - target: controller - property: "arrangeByCommunity" - value: switchArrangeByCommunity.checked - } - contentItem: ColumnLayout { spacing: Style.current.padding ShapeRectangle { Layout.fillWidth: true Layout.margins: 2 - visible: !root.controller.regularTokensModel.count + visible: !root.controller.regularTokensModel.count && !root.controller.communityTokensModel.count text: qsTr("You’ll be able to manage the display of your collectibles here") } -// TODO https://github.com/status-im/status-desktop/issues/12703 -// StatusSwitch { -// Layout.alignment: Qt.AlignTrailing -// LayoutMirroring.enabled: true -// LayoutMirroring.childrenInherit: true -// id: switchArrangeByCollection -// textColor: Theme.palette.baseColor1 -// text: qsTr("Arrange by collection") -// visible: root.controller.regularTokensModel.count -// } - -// StatusModalDivider { -// Layout.fillWidth: true -// Layout.topMargin: -Style.current.halfPadding -// visible: switchArrangeByCollection.visible && switchArrangeByCollection.checked -// } - -// StatusLinkText { -// Layout.alignment: Qt.AlignTrailing -// visible: switchArrangeByCollection.visible && switchArrangeByCollection.checked -// text: d.collectionGroupsExpanded ? qsTr("Collapse all") : qsTr("Expand all") -// normalColor: linkColor -// font.weight: Font.Normal -// onClicked: d.collectionGroupsExpanded = !d.collectionGroupsExpanded -// } - - StatusListView { - objectName: "lvRegularTokens" - Layout.fillWidth: true - model: root.controller.regularTokensModel - implicitHeight: contentHeight - interactive: false - - displaced: Transition { - NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } - } - - delegate: ManageTokensDelegate { - isCollectible: true - controller: root.controller - dragParent: root - count: root.controller.regularTokensModel.count - dragEnabled: count > 1 - keys: ["x-status-draggable-token-item"] - } - } - RowLayout { - id: communityTokensHeader Layout.fillWidth: true Layout.topMargin: Style.current.padding visible: root.controller.communityTokensModel.count StatusBaseText { - color: Theme.palette.baseColor1 - text: qsTr("Community") + Layout.fillWidth: true + text: qsTr("Community minted") } - Item { Layout.fillWidth: true } StatusSwitch { objectName: "switchArrangeByCommunity" LayoutMirroring.enabled: true LayoutMirroring.childrenInherit: true id: switchArrangeByCommunity textColor: Theme.palette.baseColor1 + font.pixelSize: 13 text: qsTr("Arrange by community") + checked: root.controller.arrangeByCommunity + onToggled: root.controller.arrangeByCommunity = checked } } - StatusModalDivider { - Layout.fillWidth: true - Layout.topMargin: -Style.current.halfPadding - visible: communityTokensHeader.visible && switchArrangeByCommunity.checked - } - - StatusLinkText { - objectName: "switchCollapseCommunityGroups" - Layout.alignment: Qt.AlignTrailing - visible: communityTokensHeader.visible && switchArrangeByCommunity.checked - text: d.communityGroupsExpanded ? qsTr("Collapse all") : qsTr("Expand all") - normalColor: linkColor - font.weight: Font.Normal - onClicked: d.communityGroupsExpanded = !d.communityGroupsExpanded - } - Loader { objectName: "loaderCommunityTokens" Layout.fillWidth: true @@ -150,6 +74,34 @@ Control { visible: active sourceComponent: switchArrangeByCommunity.checked ? cmpCommunityTokenGroups : cmpCommunityTokens } + + RowLayout { + Layout.fillWidth: true + Layout.topMargin: Style.current.padding + visible: root.controller.regularTokensModel.count + StatusBaseText { + Layout.fillWidth: true + text: qsTr("Other") + } + StatusSwitch { + LayoutMirroring.enabled: true + LayoutMirroring.childrenInherit: true + id: switchArrangeByCollection + textColor: Theme.palette.baseColor1 + font.pixelSize: 13 + text: qsTr("Arrange by collection") + checked: root.controller.arrangeByCollection + onToggled: root.controller.arrangeByCollection = checked + } + } + + Loader { + objectName: "loaderRegularTokens" + Layout.fillWidth: true + active: root.controller.regularTokensModel.count + visible: active + sourceComponent: switchArrangeByCollection.checked ? cmpCollectionTokenGroups : cmpRegularTokens + } } Component { @@ -170,7 +122,6 @@ Control { dragParent: root count: root.controller.communityTokensModel.count dragEnabled: count > 1 - keys: ["x-status-draggable-community-token-item"] } } } @@ -182,7 +133,6 @@ Control { model: root.controller.communityTokenGroupsModel implicitHeight: contentHeight interactive: false - spacing: Style.current.halfPadding displaced: Transition { NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } @@ -193,7 +143,49 @@ Control { controller: root.controller dragParent: root dragEnabled: root.controller.communityTokenGroupsModel.count > 1 - communityGroupsExpanded: d.communityGroupsExpanded + } + } + } + + Component { + id: cmpRegularTokens + StatusListView { + objectName: "lvRegularTokens" + model: root.controller.regularTokensModel + implicitHeight: contentHeight + interactive: false + + displaced: Transition { + NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } + } + + delegate: ManageTokensDelegate { + isCollectible: true + controller: root.controller + dragParent: root + count: root.controller.regularTokensModel.count + dragEnabled: count > 1 + } + } + } + + Component { + id: cmpCollectionTokenGroups + StatusListView { + objectName: "lvCollectionTokenGroups" + model: root.controller.collectionGroupsModel + implicitHeight: contentHeight + interactive: false + + displaced: Transition { + NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad } + } + + delegate: ManageTokensGroupDelegate { + isCollection: true + controller: root.controller + dragParent: root + dragEnabled: root.controller.collectionGroupsModel.count > 1 } } } diff --git a/ui/app/AppLayouts/Wallet/panels/ManageHiddenPanel.qml b/ui/app/AppLayouts/Wallet/panels/ManageHiddenPanel.qml index c97a0a3400..94cb89f8d3 100644 --- a/ui/app/AppLayouts/Wallet/panels/ManageHiddenPanel.qml +++ b/ui/app/AppLayouts/Wallet/panels/ManageHiddenPanel.qml @@ -57,14 +57,17 @@ Control { filters: FastExpressionFilter { expression: { root.collectiblesController.hiddenCommunityGroups - return !root.collectiblesController.hiddenCommunityGroups.includes(model.communityId) + root.collectiblesController.hiddenCollectionGroups + return !root.collectiblesController.hiddenCommunityGroups.includes(model.communityId) && + !root.collectiblesController.hiddenCollectionGroups.includes(model.collectionUid) } - expectedRoles: ["communityId"] + expectedRoles: ["communityId", "collectionUid"] } } readonly property var combinedModel: ConcatModel { sources: [ + // assets SourceModel { // single hidden assets (not belonging to a group) model: d.filteredHiddenAssets markerRoleValue: "asset" @@ -73,13 +76,18 @@ Control { model: root.assetsController.hiddenCommunityTokenGroupsModel markerRoleValue: "assetGroup" }, - SourceModel { // single hidden collectibles (not belonging to a group) + // collectibles + SourceModel { // single hidden collectibles (not belonging to any group) model: d.filteredHiddenCollectibles markerRoleValue: "collectible" }, SourceModel { // community collectible groups model: root.collectiblesController.hiddenCommunityTokenGroupsModel markerRoleValue: "collectibleGroup" + }, + SourceModel { // collectible collection groups + model: root.collectiblesController.hiddenCollectionGroupsModel + markerRoleValue: "collectibleCollectionGroup" } ] @@ -99,7 +107,6 @@ Control { expression: model.tokenType.endsWith("Group") expectedRoles: "tokenType" } - // TODO collection ] // TODO sort by recency/timestamp (newest first) } @@ -147,7 +154,6 @@ Control { controller: isCollectible ? root.collectiblesController : root.assetsController dragParent: null dragEnabled: false - keys: ["x-status-draggable-none"] isHidden: true } } @@ -156,10 +162,10 @@ Control { id: tokenGroupDelegate ManageTokensGroupDelegate { isCollectible: model.isCollectible + isCollection: model.tokenType === "collectibleCollectionGroup" controller: isCollectible ? root.collectiblesController : root.assetsController dragParent: null dragEnabled: false - keys: ["x-status-draggable-none"] isHidden: true } } diff --git a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml index 156d59b4d3..213fc2031b 100644 --- a/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml +++ b/ui/app/AppLayouts/Wallet/views/CollectiblesView.qml @@ -79,7 +79,7 @@ ColumnLayout { function hideAllCommunityTokens(communityId) { const tokenSymbols = ModelUtils.getAll(communityCollectiblesView.model, "symbol", "communityId", communityId) - d.controller.settingsHideCommunityTokens(communityId, tokenSymbols) + d.controller.settingsHideGroupTokens(communityId, tokenSymbols) } function containsAny(list, filterList) { @@ -184,7 +184,7 @@ ColumnLayout { FilterComboBox { id: cmbFilter regularTokensModel: d.controller.regularTokensModel - regularTokenGroupsModel: d.controller.regularTokenGroupsModel + collectionGroupsModel: d.controller.collectionGroupsModel communityTokenGroupsModel: d.controller.communityTokenGroupsModel hasCommunityGroups: d.hasCommunityCollectibles } diff --git a/ui/imports/shared/views/AssetsView.qml b/ui/imports/shared/views/AssetsView.qml index 8a7d2416af..d8ee69f62e 100644 --- a/ui/imports/shared/views/AssetsView.qml +++ b/ui/imports/shared/views/AssetsView.qml @@ -68,7 +68,7 @@ ColumnLayout { function hideAllCommunityTokens(communityId) { const tokenSymbols = ModelUtils.getAll(assetsListView.model, "symbol", "communityId", communityId) - d.controller.settingsHideCommunityTokens(communityId, tokenSymbols) + d.controller.settingsHideGroupTokens(communityId, tokenSymbols) } function getTotalBalance(balances, decimals) {