feat(wallet) connect assets ordering with saving to DB backend

Also refactor the existing code based on the latest understanding.

Closes #13312
This commit is contained in:
Stefan 2024-04-05 19:39:08 +03:00 committed by Stefan Dunca
parent 25906ffa34
commit 473e2e273f
12 changed files with 76 additions and 50 deletions

View File

@ -32,10 +32,6 @@ QtObject:
proc updateCollectiblePreferences*(self: View, collectiblePreferencesJson: string) {.slot.} =
self.delegate.updateCollectiblePreferences(collectiblePreferencesJson)
proc clearCollectiblePreferences*(self: View) {.slot.} =
# There is no requirements of clearing the preferences yet but controller is expected to expose it
discard
proc getCollectiblePreferencesJson(self: View): QVariant {.slot.} =
let preferences = self.delegate.getCollectiblePreferencesJson()
return newQVariant(preferences)

View File

@ -146,11 +146,11 @@ QtObject:
proc updateTokenPreferences*(self: View, tokenPreferencesJson: string) {.slot.} =
self.delegate.updateTokenPreferences(tokenPreferencesJson)
proc getTokenPreferencesJson(self: View): QVariant {.slot.} =
proc getTokenPreferencesJson(self: View): string {.slot.} =
let preferences = self.delegate.getTokenPreferencesJson()
return newQVariant(preferences)
return preferences
QtProperty[QVariant] tokenPreferencesJson:
QtProperty[string] tokenPreferencesJson:
read = getTokenPreferencesJson
proc tokenGroupByCommunityChanged*(self: View) {.signal.}

View File

@ -524,6 +524,7 @@ QtObject:
if preferencesJson.kind == JArray:
for preferences in preferencesJson:
add(tokenPreferences, fromJson(preferences, TokenPreferences))
let response = backend.updateTokenPreferences(tokenPreferences)
if not response.error.isNil:
raise newException(CatchableError, response.error.message)

View File

@ -26,6 +26,7 @@ StatusRoundedComponent {
StatusImage {
id: image
anchors.fill: parent
anchors.margins: parent.border.width
}

View File

@ -102,7 +102,7 @@ SerializedTokenData ManageTokensModel::save(bool isVisible, bool itemsAreGroups)
token.communityId,
isCollectionGroup,
token.collectionUid,
tokenDataToCollectiblePreferencesItemType(token, isCommunityGroup, itemsAreGroups)});
tokenDataToCollectiblePreferencesItemType(isCommunityGroup, itemsAreGroups)});
}
setDirty(false);
return result;

View File

