feat(@desktop/profile): Adapt view for settings as pre new design

fixes #5725
This commit is contained in:
Khushboo Mehta 2022-07-19 15:45:27 +02:00 committed by Iuri Matias
parent d0125c86b5
commit 91eb1a7969
12 changed files with 445 additions and 147 deletions

View File

@ -0,0 +1,89 @@
import strformat
type
Item* = object
name: string
address: string
path: string
color: string
publicKey: string
walletType: string
isWallet: bool
isChat: bool
currencyBalance: float64
emoji: string
derivedfrom: string
proc initItem*(
name: string,
address: string,
path: string,
color: string,
publicKey: string,
walletType: string,
isWallet: bool,
isChat: bool,
currencyBalance: float64,
emoji: string,
derivedfrom: string
): Item =
result.name = name
result.address = address
result.path = path
result.color = color
result.publicKey = publicKey
result.walletType = walletType
result.isWallet = isWallet
result.isChat = isChat
result.currencyBalance = currencyBalance
result.emoji = emoji
result.derivedfrom = derivedfrom
proc `$`*(self: Item): string =
result = fmt"""WalletAccountItem(
name: {self.name},
address: {self.address},
path: {self.path},
color: {self.color},
publicKey: {self.publicKey},
walletType: {self.walletType},
isWallet: {self.isWallet},
isChat: {self.isChat},
currencyBalance: {self.currencyBalance},
emoji: {self.emoji},
derivedfrom: {self.derivedfrom}
]"""
proc getName*(self: Item): string =
return self.name
proc getAddress*(self: Item): string =
return self.address
proc getPath*(self: Item): string =
return self.path
proc getEmoji*(self: Item): string =
return self.emoji
proc getColor*(self: Item): string =
return self.color
proc getPublicKey*(self: Item): string =
return self.publicKey
proc getWalletType*(self: Item): string =
return self.walletType
proc getIsWallet*(self: Item): bool =
return self.isWallet
proc getIsChat*(self: Item): bool =
return self.isChat
proc getCurrencyBalance*(self: Item): float64 =
return self.currencyBalance
proc getDerivedFrom*(self: Item): string =
return self.derivedfrom

View File

