feat(@wallet): Sort account by position

This commit is contained in:
Anthony Laibe 2023-06-20 12:59:15 +01:00
parent a5ba253730
commit 31aca3ac35
19 changed files with 198 additions and 7 deletions

View File

@ -28,6 +28,9 @@ proc getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAcco
proc updateAccount*(self: Controller, address: string, accountName: string, colorId: string, emoji: string) = proc updateAccount*(self: Controller, address: string, accountName: string, colorId: string, emoji: string) =
discard self.walletAccountService.updateWalletAccount(address, accountName, colorId, emoji) discard self.walletAccountService.updateWalletAccount(address, accountName, colorId, emoji)
proc updateAccountPosition*(self: Controller, address: string, position: int) =
self.walletAccountService.updateWalletAccountPosition(address, position)
proc deleteAccount*(self: Controller, address: string) = proc deleteAccount*(self: Controller, address: string) =
self.walletAccountService.deleteAccount(address) self.walletAccountService.deleteAccount(address)

View File

@ -25,6 +25,9 @@ method refreshWalletAccounts*(self: AccessInterface) {.base.} =
method updateAccount*(self: AccessInterface, address: string, accountName: string, colorId: string, emoji: string) {.base.} = method updateAccount*(self: AccessInterface, address: string, accountName: string, colorId: string, emoji: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method updateAccountPosition*(self: AccessInterface, address: string, position: int) {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface # View Delegate Interface
# Delegate for the view must be declared here due to use of QtObject and multi # Delegate for the view must be declared here due to use of QtObject and multi
# inheritance, which is not well supported in Nim. # inheritance, which is not well supported in Nim.

View File

@ -6,6 +6,7 @@ export wallet_account_item
type type
Item* = ref object of WalletAccountItem Item* = ref object of WalletAccountItem
position: int
relatedAccounts: related_accounts_model.Model relatedAccounts: related_accounts_model.Model
proc initItem*( proc initItem*(
@ -17,7 +18,8 @@ proc initItem*(
emoji: string = "", emoji: string = "",
relatedAccounts: related_accounts_model.Model = nil, relatedAccounts: related_accounts_model.Model = nil,
keyUid: string = "", keyUid: string = "",
keycardAccount: bool = false keycardAccount: bool = false,
position: int = 0,
): Item = ): Item =
result = Item() result = Item()
result.WalletAccountItem.setup(name, result.WalletAccountItem.setup(name,
@ -28,6 +30,7 @@ proc initItem*(
path, path,
keyUid, keyUid,
keycardAccount) keycardAccount)
result.position = position
result.relatedAccounts = relatedAccounts result.relatedAccounts = relatedAccounts
proc `$`*(self: Item): string = proc `$`*(self: Item): string =
@ -38,3 +41,6 @@ proc `$`*(self: Item): string =
proc relatedAccounts*(self: Item): related_accounts_model.Model = proc relatedAccounts*(self: Item): related_accounts_model.Model =
return self.relatedAccounts return self.relatedAccounts
proc position*(self: Item): int =
return self.position

View File

@ -11,6 +11,7 @@ type
Emoji, Emoji,
RelatedAccounts, RelatedAccounts,
KeyUid, KeyUid,
Position,
QtObject: QtObject:
type type
@ -54,6 +55,7 @@ QtObject:
ModelRole.Emoji.int: "emoji", ModelRole.Emoji.int: "emoji",
ModelRole.RelatedAccounts.int: "relatedAccounts", ModelRole.RelatedAccounts.int: "relatedAccounts",
ModelRole.KeyUid.int: "keyUid", ModelRole.KeyUid.int: "keyUid",
ModelRole.Position.int: "position",
}.toTable }.toTable
@ -104,3 +106,5 @@ QtObject:
result = newQVariant(item.relatedAccounts()) result = newQVariant(item.relatedAccounts())
of ModelRole.KeyUid: of ModelRole.KeyUid:
result = newQVariant(item.keyUid()) result = newQVariant(item.keyUid())
of ModelRole.Position:
result = newQVariant(item.position())

View File

@ -104,6 +104,9 @@ method load*(self: Module) =
return return
self.refreshWalletAccounts() self.refreshWalletAccounts()
self.events.on(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED) do(e:Args):
self.refreshWalletAccounts()
self.controller.init() self.controller.init()
self.view.load() self.view.load()
@ -118,5 +121,8 @@ method viewDidLoad*(self: Module) =
method updateAccount*(self: Module, address: string, accountName: string, colorId: string, emoji: string) = method updateAccount*(self: Module, address: string, accountName: string, colorId: string, emoji: string) =
self.controller.updateAccount(address, accountName, colorId, emoji) self.controller.updateAccount(address, accountName, colorId, emoji)
method updateAccountPosition*(self: Module, address: string, position: int) =
self.controller.updateAccountPosition(address, position)
method deleteAccount*(self: Module, address: string) = method deleteAccount*(self: Module, address: string) =
self.controller.deleteAccount(address) self.controller.deleteAccount(address)

View File

@ -45,6 +45,9 @@ QtObject:
proc updateAccount(self: View, address: string, accountName: string, colorId: string, emoji: string) {.slot.} = proc updateAccount(self: View, address: string, accountName: string, colorId: string, emoji: string) {.slot.} =
self.delegate.updateAccount(address, accountName, colorId, emoji) self.delegate.updateAccount(address, accountName, colorId, emoji)
proc updateAccountPosition(self: View, address: string, position: int) {.slot.} =
self.delegate.updateAccountPosition(address, position)
proc onUpdatedAccount*(self: View, account: Item) = proc onUpdatedAccount*(self: View, account: Item) =
self.accounts.onUpdatedAccount(account) self.accounts.onUpdatedAccount(account)
self.keyPairModel.onUpdatedAccount(account.keyUid, account.address, account.name, account.colorId, account.emoji) self.keyPairModel.onUpdatedAccount(account.keyUid, account.address, account.name, account.colorId, account.emoji)

View File

@ -6,6 +6,7 @@ export wallet_account_item
type type
Item* = ref object of WalletAccountItem Item* = ref object of WalletAccountItem
position: int
createdAt: int createdAt: int
assetsLoading: bool assetsLoading: bool
currencyBalance: CurrencyAmount currencyBalance: CurrencyAmount
@ -20,6 +21,7 @@ proc initItem*(
emoji: string = "", emoji: string = "",
keyUid: string = "", keyUid: string = "",
createdAt: int = 0, createdAt: int = 0,
position: int = 0,
keycardAccount: bool = false, keycardAccount: bool = false,
assetsLoading: bool = true, assetsLoading: bool = true,
): Item = ): Item =
@ -33,6 +35,7 @@ proc initItem*(
keyUid, keyUid,
keycardAccount) keycardAccount)
result.createdAt = createdAt result.createdAt = createdAt
result.position = position
result.assetsLoading = assetsLoading result.assetsLoading = assetsLoading
result.currencyBalance = currencyBalance result.currencyBalance = currencyBalance
@ -51,3 +54,6 @@ proc assetsLoading*(self: Item): bool =
proc createdAt*(self: Item): int = proc createdAt*(self: Item): int =
return self.createdAt return self.createdAt
proc position*(self: Item): int =
return self.position

