mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-19 18:18:38 +00:00
feat: check password before saving a new account
Also shows the error if there is one when adding. Should show a loading state too, but it doesn't work because the Nim function freezes the QML
This commit is contained in:
parent
8e21a1b8b3
commit
8cb8395ceb
@ -121,17 +121,17 @@ QtObject:
|
|||||||
self.setCurrentAccountByIndex(0)
|
self.setCurrentAccountByIndex(0)
|
||||||
self.accountListChanged()
|
self.accountListChanged()
|
||||||
|
|
||||||
proc generateNewAccount*(self: WalletView, password: string, accountName: string, color: string) {.slot.} =
|
proc generateNewAccount*(self: WalletView, password: string, accountName: string, color: string): string {.slot.} =
|
||||||
self.status.wallet.generateNewAccount(password, accountName, color)
|
result = self.status.wallet.generateNewAccount(password, accountName, color)
|
||||||
|
|
||||||
proc addAccountsFromSeed*(self: WalletView, seed: string, password: string, accountName: string, color: string) {.slot.} =
|
proc addAccountsFromSeed*(self: WalletView, seed: string, password: string, accountName: string, color: string): string {.slot.} =
|
||||||
self.status.wallet.addAccountsFromSeed(seed, password, accountName, color)
|
result = self.status.wallet.addAccountsFromSeed(seed, password, accountName, color)
|
||||||
|
|
||||||
proc addAccountsFromPrivateKey*(self: WalletView, privateKey: string, password: string, accountName: string, color: string) {.slot.} =
|
proc addAccountsFromPrivateKey*(self: WalletView, privateKey: string, password: string, accountName: string, color: string): string {.slot.} =
|
||||||
self.status.wallet.addAccountsFromPrivateKey(privateKey, password, accountName, color)
|
result = self.status.wallet.addAccountsFromPrivateKey(privateKey, password, accountName, color)
|
||||||
|
|
||||||
proc addWatchOnlyAccount*(self: WalletView, address: string, accountName: string, color: string) {.slot.} =
|
proc addWatchOnlyAccount*(self: WalletView, address: string, accountName: string, color: string): string {.slot.} =
|
||||||
self.status.wallet.addWatchOnlyAccount(address, accountName, color)
|
result = self.status.wallet.addWatchOnlyAccount(address, accountName, color)
|
||||||
|
|
||||||
proc changeAccountSettings*(self: WalletView, address: string, accountName: string, color: string): string {.slot.} =
|
proc changeAccountSettings*(self: WalletView, address: string, accountName: string, color: string): string {.slot.} =
|
||||||
result = self.status.wallet.changeAccountSettings(address, accountName, color)
|
result = self.status.wallet.changeAccountSettings(address, accountName, color)
|
||||||
|
@ -7,7 +7,10 @@ import accounts/constants
|
|||||||
import ../../signals/types as signal_types
|
import ../../signals/types as signal_types
|
||||||
import ../wallet/account
|
import ../wallet/account
|
||||||
|
|
||||||
proc queryAccounts*(): string =
|
proc hashPassword(password: string): string =
|
||||||
|
result = "0x" & $keccak_256.digest(password)
|
||||||
|
|
||||||
|
proc getDefaultAccount*(): string =
|
||||||
var response = callPrivateRPC("eth_accounts")
|
var response = callPrivateRPC("eth_accounts")
|
||||||
result = parseJson(response)["result"][0].getStr()
|
result = parseJson(response)["result"][0].getStr()
|
||||||
|
|
||||||
@ -49,7 +52,7 @@ proc saveAccountAndLogin*(
|
|||||||
password: string,
|
password: string,
|
||||||
configJSON: string,
|
configJSON: string,
|
||||||
settingsJSON: string): types.Account =
|
settingsJSON: string): types.Account =
|
||||||
let hashedPassword = "0x" & $keccak_256.digest(password)
|
let hashedPassword = hashPassword(password)
|
||||||
let subaccountData = %* [
|
let subaccountData = %* [
|
||||||
{
|
{
|
||||||
"public-key": account.derived.defaultWallet.publicKey,
|
"public-key": account.derived.defaultWallet.publicKey,
|
||||||
@ -81,7 +84,7 @@ proc saveAccountAndLogin*(
|
|||||||
raise newException(StatusGoException, "Error saving account and logging in: " & error)
|
raise newException(StatusGoException, "Error saving account and logging in: " & error)
|
||||||
|
|
||||||
proc storeDerivedAccounts*(account: GeneratedAccount, password: string): MultiAccounts =
|
proc storeDerivedAccounts*(account: GeneratedAccount, password: string): MultiAccounts =
|
||||||
let hashedPassword = "0x" & $keccak_256.digest(password)
|
let hashedPassword = hashPassword(password)
|
||||||
let multiAccount = %* {
|
let multiAccount = %* {
|
||||||
"accountID": account.id,
|
"accountID": account.id,
|
||||||
"paths": [PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET],
|
"paths": [PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET],
|
||||||
@ -150,7 +153,7 @@ proc setupAccount*(account: GeneratedAccount, password: string): types.Account =
|
|||||||
discard libstatus.addPeer(peer)
|
discard libstatus.addPeer(peer)
|
||||||
|
|
||||||
proc login*(nodeAccount: NodeAccount, password: string): NodeAccount =
|
proc login*(nodeAccount: NodeAccount, password: string): NodeAccount =
|
||||||
let hashedPassword = "0x" & $keccak_256.digest(password)
|
let hashedPassword = hashPassword(password)
|
||||||
let account = nodeAccount.toAccount
|
let account = nodeAccount.toAccount
|
||||||
let loginResult = $libstatus.login($toJson(account), hashedPassword)
|
let loginResult = $libstatus.login($toJson(account), hashedPassword)
|
||||||
let error = parseJson(loginResult)["error"].getStr
|
let error = parseJson(loginResult)["error"].getStr
|
||||||
@ -162,6 +165,16 @@ proc login*(nodeAccount: NodeAccount, password: string): NodeAccount =
|
|||||||
|
|
||||||
raise newException(StatusGoException, "Error logging in: " & error)
|
raise newException(StatusGoException, "Error logging in: " & error)
|
||||||
|
|
||||||
|
proc verifyAccountPassword*(address: string, password: string): bool =
|
||||||
|
let hashedPassword = hashPassword(password)
|
||||||
|
let verifyResult = $libstatus.verifyAccountPassword(KEYSTOREDIR, address, hashedPassword)
|
||||||
|
let error = parseJson(verifyResult)["error"].getStr
|
||||||
|
|
||||||
|
if error == "":
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
proc multiAccountImportMnemonic*(mnemonic: string): GeneratedAccount =
|
proc multiAccountImportMnemonic*(mnemonic: string): GeneratedAccount =
|
||||||
let mnemonicJson = %* {
|
let mnemonicJson = %* {
|
||||||
"mnemonicPhrase": mnemonic,
|
"mnemonicPhrase": mnemonic,
|
||||||
|
@ -36,4 +36,6 @@ proc login*(acctData: cstring, password: cstring): cstring {.importc: "Login".}
|
|||||||
|
|
||||||
proc logout*(): cstring {.importc: "Logout".}
|
proc logout*(): cstring {.importc: "Logout".}
|
||||||
|
|
||||||
|
proc verifyAccountPassword*(keyStoreDir: cstring, address: cstring, password: cstring): cstring {.importc: "VerifyAccountPassword".}
|
||||||
|
|
||||||
proc validateMnemonic*(mnemonic: cstring): cstring {.importc: "ValidateMnemonic".}
|
proc validateMnemonic*(mnemonic: cstring): cstring {.importc: "ValidateMnemonic".}
|
||||||
|
@ -97,30 +97,44 @@ proc calculateTotalFiatBalance*(self: WalletModel) =
|
|||||||
for account in self.accounts:
|
for account in self.accounts:
|
||||||
self.totalBalance += account.realFiatBalance
|
self.totalBalance += account.realFiatBalance
|
||||||
|
|
||||||
proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true) =
|
proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true): string =
|
||||||
generatedAccount.name = accountName
|
try:
|
||||||
var derivedAccount: DerivedAccount = status_accounts.saveAccount(generatedAccount, password, color, accountType, isADerivedAccount)
|
generatedAccount.name = accountName
|
||||||
var account = self.newAccount(accountName, derivedAccount.address, color, fmt"0.00 {self.defaultCurrency}", derivedAccount.publicKey)
|
var derivedAccount: DerivedAccount = status_accounts.saveAccount(generatedAccount, password, color, accountType, isADerivedAccount)
|
||||||
self.accounts.add(account)
|
var account = self.newAccount(accountName, derivedAccount.address, color, fmt"0.00 {self.defaultCurrency}", derivedAccount.publicKey)
|
||||||
self.events.emit("newAccountAdded", AccountArgs(account: account))
|
self.accounts.add(account)
|
||||||
|
self.events.emit("newAccountAdded", AccountArgs(account: account))
|
||||||
|
except Exception as e:
|
||||||
|
return fmt"Error adding new account: {e.msg}"
|
||||||
|
|
||||||
proc generateNewAccount*(self: WalletModel, password: string, accountName: string, color: string) =
|
return ""
|
||||||
|
|
||||||
|
proc addNewGeneratedAccountWithPassword(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true): string =
|
||||||
|
let defaultAccount = status_accounts.getDefaultAccount()
|
||||||
|
let isPasswordOk = status_accounts.verifyAccountPassword(defaultAccount, password)
|
||||||
|
|
||||||
|
if (not isPasswordOk):
|
||||||
|
return "Wrong password"
|
||||||
|
|
||||||
|
result = self.addNewGeneratedAccount(generatedAccount, password, accountName, color, accountType, isADerivedAccount)
|
||||||
|
|
||||||
|
proc generateNewAccount*(self: WalletModel, password: string, accountName: string, color: string): string =
|
||||||
let accounts = status_accounts.generateAddresses(1)
|
let accounts = status_accounts.generateAddresses(1)
|
||||||
let generatedAccount = accounts[0]
|
let generatedAccount = accounts[0]
|
||||||
self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.GENERATED)
|
return self.addNewGeneratedAccountWithPassword(generatedAccount, password, accountName, color, constants.GENERATED)
|
||||||
|
|
||||||
proc addAccountsFromSeed*(self: WalletModel, seed: string, password: string, accountName: string, color: string) =
|
proc addAccountsFromSeed*(self: WalletModel, seed: string, password: string, accountName: string, color: string): string =
|
||||||
let mnemonic = replace(seed, ',', ' ')
|
let mnemonic = replace(seed, ',', ' ')
|
||||||
let generatedAccount = status_accounts.multiAccountImportMnemonic(mnemonic)
|
let generatedAccount = status_accounts.multiAccountImportMnemonic(mnemonic)
|
||||||
self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.SEED)
|
return self.addNewGeneratedAccountWithPassword(generatedAccount, password, accountName, color, constants.SEED)
|
||||||
|
|
||||||
proc addAccountsFromPrivateKey*(self: WalletModel, privateKey: string, password: string, accountName: string, color: string) =
|
proc addAccountsFromPrivateKey*(self: WalletModel, privateKey: string, password: string, accountName: string, color: string): string =
|
||||||
let generatedAccount = status_accounts.MultiAccountImportPrivateKey(privateKey)
|
let generatedAccount = status_accounts.MultiAccountImportPrivateKey(privateKey)
|
||||||
self.addNewGeneratedAccount(generatedAccount, password, accountName, color, constants.KEY, false)
|
return self.addNewGeneratedAccountWithPassword(generatedAccount, password, accountName, color, constants.KEY, false)
|
||||||
|
|
||||||
proc addWatchOnlyAccount*(self: WalletModel, address: string, accountName: string, color: string) =
|
proc addWatchOnlyAccount*(self: WalletModel, address: string, accountName: string, color: string): string =
|
||||||
let account = GeneratedAccount(address: address)
|
let account = GeneratedAccount(address: address)
|
||||||
self.addNewGeneratedAccount(account, "", accountName, color, constants.WATCH, false)
|
return self.addNewGeneratedAccount(account, "", accountName, color, constants.WATCH, false)
|
||||||
|
|
||||||
proc hasAsset*(self: WalletModel, account: string, symbol: string): bool =
|
proc hasAsset*(self: WalletModel, account: string, symbol: string): bool =
|
||||||
self.tokens.anyIt(it["symbol"].getStr == symbol)
|
self.tokens.anyIt(it["symbol"].getStr == symbol)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
import "../../../../imports"
|
import "../../../../imports"
|
||||||
import "../../../../shared"
|
import "../../../../shared"
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ ModalPopup {
|
|||||||
property string passwordValidationError: ""
|
property string passwordValidationError: ""
|
||||||
property string privateKeyValidationError: ""
|
property string privateKeyValidationError: ""
|
||||||
property string accountNameValidationError: ""
|
property string accountNameValidationError: ""
|
||||||
|
property bool loading: false
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
if (passwordInput.text === "") {
|
if (passwordInput.text === "") {
|
||||||
@ -94,17 +96,31 @@ ModalPopup {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Theme.padding
|
anchors.rightMargin: Theme.padding
|
||||||
label: qsTr("Add account >")
|
label: loading ? qsTr("Loading...") : qsTr("Add account >")
|
||||||
|
|
||||||
disabled: passwordInput.text === "" || accountNameInput.text === "" || accountPKeyInput.text === ""
|
disabled: loading || passwordInput.text === "" || accountNameInput.text === "" || accountPKeyInput.text === ""
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: accountError
|
||||||
|
title: "Adding the account failed"
|
||||||
|
icon: StandardIcon.Critical
|
||||||
|
standardButtons: StandardButton.Ok
|
||||||
|
}
|
||||||
|
|
||||||
onClicked : {
|
onClicked : {
|
||||||
|
// TODO the loaidng doesn't work because the function freezes th eview. Might need to use threads
|
||||||
|
loading = true
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
return
|
return loading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = walletModel.addAccountsFromPrivateKey(accountPKeyInput.text, passwordInput.text, accountNameInput.text, selectedColor)
|
||||||
|
loading = false
|
||||||
|
if (error) {
|
||||||
|
accountError.text = error
|
||||||
|
return accountError.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
walletModel.addAccountsFromPrivateKey(accountPKeyInput.text, passwordInput.text, accountNameInput.text, selectedColor)
|
|
||||||
// TODO manage errors adding account
|
|
||||||
popup.close();
|
popup.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
import "../../../../imports"
|
import "../../../../imports"
|
||||||
import "../../../../shared"
|
import "../../../../shared"
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ ModalPopup {
|
|||||||
property string passwordValidationError: ""
|
property string passwordValidationError: ""
|
||||||
property string seedValidationError: ""
|
property string seedValidationError: ""
|
||||||
property string accountNameValidationError: ""
|
property string accountNameValidationError: ""
|
||||||
|
property bool loading: false
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
if (passwordInput.text === "") {
|
if (passwordInput.text === "") {
|
||||||
@ -95,17 +97,31 @@ ModalPopup {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Theme.padding
|
anchors.rightMargin: Theme.padding
|
||||||
label: "Add account >"
|
label: loading ? qsTr("Loading...") : qsTr("Add account >")
|
||||||
|
|
||||||
disabled: passwordInput.text === "" || accountNameInput.text === "" || accountSeedInput.text === ""
|
disabled: loading || passwordInput.text === "" || accountNameInput.text === "" || accountSeedInput.text === ""
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: accountError
|
||||||
|
title: "Adding the account failed"
|
||||||
|
icon: StandardIcon.Critical
|
||||||
|
standardButtons: StandardButton.Ok
|
||||||
|
}
|
||||||
|
|
||||||
onClicked : {
|
onClicked : {
|
||||||
|
// TODO the loaidng doesn't work because the function freezes th eview. Might need to use threads
|
||||||
|
loading = true
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
return
|
return loading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = walletModel.addAccountsFromSeed(accountSeedInput.text, passwordInput.text, accountNameInput.text, selectedColor)
|
||||||
|
loading = false
|
||||||
|
if (error) {
|
||||||
|
accountError.text = error
|
||||||
|
return accountError.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
walletModel.addAccountsFromSeed(accountSeedInput.text, passwordInput.text, accountNameInput.text, selectedColor)
|
|
||||||
// TODO manage errors adding account
|
|
||||||
popup.close();
|
popup.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
import "../../../../imports"
|
import "../../../../imports"
|
||||||
import "../../../../shared"
|
import "../../../../shared"
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ ModalPopup {
|
|||||||
property string selectedColor: Constants.accountColors[0]
|
property string selectedColor: Constants.accountColors[0]
|
||||||
property string addressError: ""
|
property string addressError: ""
|
||||||
property string accountNameValidationError: ""
|
property string accountNameValidationError: ""
|
||||||
|
property bool loading: false
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
if (addressInput.text === "") {
|
if (addressInput.text === "") {
|
||||||
@ -73,17 +75,31 @@ ModalPopup {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Theme.padding
|
anchors.rightMargin: Theme.padding
|
||||||
label: "Add account >"
|
label: loading ? qsTr("Loading...") : qsTr("Add account >")
|
||||||
|
|
||||||
disabled: addressInput.text === "" || accountNameInput.text === ""
|
disabled: loading || addressInput.text === "" || accountNameInput.text === ""
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: accountError
|
||||||
|
title: "Adding the account failed"
|
||||||
|
icon: StandardIcon.Critical
|
||||||
|
standardButtons: StandardButton.Ok
|
||||||
|
}
|
||||||
|
|
||||||
onClicked : {
|
onClicked : {
|
||||||
|
// TODO the loaidng doesn't work because the function freezes th eview. Might need to use threads
|
||||||
|
loading = true
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
return
|
return loading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = walletModel.addWatchOnlyAccount(addressInput.text, accountNameInput.text, selectedColor);
|
||||||
|
loading = false
|
||||||
|
if (error) {
|
||||||
|
accountError.text = error
|
||||||
|
return accountError.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
walletModel.addWatchOnlyAccount(addressInput.text, accountNameInput.text, selectedColor);
|
|
||||||
// TODO manage errors adding account
|
|
||||||
popup.close();
|
popup.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
import "../../../../imports"
|
import "../../../../imports"
|
||||||
import "../../../../shared"
|
import "../../../../shared"
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ ModalPopup {
|
|||||||
property string selectedColor: Constants.accountColors[0]
|
property string selectedColor: Constants.accountColors[0]
|
||||||
property string passwordValidationError: ""
|
property string passwordValidationError: ""
|
||||||
property string accountNameValidationError: ""
|
property string accountNameValidationError: ""
|
||||||
|
property bool loading: false
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
if (passwordInput.text === "") {
|
if (passwordInput.text === "") {
|
||||||
@ -73,17 +75,31 @@ ModalPopup {
|
|||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Theme.padding
|
anchors.rightMargin: Theme.padding
|
||||||
label: "Add account >"
|
label: loading ? qsTr("Loading...") : qsTr("Add account >")
|
||||||
|
|
||||||
disabled: passwordInput.text === "" || accountNameInput.text === ""
|
disabled: loading || passwordInput.text === "" || accountNameInput.text === ""
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: accountError
|
||||||
|
title: "Adding the account failed"
|
||||||
|
icon: StandardIcon.Critical
|
||||||
|
standardButtons: StandardButton.Ok
|
||||||
|
}
|
||||||
|
|
||||||
onClicked : {
|
onClicked : {
|
||||||
|
// TODO the loaidng doesn't work because the function freezes th eview. Might need to use threads
|
||||||
|
loading = true
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
return
|
return loading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = walletModel.generateNewAccount(passwordInput.text, accountNameInput.text, selectedColor)
|
||||||
|
loading = false
|
||||||
|
if (error) {
|
||||||
|
accountError.text = error
|
||||||
|
return accountError.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
walletModel.generateNewAccount(passwordInput.text, accountNameInput.text, selectedColor);
|
|
||||||
// TODO manage errors adding account
|
|
||||||
popup.close();
|
popup.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,6 @@ Item {
|
|||||||
SVGImage {
|
SVGImage {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
// TODO replace by a real loading image
|
|
||||||
source: "../app/img/arrowUp.svg"
|
source: "../app/img/arrowUp.svg"
|
||||||
width: 13.5
|
width: 13.5
|
||||||
height: 17.5
|
height: 17.5
|
||||||
@ -176,6 +175,7 @@ Item {
|
|||||||
anchors.left: txtPassword.right
|
anchors.left: txtPassword.right
|
||||||
anchors.leftMargin: Theme.padding
|
anchors.leftMargin: Theme.padding
|
||||||
anchors.verticalCenter: txtPassword.verticalCenter
|
anchors.verticalCenter: txtPassword.verticalCenter
|
||||||
|
// TODO replace by a real loading image
|
||||||
source: "../app/img/settings.svg"
|
source: "../app/img/settings.svg"
|
||||||
width: 30
|
width: 30
|
||||||
height: 30
|
height: 30
|
||||||
|
Loading…
x
Reference in New Issue
Block a user