@ -0,0 +1,105 @@
import NimQml, Tables, strutils, strformat, sequtils
import ./compact_item
type
ModelRole {.pure.} = enum
Name = UserRole + 1,
Address,
Path,
Color,
PublicKey,
WalletType,
IsWallet,
IsChat,
CurrencyBalance,
Emoji,
DerivedFrom,
QtObject:
type
Model* = ref object of QAbstractListModel
items: seq[Item]
proc delete(self: Model) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: Model) =
self.QAbstractListModel.setup
proc newModel*(): Model =
new(result, delete)
result.setup
proc `$`*(self: Model): string =
for i in 0 ..< self.items.len:
result &= fmt"""[{i}]:({$self.items[i]})"""
proc countChanged(self: Model) {.signal.}
proc getCount*(self: Model): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
method rowCount(self: Model, index: QModelIndex = nil): int =
return self.items.len
method roleNames(self: Model): Table[int, string] =
{
ModelRole.Name.int:"name",
ModelRole.Address.int:"address",
ModelRole.Path.int:"path",
ModelRole.Color.int:"color",
ModelRole.PublicKey.int:"publicKey",
ModelRole.WalletType.int:"walletType",
ModelRole.IsWallet.int:"isWallet",
ModelRole.IsChat.int:"isChat",
ModelRole.CurrencyBalance.int:"currencyBalance",
ModelRole.Emoji.int: "emoji",
ModelRole.DerivedFrom.int: "derivedfrom",
}.toTable
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
method data(self: Model, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
if (index.row < 0 or index.row >= self.items.len):
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Name:
result = newQVariant(item.getName())
of ModelRole.Address:
result = newQVariant(item.getAddress())
of ModelRole.Path:
result = newQVariant(item.getPath())
of ModelRole.Color:
result = newQVariant(item.getColor())
of ModelRole.PublicKey:
result = newQVariant(item.getPublicKey())
of ModelRole.WalletType:
result = newQVariant(item.getWalletType())
of ModelRole.IsWallet:
result = newQVariant(item.getIsWallet())
of ModelRole.IsChat:
result = newQVariant(item.getIsChat())
of ModelRole.CurrencyBalance:
result = newQVariant(item.getCurrencyBalance())
of ModelRole.Emoji:
result = newQVariant(item.getEmoji())
of ModelRole.DerivedFrom:
result = newQVariant(item.getDerivedFrom())

View File

@ -1,5 +1,6 @@
import strformat
import ../../../shared_models/token_model as token_model
import ./compact_model as compact_model
type
Item* = object
@ -15,6 +16,7 @@ type
assets: token_model.Model
emoji: string
derivedfrom: string
relatedAccounts: compact_model.Model
proc initItem*(
name: string,
@ -28,7 +30,8 @@ proc initItem*(
currencyBalance: float64,
assets: token_model.Model,
emoji: string,
derivedfrom: string
derivedfrom: string,
relatedAccounts: compact_model.Model
): Item =
result.name = name
result.address = address
@ -42,6 +45,7 @@ proc initItem*(
result.assets = assets
result.emoji = emoji
result.derivedfrom = derivedfrom
result.relatedAccounts = relatedAccounts
proc `$`*(self: Item): string =
result = fmt"""WalletAccountItem(
@ -56,7 +60,8 @@ proc `$`*(self: Item): string =
currencyBalance: {self.currencyBalance},
assets.len: {self.assets.getCount()},
emoji: {self.emoji},
derivedfrom: {self.derivedfrom}
derivedfrom: {self.derivedfrom},
relatedAccounts: {self.relatedAccounts}
]"""
proc getName*(self: Item): string =
@ -94,3 +99,6 @@ proc getAssets*(self: Item): token_model.Model =
proc getDerivedFrom*(self: Item): string =
return self.derivedfrom
proc getRelatedAccounts*(self: Item): compact_model.Model =
return self.relatedAccounts

View File

@ -15,7 +15,8 @@ type
CurrencyBalance,
Assets,
Emoji,
DerivedFrom
DerivedFrom,
RelatedAccounts
QtObject:
type
@ -62,9 +63,17 @@ QtObject:
ModelRole.Assets.int:"assets",
ModelRole.CurrencyBalance.int:"currencyBalance",
ModelRole.Emoji.int: "emoji",
ModelRole.DerivedFrom.int: "derivedfrom"
ModelRole.DerivedFrom.int: "derivedfrom",
ModelRole.RelatedAccounts.int: "relatedAccounts"
}.toTable
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
method data(self: Model, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
@ -100,12 +109,8 @@ QtObject:
result = newQVariant(item.getEmoji())
of ModelRole.DerivedFrom:
result = newQVariant(item.getDerivedFrom())
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
of ModelRole.RelatedAccounts:
result = newQVariant(item.getRelatedAccounts())
proc getAccountNameByAddress*(self: Model, address: string): string =
for account in self.items:

View File

@ -7,6 +7,8 @@ import ../../../../core/eventemitter
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ./compact_item as compact_item
import ./compact_model as compact_model
export io_interface
@ -55,6 +57,23 @@ method refreshWalletAccounts*(self: Module) =
))
)
let relatedAccounts = compact_model.newModel()
relatedAccounts.setItems(
w.relatedAccounts.map(x => compact_item.initItem(
x.name,
x.address,
x.path,
x.color,
x.publicKey,
x.walletType,
x.isWallet,
x.isChat,
x.getCurrencyBalance(),
x.emoji,
x.derivedfrom,
))
)
result = initItem(
w.name,
w.address,
@ -67,7 +86,8 @@ method refreshWalletAccounts*(self: Module) =
w.getCurrencyBalance(),
assets,
w.emoji,
w.derivedfrom
w.derivedfrom,
relatedAccounts
))
self.view.setItems(items)

View File

