Files
pay/desktop/ReceiveTransactionPane.qml
T

330 lines
11 KiB
QML
Raw Permalink Normal View History

/*
* This file is part of the Flowee project
* Copyright (C) 2020-2021 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/>.
*/
2021-05-23 00:27:34 +02:00
import QtQuick 2.11
import QtQuick.Controls 2.11
import QtQuick.Layouts 1.11
import QtQuick.Shapes 1.11 // for shape-path
import Flowee.org.pay 1.0
Pane {
id: receivePane
2021-01-16 17:01:42 +01:00
2021-04-20 19:30:56 +02:00
property QtObject account: portfolio.current
2021-04-21 17:17:47 +02:00
property QtObject request: null
onAccountChanged: {
if (account === null)
return;
if (request === null)
request = account.createPaymentRequest(receivePane)
else
request.switchAccount(portfolio.current);
}
2021-04-21 18:15:14 +02:00
function reset() {
2021-05-05 12:42:26 +02:00
if (request.saveState !== PaymentRequest.Stored)
request.destroy();
request = account.createPaymentRequest(receivePane)
2021-04-21 18:15:14 +02:00
description.text = "";
2021-05-01 13:15:39 +02:00
bitcoinValueField.reset();
2021-04-21 18:15:14 +02:00
}
2021-04-21 17:17:47 +02:00
Label {
id: instructions
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20
2021-04-30 17:54:26 +02:00
text: qsTr("Share your QR code or copy address to receive")
opacity: 0.5
2021-04-21 17:17:47 +02:00
}
Image {
id: qrCode
width: height
height: {
var h = parent.height - 220;
return Math.min(h, 256)
}
source: "image://qr/" + receivePane.request.qr
smooth: false
anchors.horizontalCenter: parent.horizontalCenter
2021-04-21 17:17:47 +02:00
anchors.top: instructions.bottom
anchors.topMargin: 20
2021-01-18 14:27:24 +01:00
opacity: receivePane.request.state === PaymentRequest.Unpaid ? 1: 0
MouseArea {
anchors.fill: parent
onClicked: {
Flowee.copyToClipboard(receivePane.request.qr)
2021-02-05 16:53:42 +01:00
clipboardFeedback.opacity = 1
}
}
Rectangle {
2021-01-18 14:27:24 +01:00
id: clipboardFeedback
opacity: 0
2021-04-29 16:31:32 +02:00
width: feedbackText.width + 20
height: feedbackText.height + 20
radius: 10
color: Flowee.useDarkSkin ? "#333" : "#ddd"
2021-04-29 15:24:01 +02:00
anchors.top: parent.bottom
anchors.topMargin: -13
anchors.horizontalCenter: parent.horizontalCenter
Label {
id: feedbackText
x: 10
y: 10
text: qsTr("Copied to clipboard")
wrapMode: Text.WordWrap
}
Behavior on opacity { OpacityAnimator {} }
/// after 10 seconds, remove feedback.
Timer {
interval: 10000
2021-01-18 14:27:24 +01:00
running: clipboardFeedback.opacity === 1
onTriggered: clipboardFeedback.opacity = 0
}
}
2021-01-18 14:27:24 +01:00
Behavior on opacity { OpacityAnimator {} }
}
2021-01-18 14:27:24 +01:00
// the "payment received" screen.
Rectangle {
anchors.top: parent.top
anchors.topMargin: 20
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: qrCode.bottom
radius: 10
gradient: Gradient {
GradientStop {
position: 0.6
color: {
var state = receivePane.request.state;
if (state === PaymentRequest.PaymentSeen || state === PaymentRequest.Unpaid)
return receivePane.palette.base
if (state === PaymentRequest.DoubleSpentSeen)
return "#640e0f" // red
return "#3e8b4e" // in all other cases: green
}
Behavior on color { ColorAnimation {} }
}
GradientStop {
position: 0.1
2021-04-21 17:17:47 +02:00
color: receivePane.palette.base
2021-01-18 14:27:24 +01:00
}
}
opacity: receivePane.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: receivePane.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: receivePane.request.state === PaymentRequest.Unpaid ? 0: 340
Behavior on sweepAngle { NumberAnimation { duration: Flowee.dspTimeout } }
}
}
Label {
anchors.centerIn: parent
text: qsTr("Checking") // checking security
}
Behavior on opacity { OpacityAnimator {} }
}
Label {
color: "green"
text: "✔"
opacity: 1 - circleShape.opacity
font.pixelSize: 130
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
}
}
Label {
id: feedbackLabel
2021-01-18 14:27:24 +01:00
text: {
var s = receivePane.request.state;
if (s === PaymentRequest.DoubleSpentSeen)
// double-spent-proof received
return qsTr("Transaction high risk")
2021-01-18 14:27:24 +01:00
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";
2021-01-18 14:27:24 +01:00
}
2021-02-04 19:21:45 +01:00
width: parent.width - 40
2021-01-18 14:27:24 +01:00
anchors.verticalCenter: feedback.verticalCenter
anchors.left: feedback.visible ? feedback.right : parent.left
anchors.leftMargin: 20
2021-02-04 19:21:45 +01:00
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
2021-01-18 14:27:24 +01:00
font.pointSize: 20
}
Label {
visible: receivePane.request.state === PaymentRequest.DoubleSpentSeen
anchors.top: feedbackLabel.bottom
2021-02-04 19:21:45 +01:00
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)")
}
2021-01-18 14:27:24 +01:00
Behavior on opacity { OpacityAnimator {} }
}
// entry-fields
GridLayout {
id: grid
anchors.left: parent.left
anchors.right: parent.right
anchors.top: qrCode.bottom
anchors.topMargin: 30
columns: 2
Label {
2021-01-29 10:27:24 +01:00
text: qsTr("Description") + ":"
}
TextField {
id: description
Layout.fillWidth: true
2021-01-18 14:27:24 +01:00
enabled: receivePane.request.state === PaymentRequest.Unpaid
onTextChanged: receivePane.request.message = text
}
Label {
id: payAmount
2021-01-29 10:27:24 +01:00
text: qsTr("Amount") + ":"
}
2021-05-08 00:03:07 +02:00
RowLayout {
spacing: 10
BitcoinValueField {
id: bitcoinValueField
fontPtSize: payAmount.font.pointSize
enabled: receivePane.request.state === PaymentRequest.Unpaid
onValueChanged: receivePane.request.amount = value
}
Label {
Layout.alignment: Qt.AlignBaseline
anchors.baselineOffset: bitcoinValueField.baselineOffset
text: Fiat.formattedPrice(bitcoinValueField.value, Fiat.price)
}
}
RowLayout {
Layout.columnSpan: 2
Layout.fillWidth: true
Pane {
Layout.fillWidth: true
}
2021-01-06 23:15:54 +01:00
Button {
text: qsTr("Remember", "payment request")
visible: receivePane.request.state === PaymentRequest.Unpaid || receivePane.request.state === PaymentRequest.DoubleSpentSeen
2021-01-06 23:15:54 +01:00
onClicked: {
2021-05-05 12:42:26 +02:00
receivePane.request.stored = true
2021-04-21 20:12:58 +02:00
reset();
2021-01-06 23:15:54 +01:00
}
}
Button {
2021-05-05 12:42:26 +02:00
text: receivePane.request.state === PaymentRequest.Unpaid ? qsTr("Clear") : qsTr("Done")
onClicked: {
reset();
}
}
}
}
Flow {
width: parent.width
anchors.bottom: parent.bottom
spacing: 10
Repeater {
model: portfolio.current.paymentRequests
delegate: Rectangle {
width: 70
height: width
radius: 25
clip: true
border.width: 6
border.color: {
var state = modelData.state;
if (state === PaymentRequest.Unpaid)
return "#888888"
if (state === PaymentRequest.PaymentSeen)
return "yellow"
if (state === PaymentRequest.DoubleSpentSeen)
return "red"
// in all other cases:
return "green"
}
// don't show the one we are editing
2021-05-05 12:42:26 +02:00
visible: modelData.saveState === PaymentRequest.Stored
Text {
anchors.centerIn: parent
text: modelData.message
}
MouseArea {
anchors.fill: parent
2021-04-21 20:12:58 +02:00
acceptedButtons: Qt.RightButton | Qt.LeftButton
onClicked: paymentContextMenu.popup()
Menu {
id: paymentContextMenu
MenuItem {
text: qsTr("Delete")
onTriggered: modelData.stored = false;
}
}
}
}
}
}
}