1
mirror of https://github.com/monero-project/monero-gui synced 2024-11-28 09:31:37 +01:00

Merge pull request #3163

25ca0811 transfer: new TxConfirmationDialog (rating89us)
This commit is contained in:
Alexander Blair 2020-10-28 00:39:43 -07:00
commit 08635e3030
No known key found for this signature in database
GPG Key ID: C64552D877C32479
3 changed files with 530 additions and 92 deletions

View File

@ -0,0 +1,466 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import "../components" as MoneroComponents
import FontAwesome 1.0
Rectangle {
id: root
x: parent.width/2 - root.width/2
y: parent.height/2 - root.height/2
// TODO: implement without hardcoding sizes
width: 580
height: 400
color: MoneroComponents.Style.blackTheme ? "black" : "white"
visible: false
radius: 10
border.color: MoneroComponents.Style.blackTheme ? Qt.rgba(255, 255, 255, 0.25) : Qt.rgba(0, 0, 0, 0.25)
border.width: 1
focus: true
Keys.enabled: true
Keys.onEscapePressed: {
root.close()
root.clearFields()
root.rejected()
}
Keys.onEnterPressed: {
if (root.state == "default") {
root.close()
root.accepted()
} else if (root.state == "error") {
root.close()
root.clearFields()
root.rejected()
}
}
Keys.onReturnPressed: {
if (root.state == "default") {
root.close()
root.accepted()
} else if (root.state == "error") {
root.close()
root.clearFields()
root.rejected()
}
}
KeyNavigation.tab: confirmButton
property var transactionAmount: ""
property var transactionAddress: ""
property var transactionDescription: ""
property var transactionFee: ""
property var transactionPriority: ""
property bool sweepUnmixable: false
property alias errorText: errorText
property alias confirmButton: confirmButton
property alias backButton: backButton
property alias bottomText: bottomText
property alias bottomTextAnimation: bottomTextAnimation
state: "default"
states: [
State {
// waiting for user action, show tx details + back and confirm buttons
name: "default";
when: errorText.text == "" && bottomText.text == ""
PropertyChanges { target: errorText; visible: false }
PropertyChanges { target: txAmountText; visible: root.transactionAmount !== "(all)" || (root.transactionAmount === "(all)" && currentWallet.isHwBacked() === true) }
PropertyChanges { target: txAmountBusyIndicator; visible: !txAmountText.visible }
PropertyChanges { target: txFiatAmountText; visible: txAmountText.visible && persistentSettings.fiatPriceEnabled && root.transactionAmount !== "(all)" }
PropertyChanges { target: txDetails; visible: true }
PropertyChanges { target: bottom; visible: true }
PropertyChanges { target: bottomMessage; visible: false }
PropertyChanges { target: buttons; visible: true }
PropertyChanges { target: backButton; visible: true; primary: false }
PropertyChanges { target: confirmButton; visible: true }
}, State {
// error message being displayed, show only back button
name: "error";
when: errorText.text !== ""
PropertyChanges { target: dialogTitle; text: "Error" }
PropertyChanges { target: errorText; visible: true }
PropertyChanges { target: txAmountText; visible: false }
PropertyChanges { target: txAmountBusyIndicator; visible: false }
PropertyChanges { target: txFiatAmountText; visible: false }
PropertyChanges { target: txDetails; visible: false }
PropertyChanges { target: bottom; visible: true }
PropertyChanges { target: bottomMessage; visible: false }
PropertyChanges { target: buttons; visible: true }
PropertyChanges { target: backButton; visible: true; primary: true }
PropertyChanges { target: confirmButton; visible: false }
}, State {
// creating or sending transaction, show tx details and don't show any button
name: "bottomText";
when: errorText.text == "" && bottomText.text !== ""
PropertyChanges { target: errorText; visible: false }
PropertyChanges { target: txAmountText; visible: root.transactionAmount !== "(all)" || (root.transactionAmount === "(all)" && currentWallet.isHwBacked() === true) }
PropertyChanges { target: txAmountBusyIndicator; visible: !txAmountText.visible }
PropertyChanges { target: txFiatAmountText; visible: txAmountText.visible && persistentSettings.fiatPriceEnabled && root.transactionAmount !== "(all)" }
PropertyChanges { target: txDetails; visible: true }
PropertyChanges { target: bottom; visible: true }
PropertyChanges { target: bottomMessage; visible: true }
PropertyChanges { target: buttons; visible: false }
}
]
// same signals as Dialog has
signal accepted()
signal rejected()
function open() {
root.visible = true;
//clean previous error message
errorText.text = "";
root.forceActiveFocus()
}
function close() {
root.visible = false;
}
function clearFields() {
root.transactionAmount = "";
root.transactionAddress = "";
root.transactionDescription = "";
root.transactionFee = "";
root.transactionPriority = "";
root.sweepUnmixable = false;
}
function showFiatConversion(valueXMR) {
const fiatFee = fiatApiConvertToFiat(valueXMR);
return "%1 %2".arg(fiatFee < 0.01 ? "<0.01" : "~" + fiatFee).arg(fiatApiCurrencySymbol());
}
ColumnLayout {
spacing: 10
anchors.fill: parent
anchors.margins: 25
RowLayout {
Layout.topMargin: 10
Layout.fillWidth: true
MoneroComponents.Label {
id: dialogTitle
Layout.fillWidth: true
fontSize: 18
fontFamily: "Arial"
horizontalAlignment: Text.AlignHCenter
text: {
if (appWindow.viewOnly) {
return qsTr("Create transaction file") + translationManager.emptyString;
} else if (root.sweepUnmixable) {
return qsTr("Sweep unmixable outputs") + translationManager.emptyString;
} else {
return qsTr("Confirm send") + translationManager.emptyString;
}
}
}
}
Text {
id: errorText
Layout.fillWidth: true
Layout.fillHeight: true
color: MoneroComponents.Style.defaultFontColor
wrapMode: Text.Wrap
font.pixelSize: 15
}
ColumnLayout {
spacing: 0
Layout.fillWidth: true
Layout.preferredHeight: 71
BusyIndicator {
id: txAmountBusyIndicator
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
running: root.transactionAmount == "(all)"
}
Text {
id: txAmountText
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: root.transactionAmount == "(all)" && currentWallet.isHwBacked() === true ? 32 : 42
color: MoneroComponents.Style.defaultFontColor
text: {
if (root.transactionAmount == "(all)" && currentWallet.isHwBacked() === true) {
return qsTr("All unlocked balance") + translationManager.emptyString;
} else {
return root.transactionAmount + " XMR " + translationManager.emptyString;
}
}
}
Text {
id: txFiatAmountText
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 20
color: MoneroComponents.Style.buttonSecondaryTextColor
text: showFiatConversion(transactionAmount) + translationManager.emptyString
}
}
GridLayout {
columns: 2
id: txDetails
Layout.fillWidth: true
columnSpacing: 15
rowSpacing: 16
ColumnLayout {
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
Text {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("From") + ":" + translationManager.emptyString
font.pixelSize: 15
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 16
Text {
Layout.fillWidth: true
font.pixelSize: 15
color: MoneroComponents.Style.defaultFontColor
text: {
if (currentWallet) {
var walletTitle = function() {
if (currentWallet.isLedger()) {
return "Ledger";
} else if (currentWallet.isTrezor()) {
return "Trezor";
} else {
return qsTr("My wallet");
}
}
var walletName = appWindow.walletName;
if (appWindow.currentWallet.numSubaddressAccounts() > 1) {
var currentSubaddressAccount = currentWallet.currentSubaddressAccount;
var currentAccountLabel = currentWallet.getSubaddressLabel(currentWallet.currentSubaddressAccount, 0);
return walletTitle() + " (" + walletName + ")" + "<br>" + qsTr("Account #") + currentSubaddressAccount + (currentAccountLabel !== "" ? " (" + currentAccountLabel + ")" : "") + translationManager.emptyString;
} else {
return walletTitle() + " (" + walletName + ")" + translationManager.emptyString;
}
} else {
return "";
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
Text {
Layout.fillWidth: true
font.pixelSize: 15
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("To") + ":" + translationManager.emptyString
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 16
Text {
Layout.fillWidth: true
font.pixelSize: 15
font.family: MoneroComponents.Style.fontRegular.name
textFormat: Text.RichText
wrapMode: Text.Wrap
color: MoneroComponents.Style.defaultFontColor
text: {
if (root.transactionAddress) {
const addressBookName = currentWallet ? currentWallet.addressBook.getDescription(root.transactionAddress) : null;
var fulladdress = root.transactionAddress;
var spacedaddress = fulladdress.match(/.{1,4}/g);
var spacedaddress = spacedaddress.join(' ');
if (!addressBookName) {
return qsTr("Monero address") + "<br>" + spacedaddress + translationManager.emptyString;
} else {
return FontAwesome.addressBook + " " + addressBookName + "<br>" + spacedaddress;
}
} else {
return "";
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.alignment : Qt.AlignTop | Qt.AlignLeft
Text {
Layout.fillWidth: true
color: MoneroComponents.Style.dimmedFontColor
text: qsTr("Fee") + ":" + translationManager.emptyString
font.pixelSize: 15
}
}
RowLayout {
Layout.fillWidth: true
spacing: 16
Text {
color: MoneroComponents.Style.defaultFontColor
font.pixelSize: 15
text: {
if (currentWallet) {
if (!root.transactionFee) {
if (currentWallet.isHwBacked() === true) {
return qsTr("See on device") + translationManager.emptyString;
} else {
return qsTr("Calculating fee") + "..." + translationManager.emptyString;
}
} else {
return root.transactionFee + " XMR"
}
} else {
return "";
}
}
}
Text {
Layout.fillWidth: true
Layout.leftMargin: 8
color: MoneroComponents.Style.buttonSecondaryTextColor
visible: persistentSettings.fiatPriceEnabled && root.transactionFee
font.pixelSize: 15
text: showFiatConversion(root.transactionFee)
}
}
}
ColumnLayout {
id: bottom
Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter
Layout.fillWidth: true
RowLayout {
id: bottomMessage
Layout.fillWidth: true
Layout.preferredHeight: 50
BusyIndicator {
visible: !bottomTextAnimation.running
running: !bottomTextAnimation.running
scale: .5
}
Text {
id: bottomText
color: MoneroComponents.Style.defaultFontColor
text: ""
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
font.pixelSize: 17
opacity: 1
SequentialAnimation{
id:bottomTextAnimation
running: false
loops: Animation.Infinite
alwaysRunToEnd: true
NumberAnimation { target: bottomText; property: "opacity"; to: 0; duration: 500}
NumberAnimation { target: bottomText; property: "opacity"; to: 1; duration: 500}
}
}
}
RowLayout {
id: buttons
spacing: 70
Layout.fillWidth: true
Layout.preferredHeight: 50
MoneroComponents.StandardButton {
id: backButton
text: qsTr("Back") + translationManager.emptyString;
width: 200
focus: false
primary: false
KeyNavigation.tab: confirmButton
Keys.enabled: backButton.visible
Keys.onReturnPressed: backButton.onClicked
Keys.onEnterPressed: backButton.onClicked
Keys.onEscapePressed: {
root.close()
root.clearFields()
root.rejected()
}
onClicked: {
root.close()
root.clearFields()
root.rejected()
}
}
MoneroComponents.StandardButton {
id: confirmButton
text: qsTr("Confirm") + translationManager.emptyString;
rightIcon: "qrc:///images/rightArrow.png"
width: 200
focus: false
KeyNavigation.tab: backButton
Keys.enabled: confirmButton.visible
Keys.onReturnPressed: confirmButton.onClicked
Keys.onEnterPressed: confirmButton.onClicked
Keys.onEscapePressed: {
root.close()
root.clearFields()
root.rejected()
}
onClicked: {
root.close()
root.accepted()
}
}
}
}
}
}

155
main.qml
View File

@ -65,7 +65,6 @@ ApplicationWindow {
property var currentWallet;
property bool disconnected: currentWallet ? currentWallet.disconnected : false
property var transaction;
property var transactionDescription;
property var walletPassword
property int restoreHeight:0
property bool daemonSynced: false
@ -508,16 +507,30 @@ ApplicationWindow {
}
function onDeviceButtonRequest(code){
prevSplashText = splash.messageText;
splashDisplayedBeforeButtonRequest = splash.visible;
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
if (txConfirmationPopup.visible) {
txConfirmationPopup.bottomTextAnimation.running = true
if (!txConfirmationPopup.errorText.visible) {
txConfirmationPopup.bottomText.text = qsTr("Please confirm transaction on the device...") + translationManager.emptyString;
} else {
txConfirmationPopup.bottomText.text = qsTr("Please proceed to the device...") + translationManager.emptyString;
}
} else {
prevSplashText = splash.messageText;
splashDisplayedBeforeButtonRequest = splash.visible;
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
}
}
function onDeviceButtonPressed(){
if (splashDisplayedBeforeButtonRequest){
appWindow.showProcessingSplash(prevSplashText);
if (txConfirmationPopup.visible) {
txConfirmationPopup.bottomTextAnimation.running = false;
txConfirmationPopup.bottomText.text = qsTr("Signing transaction in the device...") + translationManager.emptyString;
} else {
hideProcessingSplash();
if (splashDisplayedBeforeButtonRequest){
appWindow.showProcessingSplash(prevSplashText);
} else {
hideProcessingSplash();
}
}
}
@ -812,51 +825,33 @@ ApplicationWindow {
function onTransactionCreated(pendingTransaction,address,paymentId,mixinCount){
console.log("Transaction created");
hideProcessingSplash();
txConfirmationPopup.bottomText.text = "";
transaction = pendingTransaction;
// validate address;
if (transaction.status !== PendingTransaction.Status_Ok) {
console.error("Can't create transaction: ", transaction.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString;
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion)
informationPopup.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
else
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion) {
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
} else {
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString
}
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else if (transaction.txCount == 0) {
informationPopup.title = qsTr("Error") + translationManager.emptyString
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
informationPopup.icon = StandardIcon.Information
informationPopup.onCloseCallback = null
informationPopup.open()
console.error("Can't create transaction: ", transaction.errorString);
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else {
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
+ ", fee: " + walletManager.displayAmount(transaction.fee));
// here we show confirmation popup;
transactionConfirmationPopup.title = qsTr("Please confirm transaction:\n") + translationManager.emptyString;
transactionConfirmationPopup.text = "";
transactionConfirmationPopup.text += (address === "" ? "" : (qsTr("Address: ") + address));
transactionConfirmationPopup.text += (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId));
transactionConfirmationPopup.text += qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount);
transactionConfirmationPopup.text += qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee);
transactionConfirmationPopup.text += qsTr("\nRingsize: ") + (mixinCount + 1);
transactionConfirmationPopup.text += qsTr("\n\nNumber of transactions: ") + transaction.txCount
transactionConfirmationPopup.text += (transactionDescription === "" ? "" : (qsTr("\nDescription: ") + transactionDescription))
for (var i = 0; i < transaction.subaddrIndices.length; ++i){
transactionConfirmationPopup.text += qsTr("\nSpending address index: ") + transaction.subaddrIndices[i];
}
transactionConfirmationPopup.text += translationManager.emptyString;
transactionConfirmationPopup.icon = StandardIcon.Question
transactionConfirmationPopup.open()
// here we update txConfirmationPopup
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
txConfirmationPopup.confirmButton.text = viewOnly ? qsTr("Save as file") : qsTr("Confirm") + translationManager.emptyString;
txConfirmationPopup.confirmButton.rightIcon = viewOnly ? "" : "qrc:///images/rightArrow.png"
}
}
@ -870,12 +865,12 @@ ApplicationWindow {
", mixins: ", mixinCount,
", priority: ", priority,
", description: ", description);
var splashMsg = qsTr("Creating transaction...");
splashMsg += appWindow.currentWallet.isLedger() ? qsTr("\n\nPlease check your hardware wallet \nyour input may be required.") : "";
showProcessingSplash(splashMsg);
transactionDescription = description;
txConfirmationPopup.bottomTextAnimation.running = false
txConfirmationPopup.bottomText.text = qsTr("Creating transaction...") + translationManager.emptyString;
txConfirmationPopup.transactionAddress = address;
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(amount);
txConfirmationPopup.transactionPriority = priority;
txConfirmationPopup.transactionDescription = description;
// validate amount;
if (amount !== "(all)") {
@ -883,31 +878,21 @@ ApplicationWindow {
console.log("integer amount: ", amountxmr);
console.log("integer unlocked", currentWallet.unlockedBalance())
if (amountxmr <= 0) {
hideProcessingSplash()
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Amount is wrong: expected number from %1 to %2")
.arg(walletManager.displayAmount(0))
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open()
txConfirmationPopup.errorText.text = qsTr("Amount is wrong: expected number from %1 to %2")
.arg(walletManager.displayAmount(0))
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString;
return;
} else if (amountxmr > currentWallet.unlockedBalance()) {
hideProcessingSplash()
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Insufficient funds. Unlocked balance: %1")
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open()
txConfirmationPopup.errorText.text = qsTr("Insufficient funds. Unlocked balance: %1")
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
+ translationManager.emptyString;
return;
}
}
txConfirmationPopup.open();
if (amount === "(all)")
currentWallet.createTransactionAllAsync(address, paymentId, mixinCount, priority);
else
@ -935,40 +920,27 @@ ApplicationWindow {
function handleSweepUnmixable() {
console.log("Creating transaction: ")
txConfirmationPopup.sweepUnmixable = true;
transaction = currentWallet.createSweepUnmixableTransaction();
if (transaction.status !== PendingTransaction.Status_Ok) {
console.error("Can't create transaction: ", transaction.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
informationPopup.icon = StandardIcon.Critical
informationPopup.onCloseCallback = null
informationPopup.open();
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString + translationManager.emptyString
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else if (transaction.txCount == 0) {
informationPopup.title = qsTr("Error") + translationManager.emptyString
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
informationPopup.icon = StandardIcon.Information
informationPopup.onCloseCallback = null
informationPopup.open()
console.error("No unmixable outputs to sweep");
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
// deleting transaction object, we don't want memleaks
currentWallet.disposeTransaction(transaction);
} else {
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
+ ", fee: " + walletManager.displayAmount(transaction.fee));
// here we show confirmation popup;
transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n")
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee)
+ translationManager.emptyString
transactionConfirmationPopup.icon = StandardIcon.Question
transactionConfirmationPopup.open()
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
// committing transaction
}
txConfirmationPopup.open();
}
// called after user confirms transaction
@ -986,13 +958,10 @@ ApplicationWindow {
// Store to file
transaction.setFilename(path);
}
appWindow.showProcessingSplash(qsTr("Sending transaction ..."));
currentWallet.commitTransactionAsync(transaction);
}
function onTransactionCommitted(success, transaction, txid) {
hideProcessingSplash();
if (!success) {
console.log("Error committing transaction: " + transaction.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString
@ -1001,13 +970,14 @@ ApplicationWindow {
informationPopup.onCloseCallback = null;
informationPopup.open();
} else {
if (transactionDescription.length > 0) {
if (txConfirmationPopup.transactionDescription.length > 0) {
for (var i = 0; i < txid.length; ++i)
currentWallet.setUserNote(txid[i], transactionDescription);
currentWallet.setUserNote(txid[i], txConfirmationPopup.transactionDescription);
}
// Clear tx fields
middlePanel.transferView.clearFields()
txConfirmationPopup.clearFields()
successfulTxPopup.open(txid)
}
currentWallet.refresh()
@ -1459,10 +1429,11 @@ ApplicationWindow {
}
}
// Confrirmation aka question dialog
StandardDialog {
// Transaction confirmation popup
TxConfirmationDialog {
// dynamically change onclose handler
id: txConfirmationPopup
z: parent.z + 1
id: transactionConfirmationPopup
onAccepted: {
var handleAccepted = function() {
// Save transaction to file if view only wallet
@ -1768,7 +1739,7 @@ ApplicationWindow {
anchors.fill: blurredArea
source: blurredArea
radius: 64
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || devicePassphraseDialog.visible || successfulTxPopup.visible
visible: passwordDialog.visible || inputDialog.visible || splash.visible || updateDialog.visible || devicePassphraseDialog.visible || txConfirmationPopup.visible || successfulTxPopup.visible
}

View File

@ -243,5 +243,6 @@
<file>images/success.png</file>
<file>images/success@2x.png</file>
<file>components/SuccessfulTxDialog.qml</file>
<file>components/TxConfirmationDialog.qml</file>
</qresource>
</RCC>