chire(@desktop/wallet): Streamline send modal folder structure

fixes #12140
This commit is contained in:
Khushboo Mehta 2023-09-05 17:27:30 +02:00 committed by Khushboo-dev-cpp
parent a75890d7be
commit 1d99d8ae97
63 changed files with 71 additions and 2199 deletions

View File

@ -6,7 +6,7 @@ import Models 1.0
import Storybook 1.0
import utils 1.0
import shared.popups 1.0
import shared.popups.send 1.0
import shared.stores 1.0
import StatusQ.Core.Utils 0.1

View File

@ -14,7 +14,7 @@ import utils 1.0
import shared.controls 1.0
import shared 1.0
import shared.status 1.0
import shared.popups 1.0
import shared.popups.send 1.0
import "popups"
import "controls"

View File

@ -1,174 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import utils 1.0
import shared.controls 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import StatusQ.Controls 0.1
import shared.views 1.0
import shared.panels 1.0
StatusModal {
property var store
property var contactsStore
property string commandTitle: qsTr("Send")
property string finalButtonLabel: qsTr("Request address")
property var sendChatCommand: function () {}
property bool isRequested: false
id: root
anchors.centerIn: parent
headerSettings.title: root.commandTitle
height: 504
property alias selectRecipient: selectRecipient
contentItem: Item {
width: root.width
height: childrenRect.height
TransactionStackView {
id: stack
anchors.top: parent.top
anchors.topMargin: 16
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
onGroupActivated: {
root.headerSettings.title = group.headerText
btnNext.text = group.footerText
}
TransactionFormGroup {
id: group1
headerText: root.commandTitle
footerText: qsTr("Continue")
StatusAccountSelector {
id: selectFromAccount
accounts: root.store.accounts
selectedAccount: {
const currAcc = root.store.currentAccount
if (currAcc.walletType !== Constants.watchWalletType) {
return currAcc
}
return null
}
currency: root.store.currentCurrency
width: stack.width
label: {
return root.isRequested ?
qsTr("Receive on account") :
qsTr("From account")
}
}
SeparatorWithIcon {
id: separator
anchors.top: selectFromAccount.bottom
anchors.topMargin: 19
icon.rotation: root.isRequested ? -90 : 90
}
StatusBaseText {
id: addressRequiredInfo
anchors.right: selectRecipient.right
anchors.bottom: selectRecipient.top
anchors.bottomMargin: -Style.current.padding
text: qsTr("Address request required")
color: Theme.palette.dangerColor1
visible: addressRequiredValidator.isWarn
}
RecipientSelector {
id: selectRecipient
accounts: root.store.accounts
contactsStore: root.contactsStore
label: root.isRequested ?
qsTr("From") :
qsTr("To")
anchors.top: separator.bottom
anchors.topMargin: 10
width: stack.width
onSelectedRecipientChanged: {
addressRequiredValidator.address = root.isRequested ? selectFromAccount.selectedAccount.address : selectRecipient.selectedRecipient.address
}
}
}
TransactionFormGroup {
id: group2
headerText: root.commandTitle
footerText: qsTr("Preview")
AssetAndAmountInput {
id: txtAmount
selectedAccount: selectFromAccount.selectedAccount
currentCurrency: root.store.currentCurrency
getFiatValue: root.store.getFiatValue
// Not Refactored Yet
// getCryptoValue: root.store.walletModelInst.balanceView.getCryptoValue
validateBalance: !root.isRequested
width: stack.width
}
}
TransactionFormGroup {
id: group3
headerText: root.isRequested ?
qsTr("Preview") :
qsTr("Transaction preview")
footerText: root.finalButtonLabel
TransactionPreview {
id: pvwTransaction
width: stack.width
fromAccount: root.isRequested ? selectRecipient.selectedRecipient : selectFromAccount.selectedAccount
toAccount: root.isRequested ? selectFromAccount.selectedAccount : selectRecipient.selectedRecipient
asset: txtAmount.selectedAsset
amount: { "value": txtAmount.selectedAmount, "fiatValue": txtAmount.selectedFiatAmount }
toWarn: addressRequiredValidator.isWarn
currency: root.store.currentCurrency
}
AddressRequiredValidator {
id: addressRequiredValidator
anchors.bottom: parent.bottom
anchors.bottomMargin: Style.current.padding
}
}
}
}
leftButtons: [
StatusBackButton {
visible: !stack.isFirstGroup
onClicked: {
stack.back()
}
}
]
rightButtons: [
StatusButton {
id: btnNext
text: qsTr("Next")
enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending
onClicked: {
const validity = stack.currentGroup.validate()
if (validity.isValid && !validity.isPending) {
if (stack.isLastGroup) {
root.sendChatCommand(selectFromAccount.selectedAccount.address,
txtAmount.selectedAmount,
txtAmount.selectedAsset.symbol,
txtAmount.selectedAsset.decimals)
return root.close()
}
stack.next()
}
}
}
]
}

View File

@ -595,22 +595,6 @@ QtObject {
return profileSectionModule.ensUsernamesModule.getGasEthValue(gweiValue, gasLimit)
}
function estimateGas(from_addr, to, assetSymbol, value, chainId, data) {
return walletSectionSendInst.estimateGas(from_addr, to, assetSymbol, value === "" ? "0.00" : value, chainId, data)
}
function authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes) {
walletSectionSendInst.authenticateAndTransfer(from, to, tokenSymbol, amount, uuid, selectedRoutes)
}
function suggestedFees(chainId) {
return JSON.parse(walletSectionSendInst.suggestedFees(chainId))
}
function suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, sendType, lockedInAmounts) {
walletSectionSendInst.suggestedRoutes(account, amount, token, disabledFromChainIDs, disabledToChainIDs, preferredChainIds, sendType, lockedInAmounts)
}
function resolveENS(value) {
mainModuleInst.resolveENS(value, "")
}

View File

@ -15,6 +15,7 @@ import shared.popups 1.0
import shared.status 1.0
import shared.controls 1.0
import shared.views.chat 1.0
import shared.popups.send 1.0
import SortFilterProxyModel 0.2
import AppLayouts.Communities.popups 1.0

View File

@ -15,6 +15,7 @@ import shared.panels 1.0
import shared.popups 1.0
import shared.stores 1.0
import shared.views.chat 1.0
import shared.popups.send.stores 1.0
import utils 1.0
import AppLayouts.Communities.controls 1.0

View File