View File

@ -15,6 +15,7 @@ type
Emoji, Emoji,
KeyUid, KeyUid,
CreatedAt, CreatedAt,
Position,
KeycardAccount, KeycardAccount,
AssetsLoading, AssetsLoading,
@ -62,6 +63,7 @@ QtObject:
ModelRole.Emoji.int: "emoji", ModelRole.Emoji.int: "emoji",
ModelRole.KeyUid.int: "keyUid", ModelRole.KeyUid.int: "keyUid",
ModelRole.CreatedAt.int: "createdAt", ModelRole.CreatedAt.int: "createdAt",
ModelRole.Position.int: "position",
ModelRole.KeycardAccount.int: "keycardAccount", ModelRole.KeycardAccount.int: "keycardAccount",
ModelRole.AssetsLoading.int: "assetsLoading", ModelRole.AssetsLoading.int: "assetsLoading",
}.toTable }.toTable
@ -105,6 +107,8 @@ QtObject:
result = newQVariant(item.keyUid()) result = newQVariant(item.keyUid())
of ModelRole.CreatedAt: of ModelRole.CreatedAt:
result = newQVariant(item.createdAt()) result = newQVariant(item.createdAt())
of ModelRole.Position:
result = newQVariant(item.position())
of ModelRole.KeycardAccount: of ModelRole.KeycardAccount:
result = newQVariant(item.keycardAccount()) result = newQVariant(item.keycardAccount())
of ModelRole.AssetsLoading: of ModelRole.AssetsLoading:

