From 25ca0811099ad3485e47155bc23916da270a5604 Mon Sep 17 00:00:00 2001
From: rating89us <45968869+rating89us@users.noreply.github.com>
Date: Sat, 17 Oct 2020 11:57:37 +0200
Subject: [PATCH] transfer: new TxConfirmationDialog
---
components/TxConfirmationDialog.qml | 466 ++++++++++++++++++++++++++++
main.qml | 155 ++++-----
qml.qrc | 1 +
3 files changed, 530 insertions(+), 92 deletions(-)
create mode 100644 components/TxConfirmationDialog.qml
diff --git a/components/TxConfirmationDialog.qml b/components/TxConfirmationDialog.qml
new file mode 100644
index 00000000..1d0a21e9
--- /dev/null
+++ b/components/TxConfirmationDialog.qml
@@ -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 + ")" + "
" + 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") + "
" + spacedaddress + translationManager.emptyString;
+ } else {
+ return FontAwesome.addressBook + " " + addressBookName + "
" + 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()
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/main.qml b/main.qml
index c849939c..b5f8dcd3 100644
--- a/main.qml
+++ b/main.qml
@@ -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();
+ }
}
}
@@ -811,51 +824,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"
}
}
@@ -869,12 +864,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)") {
@@ -882,31 +877,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
@@ -934,40 +919,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
@@ -985,13 +957,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
@@ -1000,13 +969,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()
@@ -1458,10 +1428,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
@@ -1767,7 +1738,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
}
diff --git a/qml.qrc b/qml.qrc
index 4e722891..31754983 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -243,5 +243,6 @@
images/success.png
images/success@2x.png
components/SuccessfulTxDialog.qml
+ components/TxConfirmationDialog.qml