Files
pay/modules/send-sweep/SendPage.qml
T

373 lines
13 KiB
QML
Raw Permalink Normal View History

2024-10-01 21:26:01 +02:00
/*
* This file is part of the Flowee project
* Copyright (C) 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 as QQC2
import QtQuick.Layouts
import "../Flowee" as Flowee
import "../mobile" as Mobile;
import Flowee.org.pay;
2024-10-02 23:04:38 +02:00
import Flowee.org.pay.SendSweep;
2024-10-01 21:26:01 +02:00
Mobile.Page {
id: root
headerText: qsTr("Sweep coins")
2024-10-01 21:26:01 +02:00
2024-10-02 23:04:38 +02:00
Item { // data
QRScanner {
id: scanner
scanType: QRScanner.PrivateKeyWIF
autostart: Intent.sweepKey === ""
2024-10-05 21:13:14 +02:00
helpText: qsTr("Scan QR (WIF) to find funds", "Please note that WIF and QR are names")
2024-10-02 23:04:38 +02:00
onFinished: {
var rc = scanResult
if (rc === "") { // scanning interrupted
thePile.pop();
2024-10-02 23:04:38 +02:00
return;
}
2024-10-06 00:17:04 +02:00
root.forceActiveFocus();
2024-10-02 23:04:38 +02:00
sweeper.privKey = rc;
}
onAutostartSkipped: {
/*
* This page can be opened as part of the Intent feature,
* if it has then we need to set the privatekey and at
* the same time clear out the property to prepare for
* next usage.
*/
var fromIntent = Intent.sweepKey
if (fromIntent !== "") {
Intent.sweepKey = ""; // prepare for next usage.
sweeper.privKey = fromIntent;
}
}
2024-10-02 23:04:38 +02:00
}
SweepHandler {
id: sweeper
account: pay.portfolio.current
}
2024-10-02 23:04:38 +02:00
}
2024-10-01 21:26:01 +02:00
Column {
width: parent.width
spacing: 6
Flowee.Label {
text: qsTr("Sweeping from address:")
font.bold: true
width: parent.width
horizontalAlignment: Qt.AlignHCenter
wrapMode: Text.Wrap
}
Flowee.Label {
text: sweeper.sweepAddress
width: parent.width
horizontalAlignment: Qt.AlignHCenter
fontSizeMode: Text.HorizontalFit
}
2024-10-09 16:51:37 +02:00
Flowee.Label {
id: coinsLabel
visible: sweeper.numOutputsFound > 0 || sweeper.prepared
2024-10-14 13:25:22 +02:00
text: qsTr("Found %1 coins on address.", "this is a simple number", sweeper.numOutputsFound).arg(sweeper.numOutputsFound)
2024-10-09 16:51:37 +02:00
}
Flowee.Label {
visible: sweeper.numTokensFound > 0
2024-10-14 13:25:22 +02:00
text: qsTr("Ignoring %1 tokens.", "Number of CashTokens", sweeper.numTokensFound).arg(sweeper.numTokensFound)
2024-10-09 16:51:37 +02:00
}
2024-10-06 22:36:10 +02:00
2024-10-14 19:55:53 +02:00
Flowee.Progressbar {
width: parent.width
visible: !sweeper.prepared && sweeper.error === SweepHandler.NoError
progress: sweeper.downloadProgress / 1000
}
2024-10-06 22:36:10 +02:00
Item {
id: busyIndicator
visible: !sweeper.prepared && sweeper.error === SweepHandler.NoError
width: 105
height: visible ? 105 : 1
anchors.horizontalCenter: parent.horizontalCenter
RotationAnimation on rotation {
loops: Animation.Infinite
from: 0
to: 360
duration: 6000
running: busyIndicator.visible
}
Repeater {
model: 6
Item {
width: 105
height: 35
y: 35
Rectangle {
color: mainWindow.floweeGreen
width: 30
height: 30
x: 70
radius: 15
}
rotation: 360 / 6 * index
}
}
}
Rectangle {
color: mainWindow.errorRedBg
width: parent.width
height: sweepErrorLabel.text === "" ? 0 : sweepErrorLabel.height + 20
radius: 6
Flowee.Label {
id: sweepErrorLabel
width: parent.width - 20
wrapMode: Text.Wrap
horizontalAlignment: Qt.AlignHCenter
anchors.centerIn: parent
text: {
var err = sweeper.error;
if (err === SweepHandler.InvalidInput)
return qsTr("Failed to understand QR");
if (err === SweepHandler.NoBackendFound)
return "No indexing servers found";
if (err === SweepHandler.FileError)
return "File not found error"; // not translated as this should never happen.
if (err === SweepHandler.DataInconsistency)
return qsTr("Indexer results invalid. Please try again.");
if (err === SweepHandler.NoError)
return "";
}
}
}
Flowee.BitcoinAmountLabel {
font.pixelSize: coinsLabel.font.pixelSize * 1.2
visible: sweeper.prepared
value: sweeper.sweepTotal
anchors.right: parent.right
}
2024-10-06 00:17:04 +02:00
}
Mobile.AccountSelectorWidget {
id: walletSelector
visible: !portfolio.singleAccountSetup
2024-10-14 19:55:53 +02:00
y: 320
onSelectedAccountChanged: sweeper.account = selectedAccount
}
Flowee.Label {
visible: walletSelector.visible
anchors.bottom: walletSelector.top
text: qsTr("Transfer to:")
}
2024-10-06 00:17:04 +02:00
Mobile.SlideToApprove {
id: slideToApprove
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
width: parent.width
2024-10-09 16:51:37 +02:00
enabled: sweeper.prepared && sweeper.numOutputsFound > 0
2024-10-06 00:17:04 +02:00
visible: !sweeper.account.needsPinToOpen
onActivated: {
2024-10-06 22:36:10 +02:00
root.hideHeader = true;
background.y = 0;
background.opacity = 1;
sweeper.markUserApproved();
2024-10-06 00:17:04 +02:00
}
}
QQC2.Control {
id: broadcastFeedback
anchors.leftMargin: -10 // go against the margins Page gave us to show more fullscreen.
anchors.rightMargin: -10
anchors.fill: parent
font.pixelSize: root.font.pixelSize * 1.2
property int status: sweeper.broadcastStatus
property double bitcoinAmount: sweeper.sweepTotal
property int fiatAmount: bitcoinAmount / 100000000 * Fiat.price
property string targetAddress: sweeper.targetAddress
states: [
State {
name: "notStarted"
when: broadcastFeedback.status === FloweePay.NotStarted
},
State {
name: "preparing"
when: broadcastFeedback.status === FloweePay.TxOffered
PropertyChanges { target: progressIcon; sweepAngle: 90 }
},
State {
name: "sent1" // sent to only one peer
extend: "preparing"
when: broadcastFeedback.status === FloweePay.TxSent1
PropertyChanges { target: progressIcon; sweepAngle: 150 }
PropertyChanges { target: statusLabel; text: qsTr("Sending Payment") }
},
State {
name: "waiting" // waiting for possible rejection.
when: broadcastFeedback.status === FloweePay.TxWaiting
extend: "preparing"
PropertyChanges { target: progressIcon; sweepAngle: 320 }
},
State {
name: "success" // no reject, great success
when: broadcastFeedback.status === FloweePay.TxBroadcastSuccess
extend: "preparing"
PropertyChanges { target: progressIcon
sweepAngle: 320
startAngle: -20
}
PropertyChanges { target: progressIcon; showCheck: true }
PropertyChanges { target: statusLabel; text: qsTr("Payment Sent") }
},
State {
name: "rejected" // a peer didn't like our tx
when: broadcastFeedback.status === FloweePay.TxRejected
extend: "preparing"
PropertyChanges { target: background; color: "#7f0000" }
PropertyChanges { target: progressIcon; opacity: 0 }
PropertyChanges { target: statusLabel; text: qsTr("Failed") }
PropertyChanges { target: errorLabel; text: qsTr("Transaction rejected by network") }
}
]
Rectangle {
id: background
width: parent.width
height: parent.height
opacity: 0
visible: opacity > 0
color: "#7bb688"
y: height + 2
MouseArea {
anchors.fill: parent // eat all mouse events.
}
Flowee.Label {
id: statusLabel
anchors.horizontalCenter: parent.horizontalCenter
font.bold: true
y: 30
color: "#e8e8e8"
}
Flowee.ProgressCheckIcon {
id: progressIcon
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: statusLabel.bottom
anchors.topMargin: 20
}
Column {
width: parent.width
anchors.top: progressIcon.bottom
anchors.topMargin: 6
spacing: 6
Rectangle {
id: errorTextPane
visible: errorLabel.text !== ""
color: mainWindow.errorRedBg
radius: 10
width: parent.width
height: errorLabel.height + 20
Flowee.Label {
id: errorLabel
wrapMode: Text.Wrap
x: 10
y: 10
width: parent.width - 20
horizontalAlignment: Qt.AlignHCenter
}
}
Flowee.Label {
id: fiatLabel
anchors.horizontalCenter: parent.horizontalCenter
color: statusLabel.color
font.pixelSize: statusLabel.font.pixelSize * 2.5
text: Fiat.formattedPrice(broadcastFeedback.fiatAmount)
visible: Fiat.price !== 0
}
Flowee.BitcoinAmountLabel {
id: cryptoAmount
anchors.horizontalCenter: parent.horizontalCenter
value: broadcastFeedback.bitcoinAmount
colorize: false
showFiat: false
color: statusLabel.color
}
Item { width: 10; height: 10 } // spacer
Flowee.Label {
id: addressLabel
color: statusLabel.color
visible: broadcastFeedback.targetAddress !== ""
width: parent.width - 20
x: 10
horizontalAlignment: Qt.AlignHCenter
wrapMode: Text.Wrap
2024-10-06 22:36:10 +02:00
text: qsTr("The payment has been sent to:", "Followed by the address")
}
Flowee.Label {
color: statusLabel.color
visible: broadcastFeedback.targetAddress !== ""
width: parent.width - 20
x: 10
horizontalAlignment: Qt.AlignHCenter
text: broadcastFeedback.targetAddress
fontSizeMode: Text.HorizontalFit
2024-10-06 00:17:04 +02:00
}
}
Rectangle {
id: closeButtonBg
color: statusLabel.color
radius: 10
width: parent.width - 20
x: 10
height: closeButtonLabel.height + 25
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
Flowee.Label {
id: closeButtonLabel
text: qsTr("Close")
anchors.centerIn: parent
color: background.color
}
MouseArea {
anchors.fill: parent
anchors.margins: -10
focus: true
onClicked: {
var mainView = thePile.get(0);
mainView.currentIndex = 0; // go to the 'main' tab.
thePile.pop();
}
}
}
Behavior on opacity { NumberAnimation { } }
Behavior on y { NumberAnimation { } }
Behavior on color { ColorAnimation { } }
}
}
2024-10-01 21:26:01 +02:00
}