View File

@ -200,6 +200,8 @@ method load*(self: Module) =
if not args.success: if not args.success:
return return
self.notifyFilterChanged() self.notifyFilterChanged()
self.events.on(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED) do(e:Args):
self.notifyFilterChanged()
self.controller.init() self.controller.init()
self.view.load() self.view.load()

View File

@ -50,7 +50,8 @@ proc walletAccountToWalletSettingsAccountsItem*(w: WalletAccountDto, keycardAcco
w.emoji, w.emoji,
relatedAccounts, relatedAccounts,
w.keyUid, w.keyUid,
keycardAccount keycardAccount,
w.position,
) )
proc walletAccountToWalletAccountsItem*(w: WalletAccountDto, keycardAccount: bool, enabledChainIds: seq[int], currency: string, proc walletAccountToWalletAccountsItem*(w: WalletAccountDto, keycardAccount: bool, enabledChainIds: seq[int], currency: string,
@ -65,6 +66,7 @@ proc walletAccountToWalletAccountsItem*(w: WalletAccountDto, keycardAccount: boo
w.emoji, w.emoji,
w.keyUid, w.keyUid,
w.createdAt, w.createdAt,
w.position,
keycardAccount, keycardAccount,
w.assetsLoading, w.assetsLoading,
) )

View File

@ -108,6 +108,7 @@ type
removed*: bool # needs for synchronization removed*: bool # needs for synchronization
operable*: string operable*: string
createdAt*: int createdAt*: int
position*: int
proc toWalletAccountDto*(jsonObj: JsonNode): WalletAccountDto = proc toWalletAccountDto*(jsonObj: JsonNode): WalletAccountDto =
result = WalletAccountDto() result = WalletAccountDto()
@ -126,6 +127,7 @@ proc toWalletAccountDto*(jsonObj: JsonNode): WalletAccountDto =
discard jsonObj.getProp("removed", result.removed) discard jsonObj.getProp("removed", result.removed)
discard jsonObj.getProp("operable", result.operable) discard jsonObj.getProp("operable", result.operable)
discard jsonObj.getProp("createdAt", result.createdAt) discard jsonObj.getProp("createdAt", result.createdAt)
discard jsonObj.getProp("position", result.position)
result.assetsLoading = true result.assetsLoading = true
result.hasBalanceCache = false result.hasBalanceCache = false
result.hasMarketValuesCache = false result.hasMarketValuesCache = false

View File

@ -33,6 +33,7 @@ const SIGNAL_WALLET_ACCOUNT_TOKENS_BEING_FETCHED* = "walletAccount/tokenFetching
const SIGNAL_WALLET_ACCOUNT_DERIVED_ADDRESSES_FETCHED* = "walletAccount/derivedAddressesFetched" const SIGNAL_WALLET_ACCOUNT_DERIVED_ADDRESSES_FETCHED* = "walletAccount/derivedAddressesFetched"
const SIGNAL_WALLET_ACCOUNT_DERIVED_ADDRESSES_FROM_MNEMONIC_FETCHED* = "walletAccount/derivedAddressesFromMnemonicFetched" const SIGNAL_WALLET_ACCOUNT_DERIVED_ADDRESSES_FROM_MNEMONIC_FETCHED* = "walletAccount/derivedAddressesFromMnemonicFetched"
const SIGNAL_WALLET_ACCOUNT_ADDRESS_DETAILS_FETCHED* = "walletAccount/addressDetailsFetched" const SIGNAL_WALLET_ACCOUNT_ADDRESS_DETAILS_FETCHED* = "walletAccount/addressDetailsFetched"
const SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED* = "walletAccount/positionUpdated"
const SIGNAL_KEYCARDS_SYNCHRONIZED* = "keycardsSynchronized" const SIGNAL_KEYCARDS_SYNCHRONIZED* = "keycardsSynchronized"
const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet" const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet"
@ -549,7 +550,14 @@ QtObject:
error "error: ", procName="updateWalletAccount", errName=e.name, errDesription=e.msg error "error: ", procName="updateWalletAccount", errName=e.name, errDesription=e.msg
return false return false
proc fetchDerivedAddresses*(self: Service, password: string, derivedFrom: string, paths: seq[string], hashPassword: bool)= proc updateWalletAccountPosition*(self: Service, address: string, position: int) =
discard backend.updateAccountPosition(address, position)
for account in self.getAccounts():
self.walletAccounts[account.address].position = account.position
self.events.emit(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED, Args())
proc fetchDerivedAddresses*(self: Service, password: string, derivedFrom: string, paths: seq[string], hashPassword: bool) =
let arg = FetchDerivedAddressesTaskArg( let arg = FetchDerivedAddressesTaskArg(
password: if hashPassword: utils.hashPassword(password) else: password, password: if hashPassword: utils.hashPassword(password) else: password,
derivedFrom: derivedFrom, derivedFrom: derivedFrom,

View File

@ -258,6 +258,10 @@ rpc(updateKeycardUID, "accounts"):
rpc(deleteKeycard, "accounts"): rpc(deleteKeycard, "accounts"):
keycardUid: string keycardUid: string
rpc(updateAccountPosition, "accounts"):
address: string
position: int
rpc(getHourlyMarketValues, "wallet"): rpc(getHourlyMarketValues, "wallet"):
symbol: string symbol: string
currency: string currency: string

View File

@ -34,6 +34,10 @@ QtObject {
return accountsModule.updateAccount(address, accountName, colorId, emoji) return accountsModule.updateAccount(address, accountName, colorId, emoji)
} }
function updateAccountPosition(address, position) {
return accountsModule.updateAccountPosition(address, position)
}
property var dappList: Global.appIsReady? dappPermissionsModule.dapps : null property var dappList: Global.appIsReady? dappPermissionsModule.dapps : null
function disconnect(dappName) { function disconnect(dappName) {

View File

@ -25,8 +25,9 @@ SettingsContentBase {
readonly property int mainViewIndex: 0; readonly property int mainViewIndex: 0;
readonly property int networksViewIndex: 1; readonly property int networksViewIndex: 1;
readonly property int accountViewIndex: 2; readonly property int accountOrderViewIndex: 2;
readonly property int dappPermissionViewIndex: 3; readonly property int accountViewIndex: 3;
readonly property int dappPermissionViewIndex: 4;
function resetStack() { function resetStack() {
stackContainer.currentIndex = mainViewIndex; stackContainer.currentIndex = mainViewIndex;
@ -57,6 +58,10 @@ SettingsContentBase {
root.rootStore.backButtonName = qsTr("Wallet") root.rootStore.backButtonName = qsTr("Wallet")
root.sectionTitle = qsTr("DApp Permissions") root.sectionTitle = qsTr("DApp Permissions")
} }
else if(currentIndex == root.accountOrderViewIndex) {
root.rootStore.backButtonName = qsTr("Wallet")
root.sectionTitle = qsTr("Edit account order")
}
} }
MainView { MainView {
@ -75,6 +80,10 @@ SettingsContentBase {
stackContainer.currentIndex = accountViewIndex stackContainer.currentIndex = accountViewIndex
} }
onGoToAccountOrderView: {
stackContainer.currentIndex = accountOrderViewIndex
}
onGoToDappPermissionsView: { onGoToDappPermissionsView: {
stackContainer.currentIndex = dappPermissionViewIndex stackContainer.currentIndex = dappPermissionViewIndex
} }
@ -88,6 +97,13 @@ SettingsContentBase {
} }
} }
AccountOrderView {
walletStore: root.walletStore
onGoBack: {
stackContainer.currentIndex = mainViewIndex
}
}
AccountView { AccountView {
id: accountView id: accountView
walletStore: root.walletStore walletStore: root.walletStore

View File

@ -0,0 +1,101 @@
import QtQuick 2.15
import SortFilterProxyModel 0.2
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import shared.status 1.0
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Popups 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
import "../../stores"
import "../../controls"
StatusListView {
id: accountsView
signal goBack
property WalletStore walletStore
header: StatusBaseText {
text: qsTr("Move your most freqently used accounts to the top of your wallet list")
color: Theme.palette.baseColor1
font.pixelSize: Style.current.primaryTextFontSize
bottomPadding: Style.current.padding
}
anchors.top: parent.top
anchors.left: parent.left
width: parent.width
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
model: SortFilterProxyModel {
sourceModel: walletStore.accounts
sorters: [
RoleSorter {
roleName: "position"
priority: 2
}
]
}
displaced: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }
}
delegate: DropArea {
id: delegateRoot
property int visualIndex: index
width: ListView.view.width
height: draggableDelegate.height
keys: ["x-status-draggable-list-item-internal"]
onEntered: function(drag) {
const from = drag.source.visualIndex
const to = draggableDelegate.visualIndex
if (to === from)
return
drag.accept()
}
onDropped: function(drop) {
walletStore.updateAccountPosition(drop.source.address, draggableDelegate.position)
drop.accept()
}
StatusDraggableListItem {
id: draggableDelegate
property int position: model.position
property string address: model.address
width: parent.width
height: implicitHeight
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
dragParent: accountsView
visualIndex: delegateRoot.visualIndex
draggable: accountsView.count > 1
title: {
console.log(model.name, model.position)
return model.name
}
secondaryTitle: model.address
hasEmoji: true
icon.width: 40
icon.height: 40
icon.name: model.emoji
icon.color: Utils.getColorForId(model.colorId)
actions: []
}
}
}

View File

@ -18,6 +18,7 @@ Column {
property WalletStore walletStore property WalletStore walletStore
signal goToNetworksView() signal goToNetworksView()
signal goToAccountOrderView()
signal goToAccountView(var account) signal goToAccountView(var account)
signal goToDappPermissionsView() signal goToDappPermissionsView()
@ -63,6 +64,22 @@ Column {
Separator {} Separator {}
StatusListItem {
objectName: "accountOrderItem"
title: qsTr("Account order")
height: 64
width: parent.width
onClicked: goToAccountOrderView()
components: [
StatusIcon {
icon: "next"
color: Theme.palette.baseColor1
}
]
}
Separator {}
Item { Item {
width: parent.width width: parent.width
height: 8 height: 8

View File

@ -426,7 +426,7 @@ Rectangle {
model: SortFilterProxyModel { model: SortFilterProxyModel {
sourceModel: RootStore.accounts sourceModel: RootStore.accounts
sorters: RoleSorter { roleName: "createdAt"; sortOrder: Qt.AscendingOrder } sorters: RoleSorter { roleName: "position"; sortOrder: Qt.AscendingOrder }
} }
} }

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 3e7d1a5f34183ea9f2ebf3b3d6a8143c98674d62 Subproject commit da2f155f2df52d689d400bffc11e67b463ddcac9