mirror of
https://github.com/monero-project/monero-gui.git
synced 2025-01-22 10:44:46 +00:00
transfer: new TxConfirmationDialog
This commit is contained in:
parent
cb1f3ad0ce
commit
25ca081109
3 changed files with 530 additions and 92 deletions
466
components/TxConfirmationDialog.qml
Normal file
466
components/TxConfirmationDialog.qml
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
main.qml
137
main.qml
|
@ -65,7 +65,6 @@ ApplicationWindow {
|
||||||
property var currentWallet;
|
property var currentWallet;
|
||||||
property bool disconnected: currentWallet ? currentWallet.disconnected : false
|
property bool disconnected: currentWallet ? currentWallet.disconnected : false
|
||||||
property var transaction;
|
property var transaction;
|
||||||
property var transactionDescription;
|
|
||||||
property var walletPassword
|
property var walletPassword
|
||||||
property int restoreHeight:0
|
property int restoreHeight:0
|
||||||
property bool daemonSynced: false
|
property bool daemonSynced: false
|
||||||
|
@ -508,18 +507,32 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDeviceButtonRequest(code){
|
function onDeviceButtonRequest(code){
|
||||||
|
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;
|
prevSplashText = splash.messageText;
|
||||||
splashDisplayedBeforeButtonRequest = splash.visible;
|
splashDisplayedBeforeButtonRequest = splash.visible;
|
||||||
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
|
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onDeviceButtonPressed(){
|
function onDeviceButtonPressed(){
|
||||||
|
if (txConfirmationPopup.visible) {
|
||||||
|
txConfirmationPopup.bottomTextAnimation.running = false;
|
||||||
|
txConfirmationPopup.bottomText.text = qsTr("Signing transaction in the device...") + translationManager.emptyString;
|
||||||
|
} else {
|
||||||
if (splashDisplayedBeforeButtonRequest){
|
if (splashDisplayedBeforeButtonRequest){
|
||||||
appWindow.showProcessingSplash(prevSplashText);
|
appWindow.showProcessingSplash(prevSplashText);
|
||||||
} else {
|
} else {
|
||||||
hideProcessingSplash();
|
hideProcessingSplash();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onWalletOpening(){
|
function onWalletOpening(){
|
||||||
appWindow.showProcessingSplash(qsTr("Opening wallet ..."));
|
appWindow.showProcessingSplash(qsTr("Opening wallet ..."));
|
||||||
|
@ -811,51 +824,33 @@ ApplicationWindow {
|
||||||
|
|
||||||
function onTransactionCreated(pendingTransaction,address,paymentId,mixinCount){
|
function onTransactionCreated(pendingTransaction,address,paymentId,mixinCount){
|
||||||
console.log("Transaction created");
|
console.log("Transaction created");
|
||||||
hideProcessingSplash();
|
txConfirmationPopup.bottomText.text = "";
|
||||||
transaction = pendingTransaction;
|
transaction = pendingTransaction;
|
||||||
// validate address;
|
// validate address;
|
||||||
if (transaction.status !== PendingTransaction.Status_Ok) {
|
if (transaction.status !== PendingTransaction.Status_Ok) {
|
||||||
console.error("Can't create transaction: ", transaction.errorString);
|
console.error("Can't create transaction: ", transaction.errorString);
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion) {
|
||||||
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion)
|
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
|
||||||
informationPopup.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
|
} else {
|
||||||
else
|
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString
|
||||||
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
|
}
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open();
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
|
|
||||||
} else if (transaction.txCount == 0) {
|
} else if (transaction.txCount == 0) {
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
console.error("Can't create transaction: ", transaction.errorString);
|
||||||
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
||||||
informationPopup.icon = StandardIcon.Information
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
} else {
|
} else {
|
||||||
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
||||||
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
||||||
|
|
||||||
// here we show confirmation popup;
|
// here we update txConfirmationPopup
|
||||||
transactionConfirmationPopup.title = qsTr("Please confirm transaction:\n") + translationManager.emptyString;
|
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
|
||||||
transactionConfirmationPopup.text = "";
|
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
|
||||||
transactionConfirmationPopup.text += (address === "" ? "" : (qsTr("Address: ") + address));
|
txConfirmationPopup.confirmButton.text = viewOnly ? qsTr("Save as file") : qsTr("Confirm") + translationManager.emptyString;
|
||||||
transactionConfirmationPopup.text += (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId));
|
txConfirmationPopup.confirmButton.rightIcon = viewOnly ? "" : "qrc:///images/rightArrow.png"
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,12 +864,12 @@ ApplicationWindow {
|
||||||
", mixins: ", mixinCount,
|
", mixins: ", mixinCount,
|
||||||
", priority: ", priority,
|
", priority: ", priority,
|
||||||
", description: ", description);
|
", description: ", description);
|
||||||
|
txConfirmationPopup.bottomTextAnimation.running = false
|
||||||
var splashMsg = qsTr("Creating transaction...");
|
txConfirmationPopup.bottomText.text = qsTr("Creating transaction...") + translationManager.emptyString;
|
||||||
splashMsg += appWindow.currentWallet.isLedger() ? qsTr("\n\nPlease check your hardware wallet –\nyour input may be required.") : "";
|
txConfirmationPopup.transactionAddress = address;
|
||||||
showProcessingSplash(splashMsg);
|
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(amount);
|
||||||
|
txConfirmationPopup.transactionPriority = priority;
|
||||||
transactionDescription = description;
|
txConfirmationPopup.transactionDescription = description;
|
||||||
|
|
||||||
// validate amount;
|
// validate amount;
|
||||||
if (amount !== "(all)") {
|
if (amount !== "(all)") {
|
||||||
|
@ -882,31 +877,21 @@ ApplicationWindow {
|
||||||
console.log("integer amount: ", amountxmr);
|
console.log("integer amount: ", amountxmr);
|
||||||
console.log("integer unlocked", currentWallet.unlockedBalance())
|
console.log("integer unlocked", currentWallet.unlockedBalance())
|
||||||
if (amountxmr <= 0) {
|
if (amountxmr <= 0) {
|
||||||
hideProcessingSplash()
|
txConfirmationPopup.errorText.text = qsTr("Amount is wrong: expected number from %1 to %2")
|
||||||
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(0))
|
||||||
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
||||||
+ translationManager.emptyString
|
+ translationManager.emptyString;
|
||||||
|
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
return;
|
return;
|
||||||
} else if (amountxmr > currentWallet.unlockedBalance()) {
|
} else if (amountxmr > currentWallet.unlockedBalance()) {
|
||||||
hideProcessingSplash()
|
txConfirmationPopup.errorText.text = qsTr("Insufficient funds. Unlocked balance: %1")
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
|
||||||
informationPopup.text = qsTr("Insufficient funds. Unlocked balance: %1")
|
|
||||||
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
.arg(walletManager.displayAmount(currentWallet.unlockedBalance()))
|
||||||
+ translationManager.emptyString
|
+ translationManager.emptyString;
|
||||||
|
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
txConfirmationPopup.open();
|
||||||
|
|
||||||
if (amount === "(all)")
|
if (amount === "(all)")
|
||||||
currentWallet.createTransactionAllAsync(address, paymentId, mixinCount, priority);
|
currentWallet.createTransactionAllAsync(address, paymentId, mixinCount, priority);
|
||||||
else
|
else
|
||||||
|
@ -934,40 +919,27 @@ ApplicationWindow {
|
||||||
function handleSweepUnmixable() {
|
function handleSweepUnmixable() {
|
||||||
console.log("Creating transaction: ")
|
console.log("Creating transaction: ")
|
||||||
|
|
||||||
|
txConfirmationPopup.sweepUnmixable = true;
|
||||||
transaction = currentWallet.createSweepUnmixableTransaction();
|
transaction = currentWallet.createSweepUnmixableTransaction();
|
||||||
if (transaction.status !== PendingTransaction.Status_Ok) {
|
if (transaction.status !== PendingTransaction.Status_Ok) {
|
||||||
console.error("Can't create transaction: ", transaction.errorString);
|
console.error("Can't create transaction: ", transaction.errorString);
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString;
|
txConfirmationPopup.errorText.text = qsTr("Can't create transaction: ") + transaction.errorString + translationManager.emptyString
|
||||||
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
|
|
||||||
informationPopup.icon = StandardIcon.Critical
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open();
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
|
|
||||||
} else if (transaction.txCount == 0) {
|
} else if (transaction.txCount == 0) {
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
console.error("No unmixable outputs to sweep");
|
||||||
informationPopup.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
txConfirmationPopup.errorText.text = qsTr("No unmixable outputs to sweep") + translationManager.emptyString
|
||||||
informationPopup.icon = StandardIcon.Information
|
|
||||||
informationPopup.onCloseCallback = null
|
|
||||||
informationPopup.open()
|
|
||||||
// deleting transaction object, we don't want memleaks
|
// deleting transaction object, we don't want memleaks
|
||||||
currentWallet.disposeTransaction(transaction);
|
currentWallet.disposeTransaction(transaction);
|
||||||
} else {
|
} else {
|
||||||
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount)
|
||||||
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
+ ", fee: " + walletManager.displayAmount(transaction.fee));
|
||||||
|
txConfirmationPopup.transactionAmount = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.amount));
|
||||||
// here we show confirmation popup;
|
txConfirmationPopup.transactionFee = Utils.removeTrailingZeros(walletManager.displayAmount(transaction.fee));
|
||||||
|
|
||||||
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()
|
|
||||||
// committing transaction
|
// committing transaction
|
||||||
}
|
}
|
||||||
|
txConfirmationPopup.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
// called after user confirms transaction
|
// called after user confirms transaction
|
||||||
|
@ -985,13 +957,10 @@ ApplicationWindow {
|
||||||
// Store to file
|
// Store to file
|
||||||
transaction.setFilename(path);
|
transaction.setFilename(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
appWindow.showProcessingSplash(qsTr("Sending transaction ..."));
|
|
||||||
currentWallet.commitTransactionAsync(transaction);
|
currentWallet.commitTransactionAsync(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTransactionCommitted(success, transaction, txid) {
|
function onTransactionCommitted(success, transaction, txid) {
|
||||||
hideProcessingSplash();
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.log("Error committing transaction: " + transaction.errorString);
|
console.log("Error committing transaction: " + transaction.errorString);
|
||||||
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
informationPopup.title = qsTr("Error") + translationManager.emptyString
|
||||||
|
@ -1000,13 +969,14 @@ ApplicationWindow {
|
||||||
informationPopup.onCloseCallback = null;
|
informationPopup.onCloseCallback = null;
|
||||||
informationPopup.open();
|
informationPopup.open();
|
||||||
} else {
|
} else {
|
||||||
if (transactionDescription.length > 0) {
|
if (txConfirmationPopup.transactionDescription.length > 0) {
|
||||||
for (var i = 0; i < txid.length; ++i)
|
for (var i = 0; i < txid.length; ++i)
|
||||||
currentWallet.setUserNote(txid[i], transactionDescription);
|
currentWallet.setUserNote(txid[i], txConfirmationPopup.transactionDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear tx fields
|
// Clear tx fields
|
||||||
middlePanel.transferView.clearFields()
|
middlePanel.transferView.clearFields()
|
||||||
|
txConfirmationPopup.clearFields()
|
||||||
successfulTxPopup.open(txid)
|
successfulTxPopup.open(txid)
|
||||||
}
|
}
|
||||||
currentWallet.refresh()
|
currentWallet.refresh()
|
||||||
|
@ -1458,10 +1428,11 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confrirmation aka question dialog
|
// Transaction confirmation popup
|
||||||
StandardDialog {
|
TxConfirmationDialog {
|
||||||
|
// dynamically change onclose handler
|
||||||
|
id: txConfirmationPopup
|
||||||
z: parent.z + 1
|
z: parent.z + 1
|
||||||
id: transactionConfirmationPopup
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
var handleAccepted = function() {
|
var handleAccepted = function() {
|
||||||
// Save transaction to file if view only wallet
|
// Save transaction to file if view only wallet
|
||||||
|
@ -1767,7 +1738,7 @@ ApplicationWindow {
|
||||||
anchors.fill: blurredArea
|
anchors.fill: blurredArea
|
||||||
source: blurredArea
|
source: blurredArea
|
||||||
radius: 64
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
1
qml.qrc
1
qml.qrc
|
@ -243,5 +243,6 @@
|
||||||
<file>images/success.png</file>
|
<file>images/success.png</file>
|
||||||
<file>images/success@2x.png</file>
|
<file>images/success@2x.png</file>
|
||||||
<file>components/SuccessfulTxDialog.qml</file>
|
<file>components/SuccessfulTxDialog.qml</file>
|
||||||
|
<file>components/TxConfirmationDialog.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
Loading…
Reference in a new issue