2e71a162aa
One surprise was that the main usecase of pasting is one where the user activates another app to go and copy data in order to come back to paste it. And the Qt clipboard didn't manage to get any notification of clipboard changes. Even copying data on becoming active had no effect. So now I just show the paste optimistically when the user comes back from another screen, assuming the main reason for that was to copy.
213 lines
7.0 KiB
QML
213 lines
7.0 KiB
QML
/*
|
|
* This file is part of the Flowee project
|
|
* Copyright (C) 2022-2023 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 "../Flowee" as Flowee
|
|
import Flowee.org.pay
|
|
|
|
FocusScope {
|
|
id: root
|
|
// if true, the bitcoin value is provided by the user (or QR), and the fiat follows.
|
|
// if false, the user edits the fiat price and the bitcoin value is calculated.
|
|
// Notice that 'send all' overrules both and gets the data from the wallet-total
|
|
property bool fiatFollowsSats: false
|
|
// made available for the NumericKeyboardWidget
|
|
property var editor: fiatFollowsSats ? priceBch.money : priceFiat.money;
|
|
/**
|
|
* Payment Backend processes the fiat and satoshi based pair of payments.
|
|
* The default is a simple backend, notice that the Payment QML type
|
|
* actually provides its own backend(s), as each output is one.
|
|
*/
|
|
property QtObject paymentBackend : PaymentBackend {}
|
|
|
|
onFiatFollowsSatsChanged: {
|
|
if (!activeFocus)
|
|
return;
|
|
takeFocus();
|
|
}
|
|
|
|
function shake() {
|
|
if (fiatFollowsSats)
|
|
bchShaker.start();
|
|
else
|
|
fiatShaker.start();
|
|
}
|
|
|
|
implicitHeight: 140
|
|
height: implicitHeight
|
|
|
|
function takeFocus() {
|
|
if (fiatFollowsSats)
|
|
priceBch.forceActiveFocus();
|
|
else
|
|
priceFiat.forceActiveFocus();
|
|
}
|
|
|
|
Flowee.BitcoinValueField {
|
|
id: priceBch
|
|
y: root.fiatFollowsSats ? 5 : 68
|
|
value: paymentBackend.paymentAmount
|
|
focus: true
|
|
fontPixelSize: size
|
|
property double size: fiatFollowsSats ? 38 : mainWindow.font.pixelSize* 0.8
|
|
onActiveFocusChanged: if (activeFocus) fiatFollowsSats = true
|
|
Behavior on size { NumberAnimation { } }
|
|
Behavior on y { NumberAnimation { } }
|
|
Flowee.ObjectShaker { id: bchShaker } // 'shake' to give feedback on mistakes
|
|
|
|
// this unchecks 'max' on user editing of the value
|
|
onValueEdited: paymentBackend.paymentAmount = value
|
|
}
|
|
MouseArea {
|
|
/* Since the valueField is centred but only allows clicking on its active surface,
|
|
we provide this one to make it possible to click on the full width and activate it.
|
|
*/
|
|
width: root.width
|
|
height: priceBch.height
|
|
y: priceBch.y
|
|
onClicked: priceBch.forceActiveFocus();
|
|
}
|
|
|
|
Flowee.FiatValueField {
|
|
id: priceFiat
|
|
value: paymentBackend.paymentAmountFiat
|
|
y: root.fiatFollowsSats ? 68 : 5
|
|
focus: true
|
|
fontPixelSize: size
|
|
property double size: !fiatFollowsSats ? 38 : mainWindow.font.pixelSize * 0.8
|
|
onActiveFocusChanged: if (activeFocus) fiatFollowsSats = false
|
|
Behavior on size { NumberAnimation { } }
|
|
Behavior on y { NumberAnimation { } }
|
|
Flowee.ObjectShaker { id: fiatShaker }
|
|
onValueEdited: paymentBackend.paymentAmountFiat = value
|
|
}
|
|
|
|
Rectangle {
|
|
id: inputChooser
|
|
y: 100
|
|
height: 40
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
border.width: 1
|
|
border.color: palette.midlight
|
|
color: palette.light
|
|
width: inputs.width + 20
|
|
radius: 15
|
|
|
|
Rectangle {
|
|
color: palette.highlight
|
|
opacity: 0.3
|
|
radius: 6
|
|
width: {
|
|
if (root.fiatFollowsSats)
|
|
return 35;
|
|
return currencyNameShort.width + 10
|
|
}
|
|
height: parent.height - 4
|
|
y: 2
|
|
x: root.fiatFollowsSats ? 5 : 45
|
|
|
|
Behavior on x { NumberAnimation { } }
|
|
Behavior on width { NumberAnimation { } }
|
|
}
|
|
|
|
Row {
|
|
id: inputs
|
|
x: 10
|
|
y: 7.5
|
|
height: parent.height
|
|
spacing: 4
|
|
Image {
|
|
id: logo
|
|
source: "qrc:/bch.svg"
|
|
width: 25
|
|
height: 25
|
|
smooth: true
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: priceBch.forceActiveFocus();
|
|
}
|
|
}
|
|
Item { width: 8; height: 1 } // spacer
|
|
|
|
Flowee.Label {
|
|
id: currencyNameShort
|
|
text: (Fiat.currencySymbolPost + Fiat.currencySymbolPrefix).trim();
|
|
width: Math.max(24, implicitWidth)
|
|
font.pixelSize: 32
|
|
anchors.baseline: logo.bottom
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: priceFiat.forceActiveFocus();
|
|
}
|
|
}
|
|
Rectangle {
|
|
width: 1
|
|
y: inputs.y * -1
|
|
height: parent.height
|
|
color: palette.dark
|
|
}
|
|
|
|
Flowee.HamburgerMenu {
|
|
y: 6
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
anchors.margins: -12
|
|
anchors.rightMargin: -25
|
|
onClicked: languageMenu.open()
|
|
}
|
|
|
|
Loader {
|
|
id: languageMenu
|
|
function open() {
|
|
sourceComponent = languageMenuComponent
|
|
}
|
|
onLoaded: item.open();
|
|
}
|
|
|
|
Component {
|
|
id: languageMenuComponent
|
|
|
|
QQC2.Menu {
|
|
Repeater {
|
|
model: Pay.recentCountries()
|
|
QQC2.MenuItem {
|
|
text: {
|
|
var loc = Qt.locale(modelData);
|
|
return loc.currencySymbol(Locale.CurrencySymbol) + " "
|
|
+ loc.currencySymbol(Locale.CurrencyDisplayName);
|
|
}
|
|
onClicked: Pay.setCountry(modelData);
|
|
}
|
|
}
|
|
QQC2.MenuItem {
|
|
text: qsTr("All Currencies")
|
|
onClicked: thePile.push("./CurrencySelector.qml")
|
|
}
|
|
|
|
onVisibleChanged: if (!visible) languageMenu.sourceComponent = undefined; // unload us
|
|
}
|
|
}
|
|
}
|
|
Item { width: 5; height: 1 } // spacer
|
|
}
|
|
}
|
|
}
|
|
|