@ -10,6 +10,7 @@ import StatusQ.Components 0.1
import utils 1.0
import shared.status 1.0
import shared.popups 1.0
import shared.popups.send 1.0
Item {
id: root

View File

@ -12,7 +12,7 @@ import shared 1.0
import shared.panels 1.0
import shared.status 1.0
import shared.controls 1.0
import shared.popups 1.0
import shared.popups.send 1.0
Item {
id: root

View File

@ -6,6 +6,7 @@ import utils 1.0
import shared.popups 1.0
import shared.status 1.0
import shared.popups.send 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1

View File

@ -65,6 +65,28 @@ ColumnLayout {
default: return ""
}
}
function getErrorMessageColor(status) {
switch(status) {
case EditNetworkForm.Pending:
return Theme.palette.baseColor1
case EditNetworkForm.SameAsOther:
return Theme.palette.warningColor1
case EditNetworkForm.Verified:
return Theme.palette.successColor1
default: return Theme.palette.dangerColor1
}
}
function getErrorMessageAlignment(status) {
switch(status) {
case EditNetworkForm.Pending:
case EditNetworkForm.Verified:
case EditNetworkForm.SameAsOther:
return Text.AlignLeft
default: return Text.AlignRight
}
}
}
onVisibleChanged: if(!visible) {d.revertValues()}
@ -152,24 +174,10 @@ ColumnLayout {
Qt.callLater(d.evaluateRpcEndPoint, text, true);
}
}
errorMessageCmp.horizontalAlignment: d.evaluationStatusMainRpc === EditNetworkForm.Pending ||
d.evaluationStatusMainRpc === EditNetworkForm.Verified ||
d.evaluationStatusMainRpc === EditNetworkForm.SameAsOther ?
Text.AlignLeft: Text.AlignRight
errorMessageCmp.horizontalAlignment: d.getErrorMessageAlignment(d.evaluationStatusMainRpc)
errorMessageCmp.visible: d.evaluationStatusMainRpc !== EditNetworkForm.UnTouched
errorMessageCmp.text: d.getUrlStatusText(d.evaluationStatusMainRpc, text)
errorMessageCmp.color: {
switch(d.evaluationStatusMainRpc) {
case EditNetworkForm.Pending:
return Theme.palette.baseColor1
case EditNetworkForm.SameAsOther:
return Theme.palette.warningColor1
case EditNetworkForm.Verified:
return Theme.palette.successColor1
default: return Theme.palette.dangerColor1
}
}
errorMessageCmp.color: d.getErrorMessageColor(d.evaluationStatusMainRpc)
}
}
@ -194,23 +202,10 @@ ColumnLayout {
Qt.callLater(d.evaluateRpcEndPoint, text, false);
}
}
errorMessageCmp.horizontalAlignment: d.evaluationStatusFallBackRpc === EditNetworkForm.Pending ||
d.evaluationStatusFallBackRpc === EditNetworkForm.Verified ||
d.evaluationStatusFallBackRpc === EditNetworkForm.SameAsOther ?
Text.AlignLeft: Text.AlignRight
errorMessageCmp.horizontalAlignment: d.getErrorMessageAlignment(d.evaluationStatusFallBackRpc)
errorMessageCmp.visible: d.evaluationStatusFallBackRpc !== EditNetworkForm.UnTouched
errorMessageCmp.text: d.getUrlStatusText(d.evaluationStatusFallBackRpc, text)
errorMessageCmp.color: {
switch(d.evaluationStatusFallBackRpc) {
case EditNetworkForm.Pending:
return Theme.palette.baseColor1
case EditNetworkForm.SameAsOther:
return Theme.palette.warningColor1
case EditNetworkForm.Verified:
return Theme.palette.successColor1
default: return Theme.palette.dangerColor1
}
}
errorMessageCmp.color: d.getErrorMessageColor(d.evaluationStatusFallBackRpc)
}
StatusInput {

View File

@ -15,6 +15,7 @@ import utils 1.0
import shared.controls 1.0
import shared.popups 1.0
import shared.popups.send.controls 1.0
import AppLayouts.stores 1.0
import "../stores"

View File

@ -23,6 +23,7 @@ import shared.popups 1.0
import shared.popups.keycard 1.0
import shared.status 1.0
import shared.stores 1.0
import shared.popups.send 1.0
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1

View File

@ -1,233 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.13
import utils 1.0
import shared.stores 1.0
import shared.panels 1.0
import "../"
import "../panels"
import "."
Item {
id: root
property string balanceErrorMessage: qsTr("Insufficient balance")
property string greaterThanOrEqualTo0ErrorMessage: qsTr("Must be greater than or equal to 0")
property string invalidInputErrorMessage: qsTr("This needs to be a number")
property string noInputErrorMessage: qsTr("Please enter an amount")
property string currentCurrency: "USD"
property alias selectedFiatAmount: txtFiatBalance.text
property alias selectedAmount: inputAmount.text
property var selectedAccount
property alias selectedAsset: selectAsset.selectedAsset
property var getFiatValue: function () {}
property var getCryptoValue: function () {}
property bool isDirty: false
property bool validateBalance: true
property bool isValid: false
property string validationError
property var formattedInputValue
property var getNetworkIcon: function(chainId){ return ""}
height: inputAmount.height + (inputAmount.validationError ? -16 - inputAmount.validationErrorTopMargin : 0) + txtFiatBalance.height + txtFiatBalance.anchors.topMargin
anchors.right: parent.right
anchors.left: parent.left
function validate(checkDirty) {
let isValid = true
let error = ""
const hasTyped = checkDirty ? isDirty : true
const balance = parseFloat(txtBalance.text || "0.00")
formattedInputValue = parseFloat(inputAmount.text || "0.00")
const noInput = inputAmount.text === ""
if (noInput && hasTyped) {
error = noInputErrorMessage
isValid = false
} else if (isNaN(inputAmount.text)) {
error = invalidInputErrorMessage
isValid = false
} else if (formattedInputValue < 0.00 && hasTyped) {
error = greaterThanOrEqualTo0ErrorMessage
isValid = false
} else if (validateBalance && formattedInputValue > balance && !noInput) {
error = balanceErrorMessage
isValid = false
}
if (!isValid) {
root.validationError = error
txtBalanceDesc.color = Style.current.danger
txtBalance.color = Style.current.danger
} else {
root.validationError = ""
txtBalanceDesc.color = Style.current.secondaryText
txtBalance.color = Qt.binding(function() { return txtBalance.hovered ? Style.current.textColor : Style.current.secondaryText })
}
root.isValid = isValid
return isValid
}
onSelectedAccountChanged: {
selectAsset.assets = Qt.binding(function() {
if (selectedAccount) {
return selectedAccount.assets
}
})
txtBalance.text = Qt.binding(function() {
return selectAsset.selectedAsset ? Utils.stripTrailingZeros(selectAsset.selectedAsset.value) : ""
})
}
Item {
visible: root.validateBalance
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
height: txtBalanceDesc.height
StyledText {
id: txtBalanceDesc
text: qsTr("Balance: ")
anchors.right: txtBalance.left
font.weight: Font.Medium
font.pixelSize: 13
color: Style.current.secondaryText
}
StyledText {
id: txtBalance
property bool hovered: false
text: selectAsset.selectedAsset ? Utils.stripTrailingZeros(selectAsset.selectedAsset.value) : "0.00"
anchors.right: parent.right
font.weight: Font.Medium
font.pixelSize: 13
color: hovered ? Style.current.textColor : Style.current.secondaryText
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onExited: {
txtBalance.hovered = false
}
onEntered: {
txtBalance.hovered = true
}
onClicked: {
inputAmount.text = Utils.stripTrailingZeros(selectAsset.selectedAsset.value)
txtFiatBalance.text = root.getFiatValue(inputAmount.text, selectAsset.selectedAsset.symbol, root.currentCurrency)
}
}
}
}
Input {
id: inputAmount
label: qsTr("Asset & Amount")
placeholderText: "0.00"
anchors.top: parent.top
customHeight: 56
validationErrorAlignment: TextEdit.AlignRight
validationErrorTopMargin: 8
validationErrorColor: formattedInputValue === 0 ? Style.current.warning : Style.current.danger
validationError: {
if (root.validationError) {
return root.validationError
}
if (formattedInputValue === 0) {
return qsTr("The amount is 0. Proceed only if this is desired.")
}
return ""
}
Keys.onReleased: {
let amount = inputAmount.text.trim()
if (isNaN(amount)) {
return
}
if (amount === "") {
txtFiatBalance.text = "0.00"
} else {
txtFiatBalance.text = root.getFiatValue(amount, selectAsset.selectedAsset.symbol, root.currentCurrency)
}
}
onTextChanged: {
root.isDirty = true
root.validate(true)
}
}
StatusAssetSelector {
id: selectAsset
anchors.top: inputAmount.top
anchors.topMargin: 28
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
defaultToken: Style.png("tokens/DEFAULT-TOKEN@3x")
tokenAssetSourceFn: function (symbol) {
return symbol ? Style.png("tokens/" + symbol) : defaultToken
}
searchTokenSymbolByAddressFn: function (address) {
if(popup.selectedAccount) {
return popup.selectedAccount.findTokenSymbolByAddress(address)
}
return ""
}
getNetworkIcon: root.getNetworkIcon
onSelectedAssetChanged: {
if (!selectAsset.selectedAsset) {
return
}
txtBalance.text = Utils.stripTrailingZeros(selectAsset.selectedAsset.balance.amount.toFixed(4))
if (inputAmount.text === "" || isNaN(inputAmount.text)) {
return
}
txtFiatBalance.text = root.getFiatValue(inputAmount.text, selectAsset.selectedAsset.symbol, root.currentCurrency)
root.validate(true)
}
}
Item {
height: txtFiatBalance.height
anchors.left: parent.left
anchors.top: inputAmount.bottom
anchors.topMargin: inputAmount.validationError ? -16 : inputAmount.validationErrorTopMargin
StyledTextField {
id: txtFiatBalance
anchors.left: parent.left
anchors.top: parent.top
color: txtFiatBalance.activeFocus ? Style.current.textColor : Style.current.secondaryText
font.weight: Font.Medium
font.pixelSize: 12
inputMethodHints: Qt.ImhFormattedNumbersOnly
text: "0.00"
selectByMouse: true
background: Rectangle {
color: Style.current.transparent
}
padding: 0
Keys.onReleased: {
let balance = txtFiatBalance.text.trim()
if (balance === "" || isNaN(balance)) {
return
}
inputAmount.text = root.getCryptoValue(balance, root.currentCurrency, selectAsset.selectedAsset.symbol)
}
}
StyledText {
id: txtFiatSymbol
text: root.currentCurrency
font.weight: Font.Medium
font.pixelSize: 12
color: Style.current.secondaryText
anchors.top: parent.top
anchors.left: txtFiatBalance.right
anchors.leftMargin: 2
}
}
}

