feat(StatusQ.Controls): introduce `StatusAccountSelector` component
This commit moves the original `AccountSelector` into StatusQ and makes it a `StatusAccountSelector`. The API has been preserved. The only difference is that it's internally relying completely on `StatusQ.Core.Theme` and `StatusQ.Controls` components instead. Usage: ```qml import StatusQ.Controls 0.1 StatusAccountSelector { accounts: ListModel { ListElement { name: "Pascal" address: "0x1234567891011" iconColor: "red" balance: "0" walletType: "generated" assets: [] fiatBalance: "1199.02" } ListElement { name: "Boris" address: "0x123" iconColor: "red" balance: "0" walletType: "generated" assets: [] fiatBalance: "0" } ListElement { name: "Alexandra" address: "0x123" iconColor: "yellow" balance: "0" walletType: "generated" assets: [] fiatBalance: "0" } ListElement { name: "Khushboo" address: "0x123" iconColor: "blue" balance: "0" walletType: "generated" assets: [] fiatBalance: "0" } } } ``` Closes #435
This commit is contained in:
parent
03c6da6e9f
commit
9389ee256e
|
@ -0,0 +1,55 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Popups 0.1
|
||||||
|
|
||||||
|
import Sandbox 0.1
|
||||||
|
|
||||||
|
Column {
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
StatusAccountSelector {
|
||||||
|
accounts: ListModel {
|
||||||
|
ListElement {
|
||||||
|
name: "Pascal"
|
||||||
|
address: "0x1234567891011"
|
||||||
|
iconColor: "red"
|
||||||
|
balance: "0"
|
||||||
|
walletType: "generated"
|
||||||
|
assets: []
|
||||||
|
fiatBalance: "1199.02"
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
name: "Boris"
|
||||||
|
address: "0x123"
|
||||||
|
iconColor: "red"
|
||||||
|
balance: "0"
|
||||||
|
walletType: "generated"
|
||||||
|
assets: []
|
||||||
|
fiatBalance: "0"
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
name: "Alexandra"
|
||||||
|
address: "0x123"
|
||||||
|
iconColor: "yellow"
|
||||||
|
balance: "0"
|
||||||
|
walletType: "generated"
|
||||||
|
assets: []
|
||||||
|
fiatBalance: "0"
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
name: "Khushboo"
|
||||||
|
address: "0x123"
|
||||||
|
iconColor: "blue"
|
||||||
|
balance: "0"
|
||||||
|
walletType: "generated"
|
||||||
|
assets: []
|
||||||
|
fiatBalance: "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -158,6 +158,11 @@ StatusWindow {
|
||||||
selected: page.sourceComponent == statusSelectPageComponent
|
selected: page.sourceComponent == statusSelectPageComponent
|
||||||
onClicked: page.sourceComponent = statusSelectPageComponent
|
onClicked: page.sourceComponent = statusSelectPageComponent
|
||||||
}
|
}
|
||||||
|
StatusNavigationListItem {
|
||||||
|
title: "StatusAccountSelector"
|
||||||
|
selected: page.sourceComponent == statusAccountSelectorPageComponent
|
||||||
|
onClicked: page.sourceComponent = statusAccountSelectorPageComponent
|
||||||
|
}
|
||||||
StatusListSectionHeadline { text: "StatusQ.Components" }
|
StatusListSectionHeadline { text: "StatusQ.Components" }
|
||||||
StatusNavigationListItem {
|
StatusNavigationListItem {
|
||||||
title: "List Items"
|
title: "List Items"
|
||||||
|
@ -266,6 +271,11 @@ StatusWindow {
|
||||||
StatusSelectPage {}
|
StatusSelectPage {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: statusAccountSelectorPageComponent
|
||||||
|
StatusAccountSelectorPage {}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: listItemsComponent
|
id: listItemsComponent
|
||||||
ListItems {}
|
ListItems {}
|
||||||
|
|
|
@ -0,0 +1,277 @@
|
||||||
|
import QtQuick 2.13
|
||||||
|
import QtQuick.Controls 2.13
|
||||||
|
import QtQuick.Layouts 1.13
|
||||||
|
import QtQml.Models 2.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
property string label: "Choose account"
|
||||||
|
property bool showAccountDetails: !!selectedAccount
|
||||||
|
property var accounts
|
||||||
|
property var selectedAccount
|
||||||
|
property string currency: "usd"
|
||||||
|
property alias selectField: select
|
||||||
|
implicitWidth: 448
|
||||||
|
height: select.height +
|
||||||
|
(selectedAccountDetails.visible ? selectedAccountDetails.height + selectedAccountDetails.anchors.topMargin : 0)
|
||||||
|
// set to asset symbol to display asset's balance top right
|
||||||
|
// NOTE: if this asset is not selected as a wallet token in the UI, then
|
||||||
|
// nothing will be displayed
|
||||||
|
property string showBalanceForAssetSymbol: ""
|
||||||
|
property var assetFound
|
||||||
|
property double minRequiredAssetBalance: 0
|
||||||
|
property int dropdownWidth: width
|
||||||
|
property alias dropdownAlignment: select.menuAlignment
|
||||||
|
property bool isValid: true
|
||||||
|
property bool readOnly: false
|
||||||
|
|
||||||
|
property var assetBalanceTextFn: function (foundValue) {
|
||||||
|
return "Balance: " + (parseFloat(foundValue) === 0.0 ? "0" : Utils.stripTrailingZeros(foundValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property string watchWalletType: "watch"
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
Address,
|
||||||
|
Contact,
|
||||||
|
Account
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate() {
|
||||||
|
if (showBalanceForAssetSymbol == "" || minRequiredAssetBalance == 0 || !assetFound) {
|
||||||
|
return root.isValid
|
||||||
|
}
|
||||||
|
root.isValid = assetFound.value >= minRequiredAssetBalance
|
||||||
|
return root.isValid
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectedAccountChanged: {
|
||||||
|
if (!selectedAccount) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (selectedAccount.iconColor) {
|
||||||
|
selectedIconImg.color = Utils.getThemeAccountColor(selectedAccount.iconColor, Theme.palette.accountColors) || Theme.palette.accountColors[0]
|
||||||
|
}
|
||||||
|
if (selectedAccount.name) {
|
||||||
|
selectedTextField.text = selectedAccount.name
|
||||||
|
}
|
||||||
|
if (selectedAccount.address) {
|
||||||
|
textSelectedAddress.text = selectedAccount.address + " •"
|
||||||
|
}
|
||||||
|
if (selectedAccount.fiatBalance) {
|
||||||
|
textSelectedAddressFiatBalance.text = selectedAccount.fiatBalance + " " + currency.toUpperCase()
|
||||||
|
}
|
||||||
|
if (selectedAccount.assets && showBalanceForAssetSymbol) {
|
||||||
|
assetFound = Utils.findAssetBySymbol(selectedAccount.assets, showBalanceForAssetSymbol)
|
||||||
|
if (!assetFound) {
|
||||||
|
console.warn("Cannot find asset '", showBalanceForAssetSymbol, "'. Ensure this asset has been added to the token list.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!selectedAccount.type) {
|
||||||
|
selectedAccount.type = StatusAccountSelector.Type.Account
|
||||||
|
}
|
||||||
|
validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
onAssetFoundChanged: {
|
||||||
|
if (!assetFound) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
txtAssetBalance.text = root.assetBalanceTextFn(assetFound.value)
|
||||||
|
txtAssetSymbol.text = " " + assetFound.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: txtAssetBalance
|
||||||
|
visible: root.assetFound !== undefined
|
||||||
|
anchors.bottom: select.top
|
||||||
|
anchors.bottomMargin: -18
|
||||||
|
anchors.right: txtAssetSymbol.left
|
||||||
|
anchors.left: select.left
|
||||||
|
anchors.leftMargin: select.width / 2.5
|
||||||
|
|
||||||
|
color: !root.isValid ? Theme.palette.dangerColor1 : Theme.palette.baseColor1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pixelSize: 13
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
height: 18
|
||||||
|
|
||||||
|
StatusToolTip {
|
||||||
|
enabled: txtAssetBalance.truncated
|
||||||
|
id: assetTooltip
|
||||||
|
text: txtAssetBalance.text
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
enabled: txtAssetBalance.truncated
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: enabled
|
||||||
|
onEntered: assetTooltip.visible = true
|
||||||
|
onExited: assetTooltip.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
id: txtAssetSymbol
|
||||||
|
visible: txtAssetBalance.visible
|
||||||
|
anchors.top: txtAssetBalance.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
color: txtAssetBalance.color
|
||||||
|
font.pixelSize: 13
|
||||||
|
height: txtAssetBalance.height
|
||||||
|
}
|
||||||
|
StatusSelect {
|
||||||
|
id: select
|
||||||
|
label: root.label
|
||||||
|
model: root.accounts
|
||||||
|
width: parent.width
|
||||||
|
menuAlignment: StatusSelect.MenuAlignment.Left
|
||||||
|
selectMenu.delegate: menuItem
|
||||||
|
selectMenu.width: dropdownWidth
|
||||||
|
selectedItemComponent: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
StatusIcon {
|
||||||
|
id: selectedIconImg
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 20
|
||||||
|
height: 20
|
||||||
|
icon: "filled-account"
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: selectedTextField
|
||||||
|
elide: Text.ElideRight
|
||||||
|
anchors.left: selectedIconImg.right
|
||||||
|
anchors.leftMargin: 8
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: select.selectedItemRightMargin
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font.pixelSize: 15
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
height: 22
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: selectedAccountDetails
|
||||||
|
visible: root.showAccountDetails
|
||||||
|
anchors.top: select.bottom
|
||||||
|
anchors.topMargin: 8
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 2
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: textSelectedAddress
|
||||||
|
font.pixelSize: 12
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
width: 90
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
id: textSelectedAddressFiatBalance
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: menuItem
|
||||||
|
MenuItem {
|
||||||
|
id: itemContainer
|
||||||
|
visible: walletType !== root.watchWalletType
|
||||||
|
property bool isFirstItem: index === 0
|
||||||
|
property bool isLastItem: index === accounts.rowCount() - 1
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (!root.selectedAccount && isFirstItem) {
|
||||||
|
root.selectedAccount = { address, name, iconColor, assets, fiatBalance }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
height: walletType === root.watchWalletType ? 0 : (accountName.height + 14 + accountAddress.height + 14)
|
||||||
|
|
||||||
|
StatusIcon {
|
||||||
|
id: iconImg
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
width: 20
|
||||||
|
height: 20
|
||||||
|
icon: "filled-account"
|
||||||
|
color: Utils.getThemeAccountColor(iconColor, Theme.palette.accountColors) || Theme.palette.accountColors[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
anchors.left: iconImg.right
|
||||||
|
anchors.leftMargin: 14
|
||||||
|
anchors.right: txtFiatBalance.left
|
||||||
|
anchors.rightMargin: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: accountName
|
||||||
|
text: name
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pixelSize: 15
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: 22
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
id: accountAddress
|
||||||
|
text: address
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
width: 80
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
font.pixelSize: 12
|
||||||
|
height: 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
id: txtFiatBalance
|
||||||
|
anchors.right: fiatCurrencySymbol.left
|
||||||
|
anchors.rightMargin: 4
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
text: fiatBalance
|
||||||
|
color: Theme.palette.directColor1
|
||||||
|
}
|
||||||
|
StatusBaseText {
|
||||||
|
id: fiatCurrencySymbol
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
font.pixelSize: 15
|
||||||
|
height: 22
|
||||||
|
color: Theme.palette.baseColor1
|
||||||
|
text: root.currency.toUpperCase()
|
||||||
|
}
|
||||||
|
background: Rectangle {
|
||||||
|
color: itemContainer.highlighted ? Theme.palette.statusSelect.menuItemHoverBackgroundColor : Theme.palette.statusSelect.menuItemBackgroundColor
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
anchors.fill: itemContainer
|
||||||
|
onClicked: {
|
||||||
|
root.selectedAccount = { address, name, iconColor, assets, fiatBalance }
|
||||||
|
select.selectMenu.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module StatusQ.Controls
|
module StatusQ.Controls
|
||||||
|
|
||||||
|
StatusAccountSelector 0.1 StatusAccountSelector.qml
|
||||||
StatusChatInfoButton 0.1 StatusChatInfoButton.qml
|
StatusChatInfoButton 0.1 StatusChatInfoButton.qml
|
||||||
StatusChatListCategoryItemButton 0.1 StatusChatListCategoryItemButton.qml
|
StatusChatListCategoryItemButton 0.1 StatusChatListCategoryItemButton.qml
|
||||||
StatusIconTabButton 0.1 StatusIconTabButton.qml
|
StatusIconTabButton 0.1 StatusIconTabButton.qml
|
||||||
|
|
|
@ -146,6 +146,17 @@ ThemePalette {
|
||||||
miscColor10: getColor('brown3')
|
miscColor10: getColor('brown3')
|
||||||
miscColor11: getColor('yellow2')
|
miscColor11: getColor('yellow2')
|
||||||
|
|
||||||
|
accountColors: [
|
||||||
|
getColor('blue5'),
|
||||||
|
getColor('yellow2'),
|
||||||
|
"#E6ABFC",
|
||||||
|
getColor('moss2'),
|
||||||
|
"#FB8383",
|
||||||
|
getColor('green4'),
|
||||||
|
"#ADA3FF",
|
||||||
|
getColor('brown3')
|
||||||
|
]
|
||||||
|
|
||||||
property QtObject statusAppLayout: QtObject {
|
property QtObject statusAppLayout: QtObject {
|
||||||
property color backgroundColor: baseColor3
|
property color backgroundColor: baseColor3
|
||||||
property color rightPanelBackgroundColor: baseColor3
|
property color rightPanelBackgroundColor: baseColor3
|
||||||
|
|
|
@ -144,6 +144,17 @@ ThemePalette {
|
||||||
miscColor10: getColor('brown')
|
miscColor10: getColor('brown')
|
||||||
miscColor11: getColor('brown2')
|
miscColor11: getColor('brown2')
|
||||||
|
|
||||||
|
accountColors: [
|
||||||
|
getColor('blue'),
|
||||||
|
getColor('brown2'),
|
||||||
|
getColor('violet'),
|
||||||
|
"#1D806F",
|
||||||
|
getColor('red2'),
|
||||||
|
getColor('green2'),
|
||||||
|
getColor('purple'),
|
||||||
|
getColor('brown')
|
||||||
|
]
|
||||||
|
|
||||||
property QtObject statusAppLayout: QtObject {
|
property QtObject statusAppLayout: QtObject {
|
||||||
property color backgroundColor: white
|
property color backgroundColor: white
|
||||||
property color rightPanelBackgroundColor: white
|
property color rightPanelBackgroundColor: white
|
||||||
|
|
|
@ -89,6 +89,8 @@ QtObject {
|
||||||
property color miscColor10
|
property color miscColor10
|
||||||
property color miscColor11
|
property color miscColor11
|
||||||
|
|
||||||
|
property var accountColors: []
|
||||||
|
|
||||||
property QtObject statusAppLayout: QtObject {
|
property QtObject statusAppLayout: QtObject {
|
||||||
property color backgroundColor
|
property color backgroundColor
|
||||||
property color rightPanelBackgroundColor
|
property color rightPanelBackgroundColor
|
||||||
|
|
|
@ -30,6 +30,43 @@ QtObject {
|
||||||
function uuid() {
|
function uuid() {
|
||||||
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
|
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getThemeAccountColor(c, accountColors) {
|
||||||
|
const upperCaseColor = c.toUpperCase()
|
||||||
|
let colorIndex = accountColors.indexOf(upperCaseColor)
|
||||||
|
|
||||||
|
if (colorIndex > -1) {
|
||||||
|
return upperCaseColor
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function findAssetBySymbol(assets, symbolToFind) {
|
||||||
|
for(var i=0; i<assets.rowCount(); i++) {
|
||||||
|
const symbol = assets.rowData(i, "symbol")
|
||||||
|
if (symbol.toLowerCase() === symbolToFind.toLowerCase()) {
|
||||||
|
return {
|
||||||
|
name: assets.rowData(i, "name"),
|
||||||
|
symbol,
|
||||||
|
value: assets.rowData(i, "value"),
|
||||||
|
fiatBalanceDisplay: assets.rowData(i, "fiatBalanceDisplay"),
|
||||||
|
address: assets.rowData(i, "address"),
|
||||||
|
fiatBalance: assets.rowData(i, "fiatBalance")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripTrailingZeros(strNumber) {
|
||||||
|
if (!(typeof strNumber === "string")) {
|
||||||
|
try {
|
||||||
|
strNumber = strNumber.toString()
|
||||||
|
} catch(e) {
|
||||||
|
throw "[Utils.stripTrailingZeros] input parameter must be a string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strNumber.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
<file>src/StatusQ/Controls/StatusIconTabButton.qml</file>
|
<file>src/StatusQ/Controls/StatusIconTabButton.qml</file>
|
||||||
<file>src/StatusQ/Controls/StatusChatInfoButton.qml</file>
|
<file>src/StatusQ/Controls/StatusChatInfoButton.qml</file>
|
||||||
<file>src/StatusQ/Controls/qmldir</file>
|
<file>src/StatusQ/Controls/qmldir</file>
|
||||||
|
<file>src/StatusQ/Controls/StatusAccountSelector.qml</file>
|
||||||
<file>src/StatusQ/Controls/StatusSlider.qml</file>
|
<file>src/StatusQ/Controls/StatusSlider.qml</file>
|
||||||
<file>src/StatusQ/Controls/StatusRoundButton.qml</file>
|
<file>src/StatusQ/Controls/StatusRoundButton.qml</file>
|
||||||
<file>src/StatusQ/Controls/StatusNavBarTabButton.qml</file>
|
<file>src/StatusQ/Controls/StatusNavBarTabButton.qml</file>
|
||||||
|
|
Loading…
Reference in New Issue