@ -5,7 +5,10 @@
#include <QJsonObject>
#include <QList>
CollectiblePreferencesItemType tokenDataToCollectiblePreferencesItemType(const TokenData& token, bool isCommunity, bool itemsAreGroups)
// This is used by he collectibles to deconflict types saved. However, the UX ignores them on restore/load
// and relies on the fact that all identities ("key" in backend and "symbol" in frontend) are unique between all
// types
CollectiblePreferencesItemType tokenDataToCollectiblePreferencesItemType(bool isCommunity, bool itemsAreGroups)
{
if (itemsAreGroups) {
if (isCommunity) {
@ -22,6 +25,28 @@ CollectiblePreferencesItemType tokenDataToCollectiblePreferencesItemType(const T
}
}
struct GroupingInfo {
bool isCommunity = false;
bool itemsAreGroups = false;
};
GroupingInfo collectiblePreferencesItemTypeToGroupsInfo(CollectiblePreferencesItemType type)
{
switch (type) {
case CollectiblePreferencesItemType::Community:
return {true /* isCommunity */, true /*itemsAreGroups*/};
case CollectiblePreferencesItemType::Collection:
return {false /* isCommunity */, true /*itemsAreGroups*/};
case CollectiblePreferencesItemType::CommunityCollectible:
return {true /* isCommunity */, false /*itemsAreGroups*/};
case CollectiblePreferencesItemType::NonCommunityCollectible:
return {false /* isCommunity */, false /*itemsAreGroups*/};
default:
qFatal("Unknown collectible type");
return {false, false};
}
}
TokenOrder::TokenOrder() : sortOrder(undefinedTokenOrder) {}
TokenOrder::TokenOrder(const QString& symbol,
@ -53,25 +78,27 @@ QString tokenOrdersToJson(const SerializedTokenData& dataList, bool areCollectib
QJsonArray jsonArray;
for (const TokenOrder& data : dataList) {
QJsonObject obj;
// The collectibles group ordering is handled in the backend.
obj["key"] = data.symbol;
obj["position"] = data.sortOrder;
obj["visible"] = data.visible;
if (data.isCommunityGroup) {
obj["isCommunityGroup"] = true;
obj["communityId"] = data.communityId;
}
if (data.isCollectionGroup) {
obj["isCollectionGroup"] = true;
obj["collectionUid"] = data.collectionUid;
}
if (areCollectible) {
// ignore communityId and collectionId which are embedded in key for collectibles
// ignore isCommunityGroup and isCollectionGroup that are embedded in type for collectibles
// by providing the required separation of groups and collectibles which are not yet used
// see CollectiblePreferences in src/backend/collectibles_types.nim
// type cover separation of groups and collectibles
obj["type"] = static_cast<int>(data.type);
} else { // is asset
// We ignore isCollectionGroup that doesn't exist for assets
// see TokenPreferences in src/backend/backend.nim
// TODO #13312: handle "groupPosition" for asset
// isCommunityGroup is true only if communityId is valid
if (data.isCommunityGroup) {
obj["groupPosition"] = data.sortOrder;
obj["communityId"] = data.communityId;
}
}
jsonArray.append(obj);
}
@ -100,21 +127,24 @@ SerializedTokenData tokenOrdersFromJson(const QString& json_string, bool areColl
data.symbol = obj["key"].toString();
data.sortOrder = obj["position"].toInt();
data.visible = obj["visible"].toBool();
if (obj.contains("isCommunityGroup")) {
data.isCommunityGroup = obj["isCommunityGroup"].toBool();
data.communityId = obj["communityId"].toString();
}
if (obj.contains("isCollectionGroup")) {
data.isCollectionGroup = obj["isCollectionGroup"].toBool();
data.collectionUid = obj["collectionUid"].toString();
}
if (areCollectibles) {
// see CollectiblePreferences in src/backend/collectibles_types.nim
data.type = static_cast<CollectiblePreferencesItemType>(obj["type"].toInt());
auto groupingInfo = collectiblePreferencesItemTypeToGroupsInfo(data.type);
data.isCommunityGroup = groupingInfo.isCommunity;
if (data.isCommunityGroup) {
data.communityId = data.symbol;
}
data.isCollectionGroup = groupingInfo.itemsAreGroups;
if (data.isCollectionGroup) {
data.collectionUid = data.symbol;
}
} else { // is asset
// see TokenPreferences in src/backend/backend.nim
// TODO #13312: handle "groupPosition" for assets
if (obj.contains("groupPosition")) {
data.isCommunityGroup = true;
data.communityId = obj["communityId"].toString();
}
}
dataList.insert(data.symbol, data);

View File

@ -19,7 +19,7 @@ struct TokenData {
// mirrors CollectiblePreferencesItemType from src/backend/collectibles_types.nim
enum class CollectiblePreferencesItemType { NonCommunityCollectible = 1, CommunityCollectible, Collection, Community };
CollectiblePreferencesItemType tokenDataToCollectiblePreferencesItemType(const TokenData& tokenData, bool isCommunity, bool itemsAreGroups);
CollectiblePreferencesItemType tokenDataToCollectiblePreferencesItemType(bool isCommunity, bool itemsAreGroups);
struct TokenOrder {
QString symbol;
@ -47,7 +47,8 @@ struct TokenOrder {
{
return symbol == rhs.symbol && sortOrder == rhs.sortOrder && visible == rhs.visible &&
isCommunityGroup == rhs.isCommunityGroup && (!isCommunityGroup || communityId == rhs.communityId) &&
isCollectionGroup == rhs.isCollectionGroup && (!isCollectionGroup || collectionUid == rhs.collectionUid) && type == rhs.type;
isCollectionGroup == rhs.isCollectionGroup &&
(!isCollectionGroup || collectionUid == rhs.collectionUid) && type == rhs.type;
}
QString getGroupId() const { return !communityId.isEmpty() ? communityId : collectionUid; }

View File

@ -319,7 +319,7 @@ SettingsContentBase {
inShowcaseModel: priv.showcaseModels.accountsVisibleModel
hiddenModel: priv.showcaseModels.accountsHiddenModel
showcaseLimit: root.profileStore.getProfileShowcaseEntriesLimit()
currentWallet: root.walletStore.overview.mixedcaseAddress
currentWallet: RootStore.overview.mixedcaseAddress
onChangePositionRequested: function (from, to) {
priv.showcaseModels.changeAccountPosition(from, to)

View File

@ -289,7 +289,7 @@ SettingsContentBase {
userProfilePublicKey: walletStore.userProfilePublicKey
onGoBack: stackContainer.currentIndex = mainViewIndex
onVisibleChanged: {
if (!visible) {
if (!visible && !!root.walletStore) {
root.walletStore.selectedAccount = null
keyPair = null
}

View File

@ -41,11 +41,6 @@ QtObject {
let jsonData = _allCollectiblesModule.getCollectiblePreferencesJson()
loadingFinished(jsonData)
}
onRequestClearSettings: {
savingStarted()
_allCollectiblesModule.clearCollectiblePreferences()
savingFinished()
}
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
qsTr("%1 community collectibles successfully hidden").arg(communityName), "", "checkmark-circle",

View File

@ -136,4 +136,12 @@ QtObject {
root.displayAssetsBelowBalanceThresholdChanged()
}
}
function updateTokenPreferences(jsonData) {
root._allTokensModule.updateTokenPreferences(jsonData)
}
function getTokenPreferencesJson(jsonData) {
return root._allTokensModule.getTokenPreferencesJson(jsonData)
}
}

View File

@ -20,21 +20,15 @@ QtObject {
settingsKey: "WalletAssets"
serializeAsCollectibles: false
// TODO #13312: call the assets controller for all events
onRequestSaveSettings: (jsonData) => {
// savingStarted()
saveToQSettings(jsonData)
// savingFinished()
savingStarted()
walletTokensStore.updateTokenPreferences(jsonData)
savingFinished()
}
onRequestLoadSettings: {
// loadingStarted()
loadFromQSettings()
// loadingFinished()
}
onRequestClearSettings: {
// savingStarted()
clearQSettings()
// savingFinished()
loadingStarted()
let jsonData = walletTokensStore.getTokenPreferencesJson()
loadingFinished(jsonData)
}
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(