feat(@desktop/wallet): Entering asset value + using max button in its current state

fixes #16903
This commit is contained in:
Khushboo Mehta 2024-12-06 12:18:30 +01:00 committed by Khushboo-dev-cpp
parent 889f46b392
commit 909f518d3d
7 changed files with 325 additions and 153 deletions

View File

@ -5,6 +5,7 @@ import QtQuick.Controls 2.15
import SortFilterProxyModel 0.2
import StatusQ 0.1
import StatusQ.Core 0.1
import Models 1.0
import Storybook 1.0
@ -33,6 +34,15 @@ SplitView {
}
readonly property var walletAccountsModel: WalletAccountsModel{}
function getCurrencyAmount(amount, symbol) {
return ({
amount: amount,
symbol: symbol ? symbol.toUpperCase() : root.currentCurrency,
displayDecimals: 2,
stripTrailingZeroes: false
})
}
}
PopupBackground {
@ -60,11 +70,22 @@ SplitView {
modal: false
closePolicy: Popup.CloseOnEscape
interactive: interactiveCheckbox.checked
accountsModel: d.walletAccountsModel
assetsModel: assetsSelectorViewAdaptor.outputAssetsModel
collectiblesModel: collectiblesSelectionAdaptor.model
networksModel: d.filteredNetworksModel
currentCurrency: "USD"
fnFormatCurrencyAmount: function(amount, symbol, options = null, locale = null) {
if (isNaN(amount)) {
return "N/A"
}
var currencyAmount = d.getCurrencyAmount(amount, symbol)
return LocaleUtils.currencyAmountToLocaleString(currencyAmount, options, locale)
}
Binding on selectedAccountAddress {
value: accountsCombobox.currentValue ?? ""
}
@ -123,7 +144,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "",
communityName: "",
communityImage: Qt.resolvedUrl("")
communityImage: Qt.resolvedUrl(""),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_4",
@ -144,7 +166,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "",
communityName: "",
communityImage: Qt.resolvedUrl("")
communityImage: Qt.resolvedUrl(""),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_5",
@ -165,7 +188,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "",
communityName: "",
communityImage: Qt.resolvedUrl("")
communityImage: Qt.resolvedUrl(""),
tokenType: Constants.TokenType.ERC721
},
// collection 1
{
@ -192,7 +216,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "",
communityName: "",
communityImage: Qt.resolvedUrl("")
communityImage: Qt.resolvedUrl(""),
tokenType: Constants.TokenType.ERC1155
},
{
tokenId: "id_2",
@ -213,7 +238,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "",
communityName: "",
communityImage: Qt.resolvedUrl("")
communityImage: Qt.resolvedUrl(""),
tokenType: Constants.TokenType.ERC1155
},
// collection 3, community token
{
@ -235,7 +261,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_1",
communityName: "My community",
communityImage: Constants.tokenIcon("KIN", false)
communityImage: Constants.tokenIcon("KIN", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_7",
@ -256,7 +283,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_1",
communityName: "My community",
communityImage: Constants.tokenIcon("KIN", false)
communityImage: Constants.tokenIcon("KIN", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_8",
@ -277,7 +305,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_1",
communityName: "My community",
communityImage: Constants.tokenIcon("KIN", false)
communityImage: Constants.tokenIcon("KIN", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_9",
@ -298,7 +327,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_1",
communityName: "My community",
communityImage: Constants.tokenIcon("KIN", false)
communityImage: Constants.tokenIcon("KIN", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_10",
@ -319,7 +349,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_2",
communityName: "My community 2",
communityImage: Constants.tokenIcon("ICOS", false)
communityImage: Constants.tokenIcon("ICOS", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_11",
@ -340,7 +371,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_2",
communityName: "My community 2",
communityImage: Constants.tokenIcon("ICOS", false)
communityImage: Constants.tokenIcon("ICOS", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_11",
@ -361,7 +393,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_2",
communityName: "My community 2",
communityImage: Constants.tokenIcon("ICOS", false)
communityImage: Constants.tokenIcon("ICOS", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_12",
@ -382,7 +415,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_2",
communityName: "My community 2",
communityImage: Constants.tokenIcon("ICOS", false)
communityImage: Constants.tokenIcon("ICOS", false),
tokenType: Constants.TokenType.ERC721
},
{
tokenId: "id_13",
@ -403,7 +437,8 @@ SplitView {
mediaUrl: Qt.resolvedUrl(""),
communityId: "community_2",
communityName: "My community 2",
communityImage: Constants.tokenIcon("ICOS", false)
communityImage: Constants.tokenIcon("ICOS", false),
tokenType: Constants.TokenType.ERC721
}
]
@ -420,8 +455,10 @@ SplitView {
ColumnLayout {
spacing: 20
Text {
text: "Values to set before popup is launched"
CheckBox {
id: interactiveCheckbox
text: "Is interactive"
checked: true
}
Text {
@ -491,6 +528,28 @@ SplitView {
text: "token selected is: " + simpleSend.selectedTokenKey
}
RowLayout {
Layout.fillWidth: true
TextField {
id: amountInput
Layout.preferredWidth: 200
Layout.preferredHeight: 50
validator: RegularExpressionValidator {
regularExpression: /^\d*\.?\d*$/
}
}
Button {
text: "update in modal"
onClicked: simpleSend.selectedAmount = amountInput.text
}
}
Text {
text: "amount selected in base unit: " + simpleSend.selectedAmountInBaseUnit
}
Text {
text: "amount entered is: " + simpleSend.selectedAmount
}
RolesRenamingModel {
id: collectiblesKeyModel
sourceModel: collectiblesSelectionAdaptor.model

View File

@ -58,10 +58,6 @@ RowLayout {
/** input property for programatic selection of network **/
property int selectedChainId
/** input property for programatic selection of token
(asset/collectible/collection) **/
property string selectedTokenKey
/** signal to propagate that an asset was selected **/
signal assetSelected(string key)
/** signal to propagate that a collection was selected **/
@ -71,32 +67,10 @@ RowLayout {
/** signal to propagate that a network was selected **/
signal networkSelected(string chainId)
QtObject {
id: d
readonly property bool selectedTokenNotAvailableOnAssetsOrCollectiblesList: !selectedAssetEntry.available && !selectedCollectibleEntry.available
onSelectedTokenNotAvailableOnAssetsOrCollectiblesListChanged: {
if(selectedTokenNotAvailableOnAssetsOrCollectiblesList) {
// reset token selector in case selected tokens doesnt exist in either models
tokenSelector.setSelection("", "", "")
}
}
function updateAssetInTokenSelector(available, item) {
if(available) {
tokenSelector.setSelection(item.symbol,
Constants.tokenIcon(item.symbol),
item.tokensKey)
}
}
function updateCollectibleInTokenSelector(available, item) {
if(available) {
const id = item.communityId ? item.collectionUid : item.uid
tokenSelector.setSelection(item.name,
item.imageUrl || item.mediaUrl,
id)
}
}
/** input function for programatic selection of token
(asset/collectible/collection) **/
function setToken(name, icon, key) {
tokenSelector.setSelection(name, icon, key)
}
implicitHeight: sendModalTitleText.height
@ -181,22 +155,4 @@ RowLayout {
onToggleNetwork: root.networkSelected(chainId)
}
ModelEntry {
id: selectedAssetEntry
sourceModel: root.assetsModel
key: "tokensKey"
value: root.selectedTokenKey
onAvailableChanged: d.updateAssetInTokenSelector(available, item)
onItemChanged: d.updateAssetInTokenSelector(available, item)
}
ModelEntry {
id: selectedCollectibleEntry
sourceModel: root.collectiblesModel
key: "symbol"
value: root.selectedTokenKey
onAvailableChanged: d.updateCollectibleInTokenSelector(available, item)
onItemChanged: d.updateCollectibleInTokenSelector(available, item)
}
}

View File

@ -53,10 +53,6 @@ Rectangle {
/** input property for programatic selection of network **/
property int selectedChainId: -1
/** input property for programatic selection of token
(asset/collectible/collection) **/
property string selectedTokenKey
/** signal to propagate that an asset was selected **/
signal assetSelected(string key)
/** signal to propagate that a collection was selected **/
@ -66,6 +62,12 @@ Rectangle {
/** signal to propagate that a network was selected **/
signal networkSelected(string chainId)
/** input function for programatic selection of token
(asset/collectible/collection) **/
function setToken(name, icon, key) {
sendModalHeader.setToken(name, icon, key)
}
enabled: root.isScrolling
color: Theme.palette.baseColor3
radius: 8
@ -114,7 +116,6 @@ Rectangle {
collectiblesModel: root.collectiblesModel
selectedChainId: root.selectedChainId
selectedTokenKey: root.selectedTokenKey
onCollectibleSelected: root.collectibleSelected(key)
onCollectionSelected: root.collectionSelected(key)

View File

@ -1,15 +1,22 @@
import QtQuick 2.15
import QtQuick.Layouts 1.14
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Popups.Dialog 0.1
import StatusQ.Core.Backpressure 0.1
import shared.popups.send.views 1.0
import shared.controls 1.0
import AppLayouts.Wallet.panels 1.0
import AppLayouts.Wallet.controls 1.0
import AppLayouts.Wallet 1.0
import utils 1.0
StatusDialog {
id: root
@ -64,33 +71,124 @@ StatusDialog {
Only networks valid as per mainnet/testnet selection
**/
required property var networksModel
/** Input property holds currently selected Fiat currency **/
required property string currentCurrency
/** Input function to format currency amount to locale string **/
required property var fnFormatCurrencyAmount
/** input property to decide if send mdoal is interactive or prefilled**/
property bool interactive
/** property to set and expose currently selected account **/
property string selectedAccountAddress
/** property to set and expose currently selected network **/
property int selectedChainId
/** property to set and expose currently selected token key **/
property string selectedTokenKey
/** property to set and expose the amount to send from outside without any localization **/
property string selectedAmount
/** output property to set currently set amount to send
Crypto value in a base unit as a string integer,
e.g. 1000000000000000000 for 1 ETH **/
readonly property string selectedAmountInBaseUnit: amountToSend.amount
QtObject {
id: d
readonly property bool isScrolling:
scrollView.flickable.contentY > sendModalHeader.height
// Used to get asset entry if selected token is an asset
readonly property var selectedAssetEntry: ModelEntry {
sourceModel: root.assetsModel
key: "tokensKey"
value: root.selectedTokenKey
}
// Used to get collectible entry if selected token is a collectible
readonly property var selectedCollectibleEntry: ModelEntry {
sourceModel: root.collectiblesModel
key: "symbol"
value: root.selectedTokenKey
}
/** exposes the currently selected token entry **/
readonly property var selectedTokenEntry: selectedAssetEntry.available ?
selectedAssetEntry.item :
selectedCollectibleEntry.available ?
selectedCollectibleEntry.item: null
onSelectedTokenEntryChanged: {
if(!selectedAssetEntry.available && !selectedCollectibleEntry.available) {
d.debounceResetTokenSelector()
}
if(selectedAssetEntry.available && !!selectedTokenEntry) {
d.setTokenOnBothHeaders(selectedTokenEntry.symbol,
Constants.tokenIcon(selectedTokenEntry.symbol),
selectedTokenEntry.tokensKey)
}
else if(selectedCollectibleEntry.available && !!selectedTokenEntry) {
const id = selectedTokenEntry.communityId ?
selectedTokenEntry.collectionUid :
selectedTokenEntry.uid
d.setTokenOnBothHeaders(selectedTokenEntry.name,
selectedTokenEntry.imageUrl || selectedTokenEntry.mediaUrl,
id)
}
}
function setTokenOnBothHeaders(name, icon, key) {
sendModalHeader.setToken(name, icon, key)
stickySendModalHeader.setToken(name, icon, key)
}
readonly property var debounceResetTokenSelector: Backpressure.debounce(root, 0, function() {
if(!selectedAssetEntry.available && !selectedCollectibleEntry.available) {
// reset token selector in case selected tokens doesnt exist in either models
d.setTokenOnBothHeaders("", "", "")
root.selectedTokenKey = ""
}
})
readonly property bool isCollectibleSelected: {
if(!selectedTokenEntry)
return false
const type = selectedAssetEntry.available ? selectedAssetEntry.item.type :
selectedCollectibleEntry.available ? selectedCollectibleEntry.item.tokenType :
Constants.TokenType.Unknown
return (type === Constants.TokenType.ERC721 || type === Constants.TokenType.ERC1155)
}
readonly property string selectedCryptoTokenSymbol: !!d.selectedTokenEntry ?
d.selectedTokenEntry.symbol: ""
readonly property double maxSafeCryptoValue: {
const maxCryptoBalance = !!d.selectedTokenEntry && !!d.selectedTokenEntry.currentBalance ?
d.selectedTokenEntry.currentBalance : 0
return WalletUtils.calculateMaxSafeSendAmount(maxCryptoBalance, d.selectedCryptoTokenSymbol)
}
}
width: 556
padding: 0
leftPadding: Theme.xlPadding
rightPadding: Theme.xlPadding
bottomPadding: Theme.xlPadding
topMargin: margins + accountSelector.height + Theme.padding
background: StatusDialogBackground {
color: Theme.palette.baseColor3
}
// Bindings needed for exposing and setting raw values from AmountToSend
Binding on selectedAmount {
value: amountToSend.text
}
onSelectedAmountChanged: {
if(!!selectedAmount && amountToSend.text !== root.selectedAmount) {
amountToSend.setValue(root.selectedAmount)
}
}
Item {
id: sendModalcontentItem
@ -121,6 +219,8 @@ StatusDialog {
// Sticky header only visible when scrolling
StickySendModalHeader {
id: stickySendModalHeader
width: root.width
anchors.top: accountSelector.bottom
anchors.topMargin:Theme.padding
@ -135,7 +235,6 @@ StatusDialog {
collectiblesModel: root.collectiblesModel
selectedChainId: root.selectedChainId
selectedTokenKey: root.selectedTokenKey
onCollectibleSelected: root.selectedTokenKey = key
onCollectionSelected: root.selectedTokenKey = key
@ -148,7 +247,6 @@ StatusDialog {
id: scrollView
anchors.fill: parent
anchors.topMargin: 28
contentWidth: availableWidth
padding: 0
@ -171,6 +269,7 @@ StatusDialog {
id: sendModalHeader
Layout.fillWidth: true
Layout.topMargin: 28
isScrolling: d.isScrolling
@ -179,7 +278,6 @@ StatusDialog {
collectiblesModel: root.collectiblesModel
selectedChainId: root.selectedChainId
selectedTokenKey: root.selectedTokenKey
onCollectibleSelected: root.selectedTokenKey = key
onCollectionSelected: root.selectedTokenKey = key
@ -187,31 +285,66 @@ StatusDialog {
onNetworkSelected: root.selectedChainId = chainId
}
// TODO: Remove these Dummy items added only to test dialog resizing
readonly property string longLoremIpsum: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
Text {
// Amount to send entry
AmountToSend {
id: amountToSend
Layout.fillWidth: true
text: scrollViewLayout.longLoremIpsum.repeat(3)
wrapMode: Text.WordWrap
interactive: root.interactive
dividerVisible: true
progressivePixelReduction: false
/** TODO: connect this with suggested routes being fetched as price
gets updated each time a new proposal is fetched
bottomTextLoading: root.suggestedRoutesLoading **/
/** TODO: connect to max safe value for eth.
For now simply checking balance in case of both eth and other ERC20's **/
markAsInvalid: SQUtils.AmountsArithmetic.fromNumber(d.maxSafeCryptoValue, multiplierIndex).cmp(amount) === -1
selectedSymbol: amountToSend.fiatMode ?
root.currentCurrency:
d.selectedCryptoTokenSymbol
price: !!d.selectedTokenEntry &&
!!d.selectedTokenEntry.marketDetails ?
d.selectedTokenEntry.marketDetails.currencyPrice.amount : 1
multiplierIndex: !!d.selectedTokenEntry &&
!!d.selectedTokenEntry.decimals ?
d.selectedTokenEntry.decimals : 0
formatFiat: amount => root.fnFormatCurrencyAmount(
amount, root.currentCurrency)
formatBalance: amount => root.fnFormatCurrencyAmount(
amount, d.selectedCryptoTokenSymbol)
visible: !!root.selectedTokenKey && !d.isCollectibleSelected
onVisibleChanged: if(visible) forceActiveFocus()
bottomRightComponent: MaxSendButton {
id: maxButton
formattedValue: {
const price = !!d.selectedTokenEntry && !!d.selectedTokenEntry.marketDetails ?
d.selectedTokenEntry.marketDetails.currencyPrice.amount : 0
let maxSafeValue = amountToSend.fiatMode ? d.maxSafeCryptoValue * price : d.maxSafeCryptoValue
return root.fnFormatCurrencyAmount(
maxSafeValue,
amountToSend.selectedSymbol,
{ noSymbol: !amountToSend.fiatMode,
roundingMode: LocaleUtils.RoundingMode.Down
})
}
markAsInvalid: amountToSend.markAsInvalid
/** TODO: Remove below customisations after
https://github.com/status-im/status-desktop/issues/15709
and make the button clickable **/
enabled: false
background: Rectangle {
radius: 20
color: type === StatusBaseButton.Type.Danger ? Theme.palette.dangerColor3 : Theme.palette.primaryColor3
}
disabledTextColor: type === StatusBaseButton.Type.Danger ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 200
opacity: 0.2
color: "red"
}
Text {
Layout.fillWidth: true
text: scrollViewLayout.longLoremIpsum.repeat(3)
wrapMode: Text.WordWrap
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 200
opacity: 0.2
color: "red"
}
// End Dummy items
}
}
}

View File

@ -660,6 +660,7 @@ Item {
simpleSendEnabled: appMain.featureFlagsStore.simpleSendEnabled
// for simple send
walletAccountsModel: WalletStores.RootStore.accounts
flatNetworksModel: WalletStores.RootStore.flatNetworks
areTestNetworksEnabled: WalletStores.RootStore.areTestNetworksEnabled
@ -667,6 +668,9 @@ Item {
currentCurrency: appMain.currencyStore.currentCurrency
showCommunityAssetsInSend: appMain.tokensStore.showCommunityAssetsInSend
collectiblesBySymbolModel: WalletStores.RootStore.collectiblesStore.jointCollectiblesBySymbolModel
fnFormatCurrencyAmount: function(amount, symbol, options = null, locale = null) {
return appMain.currencyStore.formatCurrencyAmount(amount, symbol)
}
Component.onCompleted: {
// It's requested from many nested places, so as a workaround we use

View File

@ -86,6 +86,8 @@ QtObject {
/** whether community tokens are shown in send modal
based on a global setting **/
required property var showCommunityAssetsInSend
/** required function to format currency amount to locale string **/
required property var fnFormatCurrencyAmount
function openSend(params = {}) {
// TODO remove once simple send is feature complete
@ -230,6 +232,9 @@ QtObject {
collectiblesModel: collectiblesSelectionAdaptor.model
networksModel: root.filteredFlatNetworksModel
currentCurrency: root.currentCurrency
fnFormatCurrencyAmount: root.fnFormatCurrencyAmount
onClosed: destroy()
TokenSelectorViewAdaptor {
@ -252,7 +257,13 @@ QtObject {
enabledChainIds: [simpleSendModal.selectedChainId]
networksModel: root.filteredFlatNetworksModel
collectiblesModel: root.collectiblesBySymbolModel
collectiblesModel: SortFilterProxyModel {
sourceModel: root.collectiblesBySymbolModel
filters: ValueFilter {
roleName: "soulbound"
value: false
}
}
}
}
}

View File

@ -76,6 +76,10 @@ Control {
property bool mainInputLoading
property bool bottomTextLoading
/* This allows user to add a component to the right of bottom text
Not set = not shown */
property alias bottomRightComponent: bottomRightComponent.sourceComponent
/* Allows mark input as invalid when it's valid number but doesn't satisfy
* arbitrary external criteria, e.g. is higher than maximum expected value. */
property bool markAsInvalid: false
@ -193,14 +197,11 @@ Control {
return validator.maxDecimalDigits + validator.maxIntegralDigits
} else {
let availableSpaceForAmount = root.availableWidth - currencyField.contentWidth - layout.spacing
return Math.floor(availableSpaceForAmount/textMetrics.tightBoundingRect.width)
// k is a coefficient based on the font style (typically 𝑘 0.6)
let digitWidth = textField.font.pixelSize * 0.6
return Math.floor(availableSpaceForAmount/digitWidth)
}
}
readonly property TextMetrics textMetrics: TextMetrics {
font: textField.font
text: "0"
}
}
contentItem: ColumnLayout {
@ -285,66 +286,73 @@ Control {
Layout.fillWidth: true
Layout.preferredHeight: 1
Layout.bottomMargin: 12
color: Theme.palette.separator
color: Theme.palette.directColor8
visible: root.dividerVisible
}
StatusBaseText {
id: bottomItem
objectName: "bottomItemText"
RowLayout {
Layout.fillWidth: true
StatusBaseText {
id: bottomItem
text: {
const divisor = SQUtils.AmountsArithmetic.fromExponent(
d.fiatMode ? root.multiplierIndex
: root.fiatDecimalPlaces)
const divided = SQUtils.AmountsArithmetic.div(
SQUtils.AmountsArithmetic.fromString(
d.secondaryValue), divisor)
const asNumber = SQUtils.AmountsArithmetic.toNumber(divided)
objectName: "bottomItemText"
return d.fiatMode ? root.formatBalance(asNumber)
: root.formatFiat(asNumber)
}
Layout.fillWidth: true
elide: Text.ElideMiddle
font.pixelSize: 13
color: Theme.palette.directColor5
MouseArea {
objectName: "amountToSend_mouseArea"
anchors.fill: parent
cursorShape: enabled ? Qt.PointingHandCursor : undefined
enabled: root.fiatInputInteractive
onClicked: {
const secondaryValue = d.secondaryValue
d.fiatMode = !d.fiatMode
if (textField.length === 0)
return
const decimalPlaces = d.fiatMode ? root.fiatDecimalPlaces
: root.multiplierIndex
text: {
const divisor = SQUtils.AmountsArithmetic.fromExponent(
decimalPlaces)
d.fiatMode ? root.multiplierIndex
: root.fiatDecimalPlaces)
const divided = SQUtils.AmountsArithmetic.div(
SQUtils.AmountsArithmetic.fromString(
d.secondaryValue), divisor)
const asNumber = SQUtils.AmountsArithmetic.toNumber(divided)
const stringNumber = SQUtils.AmountsArithmetic.div(
SQUtils.AmountsArithmetic.fromString(secondaryValue),
divisor).toFixed(decimalPlaces)
const trimmed = d.fiatMode
? stringNumber
: d.removeDecimalTrailingZeros(stringNumber)
textField.text = d.localize(trimmed)
return d.fiatMode ? root.formatBalance(asNumber)
: root.formatFiat(asNumber)
}
elide: Text.ElideMiddle
font.pixelSize: 13
color: Theme.palette.directColor5
MouseArea {
objectName: "amountToSend_mouseArea"
anchors.fill: parent
cursorShape: enabled ? Qt.PointingHandCursor : undefined
enabled: root.fiatInputInteractive
onClicked: {
const secondaryValue = d.secondaryValue
d.fiatMode = !d.fiatMode
if (textField.length === 0)
return
const decimalPlaces = d.fiatMode ? root.fiatDecimalPlaces
: root.multiplierIndex
const divisor = SQUtils.AmountsArithmetic.fromExponent(
decimalPlaces)
const stringNumber = SQUtils.AmountsArithmetic.div(
SQUtils.AmountsArithmetic.fromString(secondaryValue),
divisor).toFixed(decimalPlaces)
const trimmed = d.fiatMode
? stringNumber
: d.removeDecimalTrailingZeros(stringNumber)
textField.text = d.localize(trimmed)
}
}
visible: !root.bottomTextLoading
}
Loader {
id: bottomRightComponent
Layout.alignment: Qt.AlignVCenter
}
visible: !root.bottomTextLoading
}
LoadingComponent {