View File

@ -1,15 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import utils 1.0
import "."
FormGroup {
id: root
property string headerText
property string footerText
property bool showBackBtn: true
property bool showNextBtn: true
property var onBackClicked
property var onNextClicked
}

View File

@ -1,78 +0,0 @@
import QtQuick 2.13
import QtQuick.Layouts 1.0
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
StatusRadioButton {
id: gasRectangle
property string primaryText
property string timeText
property string totalGasFiatValue
property double totalGasEthValue
width: contentItem.implicitWidth
// To-do Use StatusCard instead. It crashes if I use StatusCard and
// already spent 2 days on this, so leaving it out for now
contentItem: Rectangle {
id: card
implicitHeight: 76
implicitWidth: 128
radius: 8
color: gasRectangle.checked || mouseArea.containsMouse ? "transparent": Theme.palette.baseColor4
border.color: gasRectangle.checked || mouseArea.containsMouse ? Theme.palette.primaryColor2: Theme.palette.baseColor4
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: 8
anchors.rightMargin: 8
anchors.topMargin: 8
StatusBaseText {
id: primaryText
font.pixelSize: 15
font.weight: Font.Medium
elide: Text.ElideRight
text: gasRectangle.primaryText
color: Theme.palette.directColor1
}
StatusBaseText {
id: secondaryLabel
Layout.maximumWidth: card.width - Style.current.smallPadding
font.pixelSize: 13
font.weight: Font.Medium
text: gasRectangle.totalGasFiatValue
color: Theme.palette.primaryColor1
elide: Text.ElideRight
}
StatusBaseText {
id: tertiaryText
font.pixelSize: 10
text: gasRectangle.timeText
color: Theme.palette.directColor5
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: gasRectangle.toggle()
}
}
indicator: Item {
width:card.width
height: card.height
}
}

View File

@ -2,14 +2,10 @@ AddressInput 1.0 AddressInput.qml
AmountInput 1.0 AmountInput.qml
AssetAndAmountInput 1.0 AssetAndAmountInput.qml
AssetDelegate 1.0 AssetDelegate.qml
CollectibleNestedDelegate 1.0 CollectibleNestedDelegate.qml
ContactSelector 1.0 ContactSelector.qml
ContactsListAndSearch 1.0 ContactsListAndSearch.qml
CopyToClipBoardButton 1.0 CopyToClipBoardButton.qml
FormGroup 1.0 FormGroup.qml
GasSelector 1.0 GasSelector.qml
GasSelectorButton 1.0 GasSelectorButton.qml
GasValidator 1.0 GasValidator.qml
Input 1.0 Input.qml
RadioButtonSelector 1.0 RadioButtonSelector.qml
RecipientSelector 1.0 RecipientSelector.qml
@ -28,7 +24,6 @@ TransactionDelegate 1.0 TransactionDelegate.qml
TransactionAddress 1.0 TransactionAddress.qml
TransactionAddressTile 1.0 TransactionAddressTile.qml
TransactionDataTile 1.0 TransactionDataTile.qml
TransactionFormGroup 1.0 TransactionFormGroup.qml
EmojiHash 1.0 EmojiHash.qml
InformationTile 1.0 InformationTile.qml
SocialLinkPreview 1.0 SocialLinkPreview.qml
@ -45,5 +40,4 @@ GetSyncCodeDesktopInstructions 1.0 GetSyncCodeDesktopInstructions.qml
ErrorDetails 1.0 ErrorDetails.qml
CopyButton 1.0 CopyButton.qml
DisabledTooltipButton 1.0 DisabledTooltipButton.qml
WalletAccountListItem 1.0 WalletAccountListItem.qml
ImportKeypairInfo 1.0 ImportKeypairInfo.qml

View File

@ -1,58 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import utils 1.0
import "../"
import "./"
Column {
id: root
anchors.horizontalCenter: parent.horizontalCenter
visible: !isValid
spacing: 5
property int chainId
property var account
property double amount
property var asset
property bool isValid: false
property alias errorMessage: txtValidationError.text
onAccountChanged: validate()
onAmountChanged: validate()
onAssetChanged: validate()
function validate() {
let isValid = true
if (!(account && account.assets && asset && amount >= 0)) {
return root.isValid
}
const currAcctAsset = Utils.findAssetByChainAndSymbol(root.chainId, account.assets, asset.symbol)
if (currAcctAsset && currAcctAsset.value < amount) {
isValid = false
}
root.isValid = isValid
return isValid
}
SVGImage {
id: imgExclamation
width: 13.33
height: 13.33
sourceSize.height: height * 2
sourceSize.width: width * 2
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: Style.svg("exclamation_outline")
}
StyledText {
id: txtValidationError
text: qsTr("Insufficient balance")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 13
height: 18
color: Style.current.danger
}
}

View File