@ -158,40 +158,52 @@ QtObject:
proc setItems*(self: View, items: seq[Item]) =
self.model.setItems(items)
var statusDefaultAccountDerivedFrom: string = ""
var importedSeedIndex: int = 1
var watchOnly: seq[Item] = @[]
var imported: seq[Item] = @[]
var generated: seq[Item] = @[]
# create a list of imported seeds/default account created from where more accounts can be derived
var generatedAccounts: seq[GeneratedWalletItem] = @[]
for item in items:
if item.getWalletType() == "" or item.getWalletType() == GENERATED:
# Default Account
if item.getWalletType() == "":
statusDefaultAccountDerivedFrom = item.getDerivedFrom()
var generatedAccs: Model = newModel()
generatedAccs.setItems(items.filter(x => cmpIgnoreCase(x.getDerivedFrom(), item.getDerivedFrom()) == 0))
generatedAccounts.add(initGeneratedWalletItem("Default", "status", generatedAccs, item.getDerivedFrom()))
generated.add(item)
# Account generated from profile seed phrase
elif item.getWalletType() == GENERATED and cmpIgnoreCase(item.getDerivedFrom(), statusDefaultAccountDerivedFrom) == 0 :
generated.add(item)
# Watch only accounts
elif item.getWalletType() == WATCH:
watchOnly.add(item)
# Accounts imported with Seed phrase
elif item.getWalletType() == SEED:
var generatedAccs1: Model = newModel()
var filterItems: seq[Item] = items.filter(x => cmpIgnoreCase(x.getDerivedFrom(), item.getDerivedFrom()) == 0)
generatedAccs1.setItems(filterItems)
generatedAccounts.add(initGeneratedWalletItem("Seed " & $importedSeedIndex , "seed-phrase", generatedAccs1, item.getDerivedFrom()))
imported.add(item)
importedSeedIndex += 1
# Accounts imported with Key OR accounts generated from a seed thats not the profile seed
else:
imported.add(item)
self.watchOnly.setItems(watchOnly)
self.imported.setItems(imported)
self.generated.setItems(generated)
# create a list of imported seeds/default account created from where more accounts can be derived
var generatedAccounts: seq[GeneratedWalletItem] = @[]
var importedSeedIndex: int = 1
for item in items:
if item.getWalletType() == "":
var generatedAccs: Model = newModel()
generatedAccs.setItems(generated.filter(x => cmpIgnoreCase(x.getDerivedFrom(), item.getDerivedFrom()) == 0))
generatedAccounts.add(initGeneratedWalletItem("Default", "status", generatedAccs, item.getDerivedFrom()))
elif item.getWalletType() == SEED:
var generatedAccs1: Model = newModel()
var filterItems: seq[Item] = generated.filter(x => cmpIgnoreCase(x.getDerivedFrom(), item.getDerivedFrom()) == 0)
filterItems.insert(item, 0)
generatedAccs1.setItems(filterItems)
generatedAccounts.add(initGeneratedWalletItem("Seed " & $importedSeedIndex , "seed-phrase", generatedAccs1, item.getDerivedFrom()))
importedSeedIndex += 1
self.generatedAccounts.setItems(generatedAccounts)
proc generateNewAccount*(self: View, password: string, accountName: string, color: string, emoji: string, path: string, derivedFrom: string): string {.slot.} =
return self.delegate.generateNewAccount(password, accountName, color, emoji, path, derivedFrom)

View File

