feat(Manage Tokens): implement "Arrange by collection"

- simplify the delegates (no more nested inner models/ListViews)
- persist the "Arrange by" toggles state (when needed)
- adjust the tests

Fixes #13232
This commit is contained in:
Lukáš Tinkl 2024-01-19 10:53:32 +01:00 committed by Lukáš Tinkl
parent 57b3b254b8
commit d7e25ea0a7
20 changed files with 423 additions and 339 deletions

View File

@ -74,12 +74,12 @@ SplitView {
}
Button {
enabled: showcasePanel.dirty
text: "Save"
onClicked: showcasePanel.saveSettings()
}
Button {
enabled: showcasePanel.dirty
text: "Revert"
onClicked: showcasePanel.revert()
}

View File

@ -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"

View File

@ -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()
}
}
}
}

View File

@ -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)
}
}
}

View File

@ -1,8 +1,6 @@
import QtQuick 2.15
import QtQml.Models 2.15
import Models 1.0
ListModel {
property bool includeRegularCollectibles: true
onIncludeRegularCollectiblesChanged: fillData()

View File

@ -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

View File

@ -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

View File

@ -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<QString, std::tuple<int, bool, QString>> 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<QColor>();
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<TokenData> 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<TokenData> 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;

View File

@ -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<ManageTokensModel*, 6> m_allModels {m_regularTokensModel, m_regularTokenGroupsModel, m_communityTokensModel, m_communityTokenGroupsModel, m_hiddenTokensModel,
m_hiddenCommunityTokenGroupsModel};
const std::array<ManageTokensModel*, 7> 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<QString> m_hiddenCommunityGroups;
QStringList hiddenCommunityGroups() const;
QSet<QString> m_hiddenCollectionGroups;
QStringList hiddenCollectionGroups() const;
};

View File

@ -54,14 +54,14 @@ std::optional<TokenData> ManageTokensModel::takeItem(const QString& symbol)
return res;
}
QList<TokenData> ManageTokensModel::takeAllItems(const QString& communityId)
QList<TokenData> ManageTokensModel::takeAllItems(const QString& groupId)
{
QList<TokenData> result;
QList<int> 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) {

View File

@ -72,7 +72,7 @@ public:
void addItem(const TokenData& item, bool append = true);
std::optional<TokenData> takeItem(const QString& symbol);
QList<TokenData> takeAllItems(const QString& communityId);
QList<TokenData> 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<int, QByteArray> roleNames() const override;

View File

@ -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"
}
]

View File

@ -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)
}
}

View File

@ -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()
}
}

View File

@ -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()
}
}
}

View File

@ -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)
}

View File

@ -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("Youll 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
}
}
}

View File

@ -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
}
}

View File

@ -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
}

View File

@ -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) {