@ -1,193 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import SortFilterProxyModel 0.2
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Backpressure 1.0
import shared.controls 1.0
import utils 1.0
import "../controls"
Item {
id: root
property var assets
property var selectedAsset
property string defaultToken
property string currentCurrencySymbol
property string placeholderText
property var hoveredToken
property var tokenAssetSourceFn: function (symbol) {
return ""
}
property var searchTokenSymbolByAddressFn: function (address) {
return ""
}
property var getNetworkIcon: function(chainId){
return ""
}
function resetInternal() {
assets = null
selectedAsset = null
}
implicitWidth: comboBox.width
implicitHeight: comboBox.implicitHeight
onSelectedAssetChanged: {
if (selectedAsset && selectedAsset.symbol) {
d.iconSource = tokenAssetSourceFn(selectedAsset.symbol)
d.text = selectedAsset.symbol
}
}
onHoveredTokenChanged: {
if (hoveredToken && hoveredToken.symbol) {
d.iconSource = tokenAssetSourceFn(hoveredToken.symbol)
d.text = hoveredToken.symbol
}
}
QtObject {
id: d
property string iconSource: ""
property string text: ""
property string searchString
readonly property bool isTokenSelected: !!root.selectedAsset || !!root.hoveredToken
readonly property var updateSearchText: Backpressure.debounce(root, 1000, function(inputText) {
d.searchString = inputText
})
}
StatusComboBox {
id: comboBox
objectName: "assetSelectorButton"
control.padding: 4
control.popup.width: 492
control.popup.x: -root.x
control.popup.verticalPadding: 0
popupContentItemObjectName: "assetSelectorList"
model : SortFilterProxyModel {
sourceModel: root.assets
filters: [
ExpressionFilter {
expression: {
var tokenSymbolByAddress = searchTokenSymbolByAddressFn(d.searchString)
return visibleForNetwork && (
symbol.startsWith(d.searchString.toUpperCase()) || name.toUpperCase().startsWith(d.searchString.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
)
}
}
]
}
control.background: Rectangle {
color: "transparent"
border.width: d.isTokenSelected ? 0 : 1
border.color: d.isTokenSelected ? "transparent" : Theme.palette.directColor7
radius: 12
}
contentItem: RowLayout {
id: rowLayout
StatusRoundedImage {
Layout.preferredWidth: 21
Layout.preferredHeight: 21
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
visible: !!d.iconSource
image.source: d.iconSource
image.onStatusChanged: {
if (image.status === Image.Error) {
image.source = defaultToken
}
}
}
StatusBaseText {
Layout.alignment: Qt.AlignVCenter
font.pixelSize: 28
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
color: Theme.palette.miscColor1
text: d.text
visible: d.isTokenSelected
}
StatusIcon {
Layout.leftMargin: -3
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 16
Layout.preferredHeight: 16
icon: "chevron-down"
color: Theme.palette.miscColor1
visible: d.isTokenSelected
}
StatusBaseText {
Layout.alignment: Qt.AlignCenter
visible: !d.isTokenSelected
font.pixelSize: 15
font.weight: Font.Medium
verticalAlignment: Text.AlignVCenter
color: Theme.palette.baseColor1
elide: Qt.ElideRight
text: placeholderText
}
}
control.indicator: null
delegate: TokenBalancePerChainDelegate {
objectName: "AssetSelector_ItemDelegate_" + symbol
width: comboBox.control.popup.width
getNetworkIcon: root.getNetworkIcon
onTokenSelected: {
selectedAsset = selectedToken
comboBox.control.popup.close()
}
}
Component.onCompleted: {
control.currentIndex = -1
control.popup.contentItem.header = searchBox
}
control.popup.onOpened: {
control.currentIndex = -1
}
}
Component {
id: searchBox
StatusInput {
width: parent.width
input.showBackground: false
placeholderText: qsTr("Search for token or enter token address")
onTextChanged: Qt.callLater(d.updateSearchText, text)
input.clearable: true
input.implicitHeight: 56
input.rightComponent: StatusFlatRoundButton {
icon.name: "search"
type: StatusFlatRoundButton.Type.Secondary
enabled: false
}
Rectangle {
anchors.bottom: parent.bottom
height: 1
width: parent.width
color: Theme.palette.baseColor2
}
}
}
}

View File

@ -1,7 +1,6 @@
AcceptRejectOptionsButtonsPanel 1.0 AcceptRejectOptionsButtonsPanel.qml
Address 1.0 Address.qml
AddressRequiredValidator 1.0 AddressRequiredValidator.qml
BalanceValidator 1.0 BalanceValidator.qml
ChatsLoadingPanel 1.0 ChatsLoadingPanel.qml
ConnectionWarnings 1.0 ConnectionWarnings.qml
DidYouKnowSplashScreen 1.0 DidYouKnowSplashScreen.qml
@ -22,9 +21,6 @@ Separator 1.0 Separator.qml
SeparatorWithIcon 1.0 SeparatorWithIcon.qml
SequenceColumnLayout 1.0 SequenceColumnLayout.qml
SplitViewHandle 1.0 SplitViewHandle.qml
HoldingItemSelector 1.0 HoldingItemSelector.qml
HoldingSelector 1.0 HoldingSelector.qml
HoldingTypes 1.0 HoldingTypes.qml
StatusAssetSelector 1.0 StatusAssetSelector.qml
StyledText 1.0 StyledText.qml
TextWithLabel 1.0 TextWithLabel.qml

View File

@ -1,46 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtQuick.Dialogs 1.3
import utils 1.0
import shared.controls 1.0
import StatusQ.Popups 0.1
import StatusQ.Controls 0.1
StatusModal {
id: root
headerSettings.title: qsTr("Select account")
height: 284
property var accounts
property string currency
property alias accountSelector: selectFromAccount
signal selectAndShareAddressButtonClicked()
contentItem: Item {
width: root.width
height: childrenRect.height
TransactionFormGroup {
anchors.fill: parent
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
StatusAccountSelector {
id: selectFromAccount
accounts: root.accounts
currency: root.currency
width: parent.width
label: qsTr("Select account to share and receive assets")
}
}
}
rightButtons: [
StatusButton {
text: qsTr("Confirm and share address")
onClicked: root.selectAndShareAddressButtonClicked()
}
]
}

View File

@ -1,364 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtQuick.Dialogs 1.3
import utils 1.0
import shared.controls 1.0
import StatusQ.Popups 0.1
import StatusQ.Controls 0.1
import shared.views 1.0
import shared.panels 1.0
import shared.popups 1.0
import AppLayouts.Wallet 1.0
StatusModal {
id: root
headerSettings.title: qsTr("Send")
height: 540
property var store
property var contactsStore
property var selectedAccount
property var selectedRecipient
property var selectedAsset
property var selectedAmount
property var selectedFiatAmount
property var selectedType: RecipientSelector.Type.Address
property bool outgoing: true
property bool isARequest: false
property string msgId: ""
property string trxData: ""
property int chainId
// property alias transactionSigner: transactionSigner
// property var sendTransaction: function() {
// stack.currentGroup.isPending = true
// let success = false
// success = root.store.transfer(
// selectFromAccount.selectedAccount.address,
// selectRecipient.selectedRecipient.address,
// root.selectedAsset.symbol,
// root.selectedAmount,
// gasSelector.selectedGasLimit,
// gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
// gasSelector.selectedTipLimit,
// gasSelector.selectedOverallLimit,
// transactionSigner.enteredPassword,
// root.chainId,
// stack.uuid,
// gasSelector.suggestedFees.eip1559Enabled,
// )
// // TODO remove this else once the thread and connection are back
//// if(!success){
//// //% "Invalid transaction parameters"
//// sendingError.text = qsTr("Invalid transaction parameters")
//// sendingError.open()
//// }
// }
property MessageDialog sendingError: MessageDialog {
id: sendingError
title: qsTr("Error sending the transaction")
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
}
signal openGasEstimateErrorPopup(string message)
// onClosed: {
// stack.pop(groupPreview, StackView.Immediate)
// }
// onOpened: {
// gasSelector.suggestedFees = root.store.suggestedFees(root.chainId)
// gasSelector.checkOptimal()
// }
// contentItem: Item {
// width: root.width
// height: childrenRect.height
// TransactionStackView {
// id: stack
// anchors.leftMargin: Style.current.padding
// anchors.rightMargin: Style.current.padding
// initialItem: groupPreview
// isLastGroup: stack.currentGroup === groupSignTx
// onGroupActivated: {
// root.headerSettings.title = group.headerText
// btnNext.text = group.footerText
// }
// TransactionFormGroup {
// id: groupSelectAcct
// headerText: {
// // Not Refactored Yet
//// if(trxData.startsWith("0x095ea7b3")){
//// const approveData = JSON.parse(root.store.walletModelInst.tokensView.decodeTokenApproval(selectedRecipient.address, trxData))
//// if(approveData.symbol)
//// //% "Authorize %1 %2"
//// return qsTr("Error sending the transaction").arg(approveData.amount).arg(approveData.symbol)
//// }
// return qsTr("Send");
// }
// footerText: qsTr("Continue")
// showNextBtn: false
// onBackClicked: function() {
// if(validate()) {
// stack.pop()
// }
// }
// StatusAccountSelector {
// id: selectFromAccount
// accounts: root.store.accounts
// currency: root.store.currentCurrency
// width: stack.width
// selectedAccount: root.selectedAccount
// label: qsTr("Choose account")
// showBalanceForAssetSymbol: root.selectedAsset.symbol
// chainId: root.chainId
// minRequiredAssetBalance: parseFloat(root.selectedAmount)
// onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
// }
// RecipientSelector {
// id: selectRecipient
// visible: false
// accounts: root.store.accounts
// contactsStore: root.contactsStore
// selectedRecipient: root.selectedRecipient
// selectedType: root.selectedType
// readOnly: true
// }
// }
// TransactionFormGroup {
// id: groupSelectGas
// headerText: qsTr("Network fee")
// footerText: qsTr("Continue")
// showNextBtn: false
// onBackClicked: function() {
// stack.pop()
// }
// GasSelector {
// id: gasSelector
// anchors.topMargin: Style.current.padding
// getGasEthValue: root.store.getGasEthValue
// getFiatValue: root.store.getFiatValue
// currentCurrency: root.store.currentCurrency
// width: stack.width
// property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
// if (!(selectFromAccount.selectedAccount && selectFromAccount.selectedAccount.address &&
// selectRecipient.selectedRecipient && selectRecipient.selectedRecipient.address &&
// root.selectedAsset && root.selectedAsset.symbol &&
// root.selectedAmount)) {
// selectedGasLimit = 250000
// defaultGasLimit = selectedGasLimit
// return
// }
// let gasEstimate = JSON.parse(root.store.estimateGas(
// selectFromAccount.selectedAccount.address,
// selectRecipient.selectedRecipient.address,
// root.selectedAsset.symbol,
// root.selectedAmount,
// root.chainId,
// trxData
// ))
// if (!gasEstimate.success) {
// let message = qsTr("Error estimating gas: %1").arg(gasEstimate.error.message)
// root.openGasEstimateErrorPopup(message);
// return
// }
// selectedGasLimit = gasEstimate.result
// defaultGasLimit = selectedGasLimit
// })
// }
// GasValidator {
// id: gasValidator
// anchors.top: gasSelector.bottom
// anchors.horizontalCenter: parent.horizontalCenter
//// selectedAccount: selectFromAccount.selectedAccount
//// selectedAmount: parseFloat(root.selectedAmount)
//// selectedAsset: root.selectedAsset
//// selectedGasEthValue: gasSelector.selectedGasEthValue
// }
// }
// TransactionFormGroup {
// id: groupPreview
// headerText: qsTr("Transaction preview")
// footerText: qsTr("Sign with password")
// showBackBtn: false
// onNextClicked: function() {
// stack.push(groupSignTx, StackView.Immediate)
// }
// isValid: groupSelectAcct.isValid && groupSelectGas.isValid && pvwTransaction.isValid
// TransactionPreview {
// id: pvwTransaction
// width: stack.width
// fromAccount: selectFromAccount.selectedAccount
// gas: {
// "value": gasSelector.selectedGasEthValue,
// "symbol": "ETH",
// "fiatValue": gasSelector.selectedGasFiatValue
// }
// toAccount: selectRecipient.selectedRecipient
// asset: root.selectedAsset
// amount: { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount }
// currency: root.store.currentCurrency
// isFromEditable: false
// trxData: root.trxData
// isGasEditable: true
// fromValid: balanceValidator.isValid
// gasValid: gasValidator.isValid
// onFromClicked: { stack.push(groupSelectAcct, StackView.Immediate) }
// onGasClicked: { stack.push(groupSelectGas, StackView.Immediate) }
// }
// BalanceValidator {
// id: balanceValidator
// anchors.top: pvwTransaction.bottom
// anchors.horizontalCenter: parent.horizontalCenter
// account: selectFromAccount.selectedAccount
// amount: !!root.selectedAmount ? parseFloat(root.selectedAmount) : 0.0
// chainId: root.chainId
// asset: root.selectedAsset
// }
// GasValidator {
// id: gasValidator2
// anchors.top: balanceValidator.visible ? balanceValidator.bottom : pvwTransaction.bottom
// anchors.topMargin: balanceValidator.visible ? 5 : 0
// anchors.horizontalCenter: parent.horizontalCenter
//// selectedAccount: selectFromAccount.selectedAccount
//// selectedAmount: parseFloat(root.selectedAmount)
//// selectedAsset: root.selectedAsset
//// selectedGasEthValue: gasSelector.selectedGasEthValue
// }
// }
// TransactionFormGroup {
// id: groupSignTx
// headerText: qsTr("Sign with password")
// footerText: qsTr("Send %1 %2").arg(root.selectedAmount).arg(!!root.selectedAsset ? root.selectedAsset.symbol : "")
// onBackClicked: function() {
// stack.pop()
// }
// TransactionSigner {
// id: transactionSigner
// width: stack.width
// signingPhrase: root.store.signingPhrase
// }
// }
// }
// }
// leftButtons: [
// StatusBackButton {
// id: btnBack
// visible: stack.currentGroup.showBackBtn
// enabled: stack.currentGroup.isValid || stack.isLastGroup
// onClicked: {
// if (typeof stack.currentGroup.onBackClicked === "function") {
// return stack.currentGroup.onBackClicked()
// }
// stack.back()
// }
// }
// ]
// rightButtons: [
// StatusButton {
// id: btnNext
// text: qsTr("Next")
// enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending
// visible: stack.currentGroup.showNextBtn
// onClicked: {
// const validity = stack.currentGroup.validate()
// if (validity.isValid && !validity.isPending) {
// if (stack.isLastGroup) {
// return root.sendTransaction(gasSelector.selectedGasLimit,
// gasSelector.suggestedFees.eip1559Enabled ? "" : gasSelector.selectedGasPrice,
// gasSelector.selectedTipLimit,
// gasSelector.selectedOverallLimit,
// transactionSigner.enteredPassword)
// }
// if(gasSelector.suggestedFees.eip1559Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
// if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
// Global.openPopup(transactionSettingsConfirmationPopupComponent, {
// currentBaseFee: gasSelector.suggestedFees.baseFee,
// currentMinimumTip: gasSelector.perGasTipLimitFloor,
// currentAverageTip: gasSelector.perGasTipLimitAverage,
// tipLimit: gasSelector.selectedTipLimit,
// suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
// priceLimit: gasSelector.selectedOverallLimit,
// suggestedPriceLimit: gasSelector.suggestedFees.baseFee + gasSelector.perGasTipLimitFloor,
// showPriceLimitWarning: gasSelector.showPriceLimitWarning,
// showTipLimitWarning: gasSelector.showTipLimitWarning,
// onConfirm: function(){
// stack.next();
// }
// })
// return
// }
// }
// if (typeof stack.currentGroup.onNextClicked === "function") {
// return stack.currentGroup.onNextClicked()
// }
// stack.next()
// }
// }
// }
// ]
// Component {
// id: transactionSettingsConfirmationPopupComponent
// TransactionSettingsConfirmationPopup { }
// }
// Connections {
// target: root.store.walletSectionSendInst
// onTransactionSent: {
// try {
// let response = JSON.parse(txResult)
// if (response.uuid !== stack.uuid)
// return
// stack.currentGroup.isPending = false
// let transactionId = response.result
// if (!response.success) {
// if (Utils.isInvalidPasswordMessage(transactionId)){
// transactionSigner.validationError = qsTr("Wrong password")
// return
// }
// sendingError.text = transactionId
// return sendingError.open()
// }
// if(isARequest)
// root.store.acceptRequestTransaction(transactionId, msgId, root.store.getPubkey() + transactionId.substr(2))
// // Refactor this
// let url = "" //`${walletModel.utilsView.etherscanLink}/${response.result}`
// Global.displayToastMessage(qsTr("Transaction pending..."),
// qsTr("View on etherscan"),
// "",
// true,
// Constants.ephemeralNotificationType.normal,
// url)
// root.close()
// } catch (e) {
// console.error('Error parsing the response', e)
// }
// }
// }
}

View File

@ -1,263 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import utils 1.0
import StatusQ.Controls 0.1
import "../panels"
import "."
// TODO: replace with StatusModal
ModalPopup {
id: popup
height: 300 + (showPriceLimitWarning ? 65 : 0) + (showTipLimitWarning ? 65 : 0)
width: 400
title: qsTr("Are you sure?")
property var onConfirm: function(){}
property double currentBaseFee: 0
property double currentMinimumTip: 0
property double currentAverageTip: 0
property double tipLimit: 0
property double suggestedTipLimit: 0
property double priceLimit: 0
property double suggestedPriceLimit: 0
property bool showPriceLimitWarning: false
property bool showTipLimitWarning: false
Column {
id: content
width: 450
height: parent.height
spacing: 10
StyledText {
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
text: qsTr("Your priority fee is below our suggested parameters.")
font.pixelSize: 13
wrapMode: Text.WordWrap
color: Style.current.secondaryText
}
Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.smallPadding
height: 20
StyledText {
text: qsTr("Current base fee")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(currentBaseFee)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.smallPadding
height: 20
StyledText {
text: qsTr("Current minimum tip")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(currentMinimumTip)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.smallPadding
height: 20
StyledText {
text: qsTr("Current average tip")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(currentAverageTip)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
Rectangle {
id: tipLimitRect
width: 368
visible: showTipLimitWarning
height: visible ? 70 : 0
radius: 8
color: Style.current.backgroundHoverLight
Column {
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
height: 100
width: 450 - Style.current.smallPadding
spacing: 10
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Your tip limit")
font.pixelSize: 13
width: 190
anchors.left: parent.left
color: Style.current.red
}
StyledText {
text: qsTr("%1 Gwei").arg(tipLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
color: Style.current.red
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Suggested minimum tip")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(suggestedTipLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
}
}
Rectangle {
id: minPriceLimitRect
width: 368
visible: showPriceLimitWarning
height: visible ? 70 : 0
radius: 8
color: Style.current.backgroundHoverLight
Column {
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.smallPadding
height: 100
width: 450 - Style.current.smallPadding
spacing: 10
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Your price limit")
font.pixelSize: 13
width: 190
anchors.left: parent.left
color: Style.current.red
}
StyledText {
text: qsTr("%1 Gwei").arg(priceLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
color: Style.current.red
}
}
Item {
anchors.left: parent.left
anchors.right: parent.right
height: 20
StyledText {
text: qsTr("Suggested minimum price limit")
font.pixelSize: 13
width: 190
anchors.left: parent.left
}
StyledText {
text: qsTr("%1 Gwei").arg(suggestedPriceLimit)
font.pixelSize: 13
width: 190
anchors.right: parent.right
}
}
}
}
}
footer: Item {
id: footerContainer
width: parent.width
StatusButton {
id: cancelButton
anchors.right: confirmButton.left
anchors.rightMargin: Style.current.smallPadding
text: qsTr("Change Limit")
anchors.bottom: parent.bottom
onClicked: popup.destroy()
}
StatusButton {
id: confirmButton
type: StatusBaseButton.Type.Danger
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
text: qsTr("Continue anyway")
anchors.bottom: parent.bottom
onClicked: {
popup.onConfirm();
popup.destroy();
}
}
}
}

View File

@ -11,18 +11,13 @@ InviteFriendsPopup 1.0 InviteFriendsPopup.qml
NicknamePopup 1.0 NicknamePopup.qml
ModalPopup 1.0 ModalPopup.qml
PopupMenu 1.0 PopupMenu.qml
SendModal 1.0 SendModal.qml
TransactionSettingsConfirmationPopup 1.0 TransactionSettingsConfirmationPopup.qml
UnblockContactConfirmationDialog 1.0 UnblockContactConfirmationDialog.qml
UserStatusContextMenu 1.0 UserStatusContextMenu.qml
SignTransactionModal 1.0 SignTransactionModal.qml
SelectAccountModal 1.0 SelectAccountModal.qml
ProfileDialog 1.0 ProfileDialog.qml
ImageCropWorkflow 1.0 ImageCropWorkflow.qml
ImportCommunityPopup 1.0 ImportCommunityPopup.qml
DisplayNamePopup 1.0 DisplayNamePopup.qml
SendContactRequestModal 1.0 SendContactRequestModal.qml
AccountsModalHeader 1.0 AccountsModalHeader.qml
GetSyncCodeInstructionsPopup 1.0 GetSyncCodeInstructionsPopup.qml
NoPermissionsToJoinPopup 1.0 NoPermissionsToJoinPopup.qml
RemoveAccountConfirmationPopup 1.0 RemoveAccountConfirmationPopup.qml

View File

@ -7,7 +7,6 @@ import SortFilterProxyModel 0.2
import utils 1.0
import shared.stores 1.0
import shared.panels 1.0
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
@ -17,9 +16,10 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Popups.Dialog 0.1
import "../panels"
import "../controls"
import "../views"
import "./panels"
import "./controls"
import "./views"
import "./stores"
StatusDialog {
id: popup
@ -475,11 +475,6 @@ StatusDialog {
onNextButtonClicked: popup.sendTransaction()
}
Component {
id: transactionSettingsConfirmationPopupComponent
TransactionSettingsConfirmationPopup {}
}
Connections {
target: popup.store.walletSectionSendInst
function onSuggestedRoutesReady(txRoutes) {

View File

@ -8,7 +8,7 @@ import StatusQ.Components 0.1
import utils 1.0
import "../panels"
import shared.panels 1.0
Column {
id: root

View File

@ -0,0 +1,12 @@
AccountsModalHeader 1.0 AccountsModalHeader.qml
WalletAccountListItem 1.0 WalletAccountListItem.qml
GasSelector 1.0 GasSelector.qml
GasValidator 1.0 GasValidator.qml
ClearButton 1.0 ClearButton.qml
SavedAddressListItem 1.0 SavedAddressListItem.qml
TokenBalancePerChainDelegate 1.0 TokenBalancePerChainDelegate.qml
SearchBoxWithRightIcon 1.0 SearchBoxWithRightIcon.qml
AmountInputWithCursor 1.0 AmountInputWithCursor.qml
BalanceExceeded 1.0 BalanceExceeded.qml
CollectibleBackButtonWithInfo 1.0 CollectibleBackButtonWithInfo.qml
CollectibleNestedDelegate 1.0 CollectibleNestedDelegate.qml

View File

@ -0,0 +1,2 @@
HoldingItemSelector 1.0 HoldingItemSelector.qml
HoldingSelector 1.0 HoldingSelector.qml

View File

@ -0,0 +1 @@
SendModal 1.0 SendModal.qml

View File

@ -0,0 +1 @@
TransactionStore 1.0 TransactionStore.qml

View File

@ -0,0 +1,12 @@
AmountToReceive 1.0 AmountToReceive.qml
AmountToSend 1.0 AmountToSend.qml
FeesView 1.0 FeesView.qml
NetworkCardsComponent 1.0 NetworkCardsComponent.qml
NetworksAdvancedCustomRoutingView 1.0 NetworksAdvancedCustomRoutingView.qml
NetworkSelector 1.0 NetworkSelector.qml
NetworksSimpleRoutingView 1.0 NetworksSimpleRoutingView.qml
RecipientView 1.0 RecipientView.qml
SendModalFooter 1.0 SendModalFooter.qml
TabAddressSelectorView 1.0 TabAddressSelectorView.qml
TokenListView 1.0 TokenListView.qml

View File

@ -13,6 +13,7 @@ import shared.panels 1.0
import shared.popups 1.0
import shared.status 1.0
import shared.stores 1.0 as SharedStores
import shared.popups.send 1.0
//TODO remove this dependency!
import AppLayouts.Chat.stores 1.0

View File

@ -10,6 +10,7 @@ import shared 1.0
import shared.popups 1.0
import shared.status 1.0
import shared.stores 1.0 as SharedStores
import shared.popups.send 1.0
//TODO remove this dependency!
import "../../../app/AppLayouts/Chat/stores"

View File

@ -1,6 +1,5 @@
singleton RootStore 1.0 RootStore.qml
CurrenciesStore 1.0 CurrenciesStore.qml
TransactionStore 1.0 TransactionStore.qml
CommunityTokensStore 1.0 CommunityTokensStore.qml
BIP39_en 1.0 BIP39_en.qml
ChartStoreBase 1.0 ChartStoreBase.qml

View File

@ -1,560 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.13
import StatusQ.Core 0.1
import StatusQ.Controls 0.1 as StatusQ
import StatusQ.Components 0.1
import utils 1.0
import "../status"
import "../panels"
import "../controls"
import "../popups"
import shared.controls.chat 1.0
Item {
id: root
property var fromAccount
property var toAccount
property var asset
property var amount
property string trxData: ""
property string currency: "USD"
property var gas
height: content.height
signal fromClicked
signal gasClicked
// Creates a mouse area around the "from account". When clicked, triggers
// the "fromClicked" signal
property bool isFromEditable: false
// Creates a mouse area around the "network fee". When clicked, triggers
// the "gasClicked" signal
property bool isGasEditable: false
property bool isValid: toValid && fromValid && gasValid
property bool fromValid: true
property bool toValid: true
property bool toWarn: false
property bool gasValid: true
Column {
id: content
anchors.left: parent.left
anchors.right: parent.right
LabelValueRow {
id: itmFrom
label: qsTr("From")
value: Item {
id: itmFromValue
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
function needsRightPadding() {
return !root.fromValid || root.isFromEditable
}
Row {
spacing: Style.current.halfPadding
rightPadding: itmFromValue.needsRightPadding() ? Style.current.halfPadding : 0
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
StyledText {
font.pixelSize: 15
height: 22
text: root.fromAccount ? root.fromAccount.name : ""
elide: Text.ElideRight
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
SVGImage {
id: imgFromWallet
sourceSize.height: 18
sourceSize.width: 18
visible: !!root.fromAccount ? root.fromAccount.type === RecipientSelector.Type.Account : true
horizontalAlignment: Image.AlignLeft
width: itmFromValue.needsRightPadding() ? (Style.current.halfPadding + sourceSize.width) : undefined // adding width to add addl spacing to image
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: Style.svg("walletIcon")
ColorOverlay {
visible: parent.visible
anchors.fill: parent
source: parent
color: root.fromAccount && root.fromAccount.color ? root.fromAccount.color : Style.current.blue
}
}
SVGImage {
id: fromInvalid
anchors.verticalCenter: parent.verticalCenter
width: 13.33
height: 13.33
sourceSize.height: height * 2
sourceSize.width: width * 2
fillMode: Image.PreserveAspectFit
source: Style.svg("exclamation_outline")
visible: !root.fromValid
}
SVGImage {
id: fromArrow
width: 13
height: 7
visible: root.isFromEditable
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: Style.svg("caret")
rotation: 270
ColorOverlay {
anchors.fill: parent
visible: parent.visible
source: parent
color: Style.current.secondaryText
}
}
}
MouseArea {
anchors.fill: parent
visible: fromArrow.visible
cursorShape: Qt.PointingHandCursor
onClicked: root.fromClicked()
}
}
}
LabelValueRow {
id: itmTo
function needsRightPadding() {
return !root.toValid || root.toWarn
}
label: qsTr("Recipient")
states: [
State {
name: "Address"
when: !!root.toAccount && root.toAccount.type === RecipientSelector.Type.Address
PropertyChanges {
target: txtToPrimary
text: (!!root.toAccount && root.toAccount.address) ? root.toAccount.address : qsTr("Unknown")
elide: Text.ElideMiddle
anchors.leftMargin: 190
anchors.right: parent.right
}
PropertyChanges {
target: txtToSecondary
width: 0
}
},
State {
name: "Contact"
when: !!root.toAccount && root.toAccount.type === RecipientSelector.Type.Contact && !!root.toAccount.address
PropertyChanges {
target: metSecondary
text: root.toAccount.ensVerified ? root.toAccount.alias : root.toAccount.address
}
PropertyChanges {
target: txtToSecondary
anchors.right: idtToContact.left
anchors.rightMargin: Style.current.halfPadding
width: txtToSecondary.visible ? metSecondary.elidedWidth : 0
text: metSecondary.elidedText
visible: root.toAccount.address !== Constants.zeroAddress
}
PropertyChanges {
target: idtToContact
visible: true
}
PropertyChanges {
target: txtToPrimary
text: root.toAccount.name
}
},
State {
name: "Account"
when: !!root.toAccount && root.toAccount.type === RecipientSelector.Type.Account && !!root.toAccount.address
PropertyChanges {
target: metSecondary
text: root.toAccount.address
}
PropertyChanges {
target: txtToSecondary
anchors.right: imgToWallet.left
anchors.rightMargin: Style.current.halfPadding
text: metSecondary.elidedText
width: metSecondary.elidedWidth
}
PropertyChanges {
target: imgToWallet
visible: true
}
PropertyChanges {
target: ovlToWallet
visible: true
color: root.toAccount.color
}
PropertyChanges {
target: txtToPrimary
text: root.toAccount.name
}
}
]
StyledText {
id: txtToPrimary
font.pixelSize: 15
height: 22
anchors.left: parent.left
anchors.right: txtToSeparator.visible ? txtToSeparator.left : idtToContact.left
anchors.rightMargin: txtToSeparator.visible ? 0 : Style.current.halfPadding
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
StyledText {
id: txtToSeparator
font.pixelSize: 15
height: 22
text: " • "
visible: txtToSecondary.visible && txtToSecondary.width > 0
color: Style.current.secondaryText
anchors.right: txtToSecondary.left
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
id: txtToSecondary
visible: true
font.pixelSize: 15
height: 22
color: Style.current.secondaryText
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
TextMetrics {
id: metSecondary
elideWidth: 102
elide: Text.ElideMiddle
}
SVGImage {
id: imgToWallet
visible: false
sourceSize.height: 18
sourceSize.width: 18
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: Style.svg("walletIcon")
}
ColorOverlay {
id: ovlToWallet
anchors.fill: imgToWallet
visible: false
source: imgToWallet
}
UserImage {
id: idtToContact
visible: false
anchors.right: toInvalid.visible ? toInvalid.left : parent.right
anchors.rightMargin: toInvalid.visible ? Style.current.halfPadding : 0
anchors.verticalCenter: parent.verticalCenter
name: root.toAccount.name
pubkey: root.toAccount.pubKey
image: root.toAccount.icon
ensVerified: root.toAccount.ensVerified
}
SVGImage {
id: toInvalid
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: 13.33
height: 13.33
sourceSize.height: height * 2
sourceSize.width: width * 2
fillMode: Image.PreserveAspectFit
source: Style.svg("exclamation_outline")
visible: !root.toValid || root.toWarn
}
}
LabelValueRow {
id: itmAsset
label: qsTr("Asset")
value: Item {
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
StyledText {
font.pixelSize: 15
height: 22
text: (root.asset && root.asset.name) ? root.asset.name : ""
anchors.left: parent.left
anchors.right: txtAssetSymbol.left
anchors.rightMargin: Style.current.halfPadding
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
id: txtAssetSymbol
font.pixelSize: 15
height: 22
text: (root.asset && root.asset.symbol) ? root.asset.symbol : ""
color: Style.current.secondaryText
anchors.right: imgAsset.left
anchors.rightMargin: Style.current.halfPadding
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
Image {
id: imgAsset
sourceSize.height: 32
sourceSize.width: 32
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: Style.png("tokens/" + ((root.asset && root.asset.symbol) ? root.asset.symbol : "ETH"))
onStatusChanged: {
if (status == Image.Error) {
source = Style.png("tokens/DEFAULT-TOKEN@3x")
}
}
}
}
}
LabelValueRow {
id: itmAmount
label: qsTr("Amount")
value: Item {
id: amountRoot
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
StyledText {
font.pixelSize: 15
height: 22
text: (root.amount && root.amount.value) ? Utils.stripTrailingZeros(root.amount.value) : ""
anchors.left: parent.left
anchors.right: txtAmountSymbol.left
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
StyledText {
id: txtAmountSymbol
font.pixelSize: 15
height: 22
text: ((root.asset && root.asset.symbol) ? root.asset.symbol : "") + " •"
color: Style.current.secondaryText
anchors.right: txtAmountFiat.left
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
id: txtAmountFiat
font.pixelSize: 15
height: 22
text: "~" + (root.amount && root.amount.fiatValue ? root.amount.fiatValue : "0.00")
anchors.right: txtAmountCurrency.left
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
id: txtAmountCurrency
font.pixelSize: 15
height: 22
text: root.currency
color: Style.current.secondaryText
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
}
}
LabelValueRow {
id: itmNetworkFee
label: qsTr("Network fee")
visible: !!root.gas
value: Item {
id: networkFeeRoot
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
function needsRightPadding() {
return !root.gasValid || root.isGasEditable
}
Row {
spacing: Style.current.halfPadding
rightPadding: networkFeeRoot.needsRightPadding() ? Style.current.halfPadding : 0
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
StyledText {
id: networkFeeText
font.pixelSize: 15
width: 75
height: 22
text: (root.gas && root.gas.value) ? Utils.stripTrailingZeros(root.gas.value) : ""
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
StatusQ.StatusToolTip {
enabled: networkFeeText.truncated
id: networkFeeTooltip
text: networkFeeText.text
}
MouseArea {
enabled: networkFeeText.truncated
anchors.fill: parent
hoverEnabled: enabled
onEntered: networkFeeTooltip.visible = true
onExited: networkFeeTooltip.visible = false
}
}
StyledText {
id: txtFeeSymbol
font.pixelSize: 15
height: 22
text: ((root.gas && root.gas.symbol) ? root.gas.symbol : "") + " •"
color: Style.current.secondaryText
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
id: txtFeeFiat
font.pixelSize: 15
height: 22
text: "~" + ((root.gas && root.gas.fiatValue) ? root.gas.fiatValue : "0.00")
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
StyledText {
id: txtFeeCurrency
font.pixelSize: 15
height: 22
text: root.currency
color: Style.current.secondaryText
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
SVGImage {
id: gasInvalid
anchors.verticalCenter: parent.verticalCenter
width: 13.33
height: 13.33
sourceSize.height: height * 2
sourceSize.width: width * 2
fillMode: Image.PreserveAspectFit
source: Style.svg("exclamation_outline")
visible: !root.gasValid
}
SVGImage {
id: gasArrow
width: 13
height: 7
visible: root.isGasEditable
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: Style.svg("caret")
rotation: 270
ColorOverlay {
anchors.fill: parent
visible: parent.visible
source: parent
color: Style.current.secondaryText
}
}
}
MouseArea {
anchors.fill: parent
visible: gasArrow.visible
cursorShape: Qt.PointingHandCursor
onClicked: root.gasClicked()
}
}
}
LabelValueRow {
id: itmData
label: qsTr("Data")
visible: trxData !== "0x" && trxData !== ""
value: Item {
id: dataRoot
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
Row {
spacing: Style.current.halfPadding
rightPadding: 0
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
StyledText {
font.pixelSize: 15
height: 22
width: 200
text: trxData
elide: Text.ElideRight
color: Style.current.secondaryText
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
verticalAlignment: Text.AlignVCenter
}
SVGImage {
width: 13
height: 7
visible: true
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
source: Style.svg("caret")
rotation: 270
ColorOverlay {
anchors.fill: parent
visible: parent.visible
source: parent
color: Style.current.secondaryText
}
}
}
// TODO: replace with StatusModal
ModalPopup {
id: dataPopup
title: qsTr("Data field")
height: 286
width: 400
Item {
anchors.fill: parent
anchors.leftMargin: 0
anchors.rightMargin: 0
StatusScrollView {
width: parent.width
height: 150
TextArea {
wrapMode: TextEdit.Wrap
readOnly: true
text: trxData
}
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: dataPopup.open()
}
}
}
}
}

View File

@ -1,70 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import utils 1.0
import "../controls"
StackView {
id: root
default property list<FormGroup> groups
property int currentIdx: 0
property bool isLastGroup: currentIdx === groups.length - 1
property bool isFirstGroup: currentIdx === 0
signal groupActivated(Item group)
property alias currentGroup: root.currentItem
readonly property string uuid: Utils.uuid()
property var next: function() {
if (groups && groups.length <= currentIdx + 1) {
return
}
const group = groups[++currentIdx]
this.push(group, StackView.Immediate)
}
property var back: function() {
if (currentIdx <= 0) {
return
}
this.pop()
currentIdx--
}
initialItem: groups[currentIdx]
anchors.fill: parent
// The below transitions are pointless, but without them,
// the final input in the final TransactionFormGroup will
// not be able to receive focus! Seems like a Qt bug...
pushEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:1
duration: 1
}
}
pushExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:1
duration: 1
}
}
popEnter: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:1
duration: 1
}
}
popExit: Transition {
PropertyAnimation {
property: "opacity"
from: 1
to:1
duration: 1
}
}
}

View File

@ -45,11 +45,7 @@ Item {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
if (root.state === Constants.addressRequested) {
Global.openPopup(selectAccountModalComponent);
} else if (root.state === Constants.transactionRequested) {
Global.openPopup(signTxComponent)
}
// ToDo launch send modal from here
}
}
}
@ -93,41 +89,4 @@ Item {
gasEstimateErrorPopup.close();
}
}
Component {
id: signTxComponent
SignTransactionModal {
anchors.centerIn: parent
store: root.store
contactsStore: root.contactsStore
msgId: messageId
isARequest: true
chainId: root.store.getChainIdForChat()
onClosed: destroy()
onOpenGasEstimateErrorPopup: {
gasEstimateErrorPopup.confirmationText = message + qsTr("Decline");
gasEstimateErrorPopup.open();
return;
}
selectedAccount: {}
selectedRecipient: root.selectedRecipient
selectedAsset: token
selectedAmount: tokenAmount
selectedFiatAmount: fiatValue
}
}
Component {
id: selectAccountModalComponent
SelectAccountModal {
id: selectAccountModal
anchors.centerIn: parent
accounts: root.store.accounts
currency: root.store.currentCurrency
onSelectAndShareAddressButtonClicked: {
root.store.acceptAddressRequest(messageId, accountSelector.selectedAccount.address)
selectAccountModal.close()
}
}
}
}

View File

@ -225,33 +225,10 @@ Item {
onSendTransaction: {
// TODO: https://github.com/status-im/status-desktop/issues/6778
console.log("not implemented")
// Global.openPopup(signTxComponent, {selectedAccount: {
// name: root.store.getAccountNameByAddress(fromAddress),
// address: fromAddress,
// color: root.store.getAccountIconColorByAddress(fromAddress),
// assets: root.store.getAccountAssetsByAddress(fromAddress)
// }})
}
}
}
Component {
id: signTxComponent
SignTransactionModal {
anchors.centerIn: parent
store: root.store
contactsStore: root.contactsStore
selectedAsset: root.token
selectedAmount: root.tokenAmount
selectedRecipient: root.selectedRecipient
selectedFiatAmount: root.fiatValue
selectedType: RecipientSelector.Type.Contact
chainId: root.store.getChainIdForChat()
onClosed: destroy()
msgId: messageId
}
}
StyledText {
id: timeText
color: Style.current.secondaryText

View File

@ -1,4 +1,3 @@
AmountToSend 1.0 AmountToSend.qml
AssetsView 1.0 AssetsView.qml
EnsResolver 1.0 EnsResolver.qml
ExistingContacts 1.0 ExistingContacts.qml
@ -9,10 +8,7 @@ PasswordConfirmationView 1.0 PasswordConfirmationView.qml
PickedContacts 1.0 PickedContacts.qml
ProfileDialogView 1.0 ProfileDialogView.qml
SearchResults 1.0 SearchResults.qml
TokenListView 1.0 TokenListView.qml
TransactionPreview 1.0 TransactionPreview.qml
TransactionSigner 1.0 TransactionSigner.qml
TransactionStackView 1.0 TransactionStackView.qml
SyncingDeviceView 1.0 SyncingDeviceView.qml
SyncingDisplayCode 1.0 SyncingDisplayCode.qml
SyncingErrorMessage 1.0 SyncingErrorMessage.qml