@ -91,6 +91,8 @@ proc setAssetsAndBalance(self: Module, tokens: seq[WalletTokenDto]) =
method switchAccount*(self: Module, accountIndex: int) =
self.currentAccountIndex = accountIndex
let walletAccount = self.controller.getWalletAccount(accountIndex)
# can safely do this as the account will always contain atleast one account
self.view.setDefaultWalletAccount(self.controller.getWalletAccount(0))
self.view.setData(walletAccount)
self.setAssetsAndBalance(walletAccount.tokens)
@ -101,4 +103,4 @@ proc onTokensRebuilt(self: Module, accountsTokens: OrderedTable[string, seq[Wall
let walletAccount = self.controller.getWalletAccount(self.currentAccountIndex)
if not accountsTokens.contains(walletAccount.address):
return
self.setAssetsAndBalance(accountsTokens[walletAccount.address])
self.setAssetsAndBalance(accountsTokens[walletAccount.address])

View File

@ -4,11 +4,17 @@ import ../../../../../app_service/service/wallet_account/service as wallet_accou
import ./io_interface
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ../accounts/compact_model
import ../accounts/compact_item
const GENERATED = "generated"
const GENERATED_FROM_IMPORTED = "generated from imported accounts"
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
defaultAccount: wallet_account_service.WalletAccountDto
name: string
address: string
mixedcaseAddress: string
@ -20,6 +26,8 @@ QtObject:
currencyBalance: float64
assets: token_model.Model
emoji: string
derivedfrom: string
relatedAccounts: compact_model.Model
proc setup(self: View) =
self.QObject.setup
@ -134,9 +142,30 @@ QtObject:
read = getEmoji
notify = emojiChanged
proc getDerivedfrom(self: View): QVariant {.slot.} =
return newQVariant(self.derivedfrom)
proc derivedfromChanged(self: View) {.signal.}
QtProperty[QVariant] derivedfrom:
read = getDerivedfrom
notify = derivedfromChanged
proc getRelatedAccounts(self: View): QVariant {.slot.} =
return newQVariant(self.relatedAccounts)
proc relatedAccountsChanged(self: View) {.signal.}
QtProperty[QVariant] relatedAccounts:
read = getRelatedAccounts
notify = relatedAccountsChanged
proc update(self: View, address: string, accountName: string, color: string, emoji: string) {.slot.} =
self.delegate.update(address, accountName, color, emoji)
proc setDefaultWalletAccount*(self: View, default: wallet_account_service.WalletAccountDto) =
self.defaultAccount = default
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto) =
if(self.name != dto.name):
self.name = dto.name
@ -156,12 +185,40 @@ QtObject:
if(self.publicKey != dto.publicKey):
self.publicKey = dto.publicKey
self.publicKeyChanged()
if(self.walletType != dto.walletType):
self.walletType = dto.walletType
self.walletTypeChanged()
# Check if the account is generated from default wallet account else change wallettype
if dto.walletType == GENERATED and dto.derivedfrom != self.defaultAccount.derivedfrom:
self.walletType = GENERATED_FROM_IMPORTED
self.walletTypeChanged()
else:
if(self.walletType != dto.walletType):
self.walletType = dto.walletType
self.walletTypeChanged()
if(self.isChat != dto.isChat):
self.isChat = dto.isChat
self.isChatChanged()
if(self.emoji != dto.emoji):
self.emoji = dto.emoji
self.emojiChanged()
self.emojiChanged()
if(self.derivedfrom != dto.derivedfrom):
self.derivedfrom = dto.derivedfrom
self.derivedfromChanged()
# Set related accounts
let relatedAccounts = compact_model.newModel()
relatedAccounts.setItems(
dto.relatedAccounts.map(x => compact_item.initItem(
x.name,
x.address,
x.path,
x.color,
x.publicKey,
x.walletType,
x.isWallet,
x.isChat,
x.getCurrencyBalance(),
x.emoji,
x.derivedfrom
))
)
self.relatedAccounts = relatedAccounts
self.relatedAccountsChanged()

View File

@ -35,6 +35,7 @@ type
tokens*: seq[WalletTokenDto]
emoji*: string
derivedfrom*: string
relatedAccounts*: seq[WalletAccountDto]
proc newDto*(
name: string,
@ -46,7 +47,8 @@ proc newDto*(
isWallet: bool,
isChat: bool,
emoji: string,
derivedfrom: string
derivedfrom: string,
relatedAccounts: seq[WalletAccountDto]
): WalletAccountDto =
return WalletAccountDto(
name: name,
@ -58,7 +60,8 @@ proc newDto*(
isWallet: isWallet,
isChat: isChat,
emoji: emoji,
derivedfrom: derivedfrom
derivedfrom: derivedfrom,
relatedAccounts: relatedAccounts
)
proc toWalletAccountDto*(jsonObj: JsonNode): WalletAccountDto =
@ -124,4 +127,4 @@ proc walletTokenDtoToJson*(dto: WalletTokenDto): JsonNode =
"enabledNetworkBalance": %* dto.enabledNetworkBalance,
"balancesPerChain": balancesPerChainJsonObj,
"visible": dto.visible
}
}

View File

@ -153,6 +153,7 @@ QtObject:
try:
let accounts = fetchAccounts()
for account in accounts:
account.relatedAccounts = accounts.filter(x => not account.derivedFrom.isEmptyOrWhitespace and (cmpIgnoreCase(x.derivedFrom, account.derivedFrom) == 0))
self.walletAccounts[account.address] = account
self.buildAllTokens(true)
@ -206,6 +207,7 @@ QtObject:
for account in accounts:
if not self.walletAccounts.haskey(account.address):
newAccount = account
newAccount.relatedAccounts = accounts.filter(x => cmpIgnoreCase(x.derivedFrom, account.derivedFrom) == 0)
break
self.walletAccounts[newAccount.address] = newAccount
self.buildAllTokens()
@ -435,4 +437,4 @@ QtObject:
for token in walletAccount.tokens:
if token.balancesPerChain.hasKey(network.chainId):
let balance = token.balancesPerChain[network.chainId]
result += balance.currencyBalance
result += balance.currencyBalance

View File

@ -0,0 +1,58 @@
import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
Rectangle {
id: root
property alias primaryText: primaryText.text
property alias secondaryText: secondaryText.text
property alias tagsModel: tags.model
property alias tagsDelegate: tags.delegate
property int maxWidth: 0
implicitHeight: 52
implicitWidth: layout.width + Style.current.xlPadding
radius: Style.current.radius
border.width: 1
border.color: Theme.palette.baseColor2
color: Style.current.transparent
ColumnLayout {
id: layout
spacing: -1
anchors.centerIn: parent
StatusBaseText {
id: primaryText
Layout.maximumWidth: root.maxWidth - Style.current.xlPadding
font.pixelSize: 13
color: Theme.palette.directColor5
visible: text
elide: Text.ElideRight
}
StatusBaseText {
id: secondaryText
Layout.maximumWidth: root.maxWidth - Style.current.xlPadding
font.pixelSize: 15
color: Theme.palette.directColor1
visible: text
elide: Text.ElideRight
}
ScrollView {
Layout.preferredHeight: 24
Layout.maximumWidth: root.maxWidth - Style.current.xlPadding
clip: true
visible: tags.count > 0
ListView {
id: tags
orientation: ListView.Horizontal
spacing: 10
}
}
}
}

View File

@ -6,6 +6,7 @@ import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import utils 1.0
import "../../stores"
@ -27,6 +28,8 @@ Item {
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
spacing: Style.current.bigPadding
Row {
id: header
spacing: Style.current.smallPadding
@ -76,127 +79,61 @@ Item {
}
}
Item {
height: Style.current.bigPadding
width: parent.width
}
Item {
height: 50
Flow {
width: parent.width
Rectangle {
spacing: Style.current.halfPadding
InformationTile {
id: typeRectangle
border.width: 1
border.color: Theme.palette.directColor7
radius: Style.current.radius
width: typeText.width + Style.current.xlPadding
height: parent.height
color: Style.current.transparent
StatusBaseText {
id: labelType
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: qsTr("Type")
font.pixelSize: 13
color: Theme.palette.directColor5
}
StatusBaseText {
id: typeText
anchors.top: labelType.bottom
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: {
const walletType = walletStore.currentAccount.walletType
if (walletType === "watch") {
return qsTr("Watch-Only Account")
} else if (walletType === "generated" || walletType === "") {
return qsTr("Generated by your Status seed phrase profile")
} else if (walletType === "imported") {
return qsTr("Imported Account")
}
maxWidth: parent.width
primaryText: qsTr("Type")
secondaryText: {
const walletType = walletStore.currentAccount.walletType
if (walletType === "watch") {
return qsTr("Watch-Only Account")
} else if (walletType === "generated" || walletType === "") {
return qsTr("Generated by your Status seed phrase profile")
} else {
return qsTr("Imported Account")
}
font.pixelSize: 15
color: Theme.palette.directColor1
}
}
Rectangle {
id: storageRectangle
anchors.left: typeRectangle.right
anchors.leftMargin: Style.current.padding
border.width: 1
border.color: Theme.palette.directColor7
radius: Style.current.radius
width: storageText.width + Style.current.xlPadding
height: parent.height
color: Style.current.transparent
InformationTile {
maxWidth: parent.width
primaryText: qsTr("Storage")
secondaryText: qsTr("On Device")
}
StatusBaseText {
id: labelStorage
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: qsTr("Storage")
font.pixelSize: 13
color: Theme.palette.directColor5
}
StatusBaseText {
id: storageText
anchors.top: labelStorage.bottom
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: qsTr("On Device")
font.pixelSize: 15
color: Theme.palette.directColor1
InformationTile {
maxWidth: parent.width
primaryText: qsTr("Derivation Path")
secondaryText: walletStore.currentAccount.path
visible: walletStore.currentAccount.path
}
InformationTile {
maxWidth: parent.width
visible: walletStore.currentAccount.relatedAccounts.count > 0
primaryText: qsTr("Related Accounts")
tagsModel: walletStore.currentAccount.relatedAccounts
tagsDelegate: StatusListItemTag {
color: model.color
height: 24
radius: 6
closeButtonVisible: false
icon.emoji: model.emoji
icon.emojiSize: Emoji.size.verySmall
icon.isLetterIdenticon: true
title: model.name
titleText.font.pixelSize: 12
titleText.color: Theme.palette.indirectColor1
}
}
}
Item {
height: Style.current.bigPadding
width: parent.width
}
Rectangle {
visible: walletStore.currentAccount.path !== ""
border.width: 1
border.color: Theme.palette.directColor7
radius: Style.current.radius
width: Math.max(path.width, labelPath.width) + Style.current.xlPadding
height: 50
color: Style.current.transparent
StatusBaseText {
id: labelPath
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: qsTr("Derivation Path")
font.weight: Font.Medium
font.pixelSize: 13
color: Theme.palette.directColor5
}
StatusBaseText {
id: path
anchors.top: labelPath.bottom
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: walletStore.currentAccount.path
font.pixelSize: 15
color: Theme.palette.directColor1
}
}
Item {
height: Style.current.bigPadding
width: parent.width
}
StatusButton {
visible: walletStore.currentAccount.walletType !== ""
text: qsTr("Remove from your profile")