Files
pay/guis/desktop/ReceiveTransactionPane.qml
T
tomFlowee dfabcde813 Use Basic QQ Controls theme
The non-themed import basically is just a proxy using some
auto-detection to find out which theme to use.
As the app only uses the basic theme, this is what we'll import.
2025-06-19 15:09:36 +02:00

257 lines
8.5 KiB
QML

/*
* This file is part of the Flowee project
* Copyright (C) 2020-2024 Tom Zander <tom@flowee.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls.Basic as QQC2
import QtQuick.Layouts
import QtQuick.Shapes
import Flowee.org.pay
import "../Flowee" as Flowee
Item {
id: receivePane
property QtObject account: portfolio.current
PaymentRequest {
id: request
}
onAccountChanged: {
var state = request.state;
if (request.state === PaymentRequest.Unpaid) {
// I can only change the wallet without cost
// if no payment has been seen.
request.account = account;
}
}
onActiveFocusChanged: {
if (activeFocus)
request.start();
}
Flowee.Label {
id: instructions
anchors.horizontalCenter: parent.horizontalCenter
y: 20
text: qsTr("Share your QR code or copy address to receive")
opacity: 0.5
}
Flowee.QRWidget {
id: qr
width: Math.min(parent.width, 360)
anchors.top: instructions.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20
qrText: request.qr
Flowee.Label {
visible: request.failReason !== PaymentRequest.NoFailure
text: {
var f = request.failReason;
if (f === PaymentRequest.AccountEncrypted)
return qsTr("Encrypted Wallet");
if (f === PaymentRequest.AccountImporting)
return qsTr("Import Running...");
if (f === PaymentRequest.NoAccountSet)
return "No Account Set"; // not translated b/c cause is bug in QML
return "";
}
anchors.centerIn: parent
width: parent.width - 40
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
font.pointSize: 18
}
}
// the "payment received" screen.
Rectangle {
anchors.top: parent.top
anchors.topMargin: 20
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 10
anchors.bottom: qr.bottom
radius: 10
gradient: Gradient {
GradientStop {
position: 0.6
color: {
var state = request.state;
if (state === PaymentRequest.PaymentSeen || state === PaymentRequest.Unpaid)
return palette.base
if (state === PaymentRequest.DoubleSpentSeen)
return "#640e0f" // red
return "#3e8b4e" // in all other cases: green
}
Behavior on color { ColorAnimation {} }
}
GradientStop {
position: 0.1
color: palette.base
}
}
opacity: request.state === PaymentRequest.Unpaid ? 0: 1
// animating timer to indicate our checking the security of the transaction.
// (i.e. waiting for the double spent proof)
Item {
id: feedback
width: 160
height: 160
y: (parent.height - height) / 3 * 2
visible: request.state !== PaymentRequest.DoubleSpentSeen
Shape {
id: circleShape
anchors.fill: parent
opacity: progressCircle.sweepAngle === 340 ? 0 : 1
x: 40
ShapePath {
strokeWidth: 20
strokeColor: "#9ea0b0"
fillColor: "transparent"
capStyle: ShapePath.RoundCap
startX: 100; startY: 10
PathAngleArc {
id: progressCircle
centerX: 80
centerY: 80
radiusX: 70; radiusY: 70
startAngle: -80
sweepAngle: request.state === PaymentRequest.Unpaid ? 0: 340
Behavior on sweepAngle { NumberAnimation { duration: Pay.dspTimeout } }
}
}
Flowee.Label {
anchors.centerIn: parent
text: qsTr("Checking") // checking security
}
Behavior on opacity { OpacityAnimator {} }
}
Flowee.Label {
color: "green"
text: "✔"
opacity: 1 - circleShape.opacity
font.pixelSize: 130
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
}
}
Flowee.Label {
id: feedbackLabel
text: {
var s = request.state;
if (s === PaymentRequest.DoubleSpentSeen)
// double-spent-proof received
return qsTr("High risk transaction")
if (s === PaymentRequest.PaymentSeen)
return qsTr("Payment Seen")
if (s === PaymentRequest.PaymentSeenOk)
return qsTr("Payment Accepted")
if (s === PaymentRequest.Confirmed)
return qsTr("Payment Settled")
return "INTERNAL ERROR";
}
width: parent.width - 40
anchors.verticalCenter: feedback.verticalCenter
anchors.left: feedback.visible ? feedback.right : parent.left
anchors.leftMargin: 20
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
font.pointSize: 20
}
Flowee.Label {
visible: request.state === PaymentRequest.DoubleSpentSeen
anchors.top: feedbackLabel.bottom
anchors.right: parent.right
anchors.rightMargin: 10
width: parent.width - 20
horizontalAlignment: Qt.AlignRight
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: qsTr("Instant payment failed. Wait for confirmation. (double spent proof received)")
}
Behavior on opacity { OpacityAnimator {} }
}
// entry-fields
GridLayout {
id: grid
anchors.left: parent.left
anchors.right: parent.right
anchors.top: qr.bottom
anchors.topMargin: 30
anchors.leftMargin: 10
anchors.rightMargin: 10
columns: 2
Flowee.Label {
text: qsTr("Description") + ":"
}
Flowee.TextField {
id: description
Layout.fillWidth: true
enabled: request.state === PaymentRequest.Unpaid
onTextChanged: request.message = text
focus: true
}
Flowee.Label {
id: payAmount
text: qsTr("Amount") + ":"
}
RowLayout {
spacing: 10
Flowee.BitcoinValueField {
id: bitcoinValueField
enabled: request.state === PaymentRequest.Unpaid
onValueChanged: request.amount = value
}
Flowee.Label {
Layout.alignment: Qt.AlignBaseline
anchors.baselineOffset: bitcoinValueField.baselineOffset
text: Fiat.formattedPrice(bitcoinValueField.value, Fiat.price)
}
}
RowLayout {
Layout.columnSpan: 2
Layout.fillWidth: true
Item {
Layout.fillWidth: true
width: 1; height: 1
}
Flowee.Button {
text: request.state === PaymentRequest.Unpaid ? qsTr("Clear") : qsTr("Done")
onClicked: {
request.clear();
request.account = portfolio.current;
description.text = "";
bitcoinValueField.value = 0;
request.start();
}
}
}
}
}