Files
pay/guis/desktop/main.qml
T

864 lines
35 KiB
QML
Raw Permalink Normal View History

2020-05-24 13:20:03 +02:00
/*
* This file is part of the Flowee project
2025-01-27 18:03:14 +01:00
* Copyright (C) 2020-2025 Tom Zander <tom@flowee.org>
2020-05-24 13:20:03 +02:00
*
* 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/>.
*/
2022-11-14 21:19:31 +01:00
import QtQuick
2025-06-18 17:48:29 +02:00
import QtQuick.Controls.Basic as QQC2
import QtQuick.Templates as T
2022-11-26 10:46:57 +01:00
import QtQuick.Layouts
2022-11-14 21:19:31 +01:00
import "../Flowee" as Flowee
import "../ControlColors.js" as ControlColors
2020-10-14 15:12:33 +02:00
2025-06-18 17:48:29 +02:00
QQC2.ApplicationWindow {
2020-10-14 18:29:10 +02:00
id: mainWindow
2020-05-24 13:20:03 +02:00
visible: true
2024-09-07 19:50:30 +02:00
width: Pay.windowWidth
height: Pay.windowHeight
2022-08-28 22:21:14 +02:00
minimumWidth: 400
minimumHeight: 300
2020-05-24 13:20:03 +02:00
title: "Flowee Pay"
2021-11-02 19:29:14 +01:00
onWidthChanged: Pay.windowWidth = width
onHeightChanged: Pay.windowHeight = height
2020-10-14 18:29:10 +02:00
onVisibleChanged: if (visible) ControlColors.applySkin(mainWindow)
2025-02-05 20:52:38 +01:00
property bool isLoading: typeof net === "undefined";
2020-06-11 17:56:06 +02:00
2024-02-12 19:19:01 +01:00
Component.onCompleted: updateFontSize(mainWindow);
function updateFontSize(window) {
// 75% = > 14.25, 100% => 19, 200% => 28
window.font.pixelSize = 17 + (11 * (Pay.fontScaling-100) / 100)
}
Connections {
target: Pay
function onFontScalingChanged() {
updateFontSize(mainWindow);
2024-05-28 22:38:53 +02:00
if (txDetailsWindow.status === Loader.Ready)
2024-02-12 19:19:01 +01:00
updateFontSize(txDetailsWindow.item);
2024-05-28 22:38:53 +02:00
if (netView.status === Loader.Ready)
2024-02-12 19:19:01 +01:00
updateFontSize(netView.item);
}
function onUseDarkSkinChanged() {
ControlColors.applySkin(mainWindow);
2024-05-28 22:38:53 +02:00
if (txDetailsWindow.status === Loader.Ready)
2024-02-12 19:19:01 +01:00
ControlColors.applySkin(txDetailsWindow.item);
2024-05-28 22:38:53 +02:00
if (netView.status === Loader.Ready)
2024-02-12 19:19:01 +01:00
ControlColors.applySkin(netView.item);
}
}
2021-04-20 19:30:56 +02:00
onIsLoadingChanged: {
if (!isLoading) {
// delay loading to avoid errors due to not having a portfolio
// portfolio is only initialized after a second or so.
receivePane.source = "./ReceiveTransactionPane.qml"
sendTransactionPane.source = "./SendTransactionPane.qml"
if (Intent.paymentUrl !== "") {
// respond to payment intent is prio one.
2023-08-30 22:42:08 +02:00
tabbar.currentIndex = 1;
}
else if (!portfolio.current.isUserOwned) {
// Open on receive tab if the wallet is effectively empty
tabbar.currentIndex = 2;
}
2021-04-20 19:30:56 +02:00
else {
tabbar.currentIndex = 0;
}
}
}
2021-04-19 22:36:02 +02:00
property color floweeSalmon: "#ff9d94"
property color floweeBlue: "#0b1088"
property color floweeGreen: "#90e4b5"
2023-04-18 21:54:43 +02:00
property color errorRed: Pay.useDarkSkin ? "#ff6568" : "#940000"
property color errorRedBg: Pay.useDarkSkin ? "#671314" : "#9f1d1f"
2021-04-19 22:36:02 +02:00
2021-07-30 21:54:26 +02:00
Item {
2021-04-19 22:36:02 +02:00
id: mainScreen
anchors.fill: parent
2021-04-20 19:30:56 +02:00
focus: true
2021-04-19 22:36:02 +02:00
2024-02-04 21:30:34 +01:00
Loader {
id: effects
source: "./BlurComponents.qml"
}
2021-07-30 21:47:15 +02:00
Rectangle {
id: header
2021-11-02 19:29:14 +01:00
color: Pay.useDarkSkin ? "#00000000" : mainWindow.floweeBlue
2021-07-30 21:47:15 +02:00
width: parent.width
2022-09-07 20:32:05 +02:00
height: 90
2021-07-30 21:47:15 +02:00
Rectangle {
color: mainWindow.floweeBlue
2021-11-02 19:29:14 +01:00
opacity: Pay.useDarkSkin ? 1 : 0
2021-07-30 21:47:15 +02:00
2022-09-07 20:32:05 +02:00
width: 60
height: 60
radius: 30
x: 3
y: 11
2021-07-30 21:47:15 +02:00
Behavior on opacity { NumberAnimation { duration: 300 } }
}
Image {
2021-10-25 15:54:41 +02:00
id: appLogo
2021-07-30 21:47:15 +02:00
anchors.verticalCenter: parent.verticalCenter
2022-09-07 20:32:05 +02:00
x: 17
2021-07-30 21:47:15 +02:00
smooth: true
2021-11-21 10:59:29 +01:00
source: "qrc:/FloweePay-light.svg"
2021-07-30 21:47:15 +02:00
// ratio: 77 / 449
2022-09-07 20:32:05 +02:00
height: 40
2021-07-30 21:47:15 +02:00
width: height * 449 / 77
}
2021-10-25 15:54:41 +02:00
Item {
id: balanceInHeader
visible: {
if (mainWindow.isLoading)
return false;
if (portfolio.accounts.length <= 1)
return false;
// If there is not enough space here (only for quite long balances), move to the left bar
var minX = appLogo.width + totalFiatLabel.width + 50 // 50 is spacing
return x > minX;
}
2022-09-07 20:32:05 +02:00
width: totalBalance.width
height: totalBalance.height
2021-10-25 15:54:41 +02:00
anchors.bottom: parent.bottom
anchors.bottomMargin: tabbar.headerHeight + 5
anchors.right: parent.right
anchors.rightMargin: 10
2022-09-07 20:32:05 +02:00
baselineOffset: totalBalance.baselineOffset
2021-10-25 15:54:41 +02:00
Flowee.BitcoinAmountLabel {
2022-09-07 20:32:05 +02:00
id: totalBalance
2021-10-25 15:54:41 +02:00
value: {
if (isLoading)
return 0;
2021-11-02 19:29:14 +01:00
if (Pay.hideBalance)
2021-10-25 15:54:41 +02:00
return 88888888;
return portfolio.totalBalance
}
colorize: false
2021-10-30 19:23:43 +02:00
color: "white"
2021-10-25 15:54:41 +02:00
showFiat: false
2022-09-08 17:34:36 +02:00
fontPixelSize: 28
2024-02-04 21:30:34 +01:00
layer.enabled: effects.loaded && Pay.hideBalance
layer.effect: effects.item.biggerBlur
2021-10-25 15:54:41 +02:00
}
}
2024-05-07 15:40:36 +02:00
Flowee.Label {
2021-10-25 15:54:41 +02:00
id: totalFiatLabel
anchors.baseline: balanceInHeader.baseline
anchors.right: balanceInHeader.left
anchors.rightMargin: 10
2021-10-29 18:20:42 +02:00
color: "white"
2022-09-08 17:34:36 +02:00
font.pixelSize: 15
2021-10-25 15:54:41 +02:00
text: {
2021-11-02 19:29:14 +01:00
if (Pay.hideBalance && Pay.isMainChain)
2024-01-05 18:19:06 +01:00
return Fiat.formattedPrice(100000000, Fiat.price)
2025-04-17 18:08:21 +02:00
if (!Fiat.hasPrice && Pay.isMainChain)
return "?"
2021-10-25 15:54:41 +02:00
return Fiat.formattedPrice(totalBalance.value, Fiat.price)
}
visible: balanceInHeader.visible
opacity: 0.6
2024-02-04 21:30:34 +01:00
layer.enabled: effects.loaded && Pay.hideBalance
layer.effect: effects.item.simpleBlur
2021-10-25 15:54:41 +02:00
}
2021-07-30 21:47:15 +02:00
}
2021-04-19 22:36:02 +02:00
Item {
id: tabbedPane
2022-08-28 22:21:14 +02:00
width: Math.max(parent.width - 270, parent.width * 65 / 100)
2021-04-19 22:36:02 +02:00
anchors.right: parent.right
2021-07-30 21:47:15 +02:00
anchors.top: header.bottom
anchors.topMargin: -1 * tabbar.headerHeight
anchors.bottom: parent.bottom
2021-04-19 22:36:02 +02:00
Rectangle {
anchors.fill: parent
opacity: 0.2
2021-07-30 21:54:26 +02:00
anchors.topMargin: -5
anchors.leftMargin: -5
2021-04-20 17:41:35 +02:00
radius: 5
2021-11-02 19:29:14 +01:00
color: Pay.useDarkSkin ? "black" : "white"
2021-04-19 22:36:02 +02:00
}
2025-01-27 13:34:42 +01:00
TabBarWidget {
2021-04-20 17:41:35 +02:00
id: tabbar
2021-04-21 16:57:14 +02:00
anchors.fill: parent
2021-04-20 17:41:35 +02:00
2025-06-18 17:48:29 +02:00
QQC2.Pane {
2024-05-28 23:39:08 +02:00
id: activityTab
2021-04-21 16:57:14 +02:00
property string title: qsTr("Activity")
2021-11-02 19:38:36 +01:00
property string icon: "qrc:/activityIcon-light.png"
2021-04-21 16:57:14 +02:00
anchors.fill: parent
2021-11-02 19:13:14 +01:00
Rectangle {
anchors.fill: parent
anchors.margins: -10
2023-02-21 16:40:46 +01:00
color: palette.light
2021-11-02 19:13:14 +01:00
radius: 10
}
2022-04-05 17:39:19 +02:00
Column {
id: activityHeader
width: parent.width
2022-08-28 22:21:14 +02:00
spacing: 6
2025-01-27 18:03:14 +01:00
Item {
width: parent.width
height: 40
Loader {
source: isLoading ? "" : "./ActivityConfigBar.qml"
width: parent.width
y: -13
}
}
2022-04-05 17:39:19 +02:00
Rectangle {
width: parent.width
2025-01-27 18:03:14 +01:00
height: visible ? (warn.height + unarchiveButton.height + 26) : 0
2023-02-14 14:56:18 +01:00
color: Pay.useDarkSkin ? "#c1ba58" : "#f6e992" // yellow
2022-04-05 17:39:19 +02:00
visible: !isLoading && portfolio.current.isArchived
2022-08-28 22:21:14 +02:00
radius: 7
2023-02-14 14:56:18 +01:00
Flowee.Label {
2022-04-05 17:39:19 +02:00
id: warn
2022-08-28 22:21:14 +02:00
y: 6
x: 6
width: parent.width - 10
2022-04-05 17:39:19 +02:00
horizontalAlignment: Text.AlignHCenter
color: "black"
font.bold: true
wrapMode: Text.WordWrap
text: qsTr("Archived wallets do not check for activities. Balance may be out of date.")
}
Flowee.Button {
2022-04-05 17:39:19 +02:00
id: unarchiveButton
text: qsTr("Unarchive")
anchors.right: warn.right
anchors.top: warn.bottom
anchors.topMargin: 6
onClicked: portfolio.current.isArchived = false
}
}
Rectangle {
id: needsDecryptPane
width: parent.width
2025-01-27 18:03:14 +01:00
height: visible ? (decryptText.height + decryptPwd.height + decryptButton.height + 36): 0
2023-02-14 14:56:18 +01:00
color: Pay.useDarkSkin ? "#c1ba58" : "#f6e992" // yellow
visible: !isLoading && portfolio.current.needsPinToOpen
&& !portfolio.current.isDecrypted
2022-08-28 22:21:14 +02:00
radius: 7
onVisibleChanged: {
decryptError.visible = false
decryptPwd.text = ""
}
Text {
id: decryptText
2022-08-28 22:21:14 +02:00
y: 6
x: 6
width: parent.width - 20
horizontalAlignment: Text.AlignHCenter
color: "black"
2024-05-28 23:39:08 +02:00
font.pixelSize: activityTab.font.pixelSize
font.bold: true
wrapMode: Text.WordWrap
text: qsTr("This wallet needs a password to open.")
}
Text {
id: decryptLabel
anchors.left: decryptText.left
anchors.verticalCenter: decryptPwd.verticalCenter
color: decryptText.color
2024-05-28 23:39:08 +02:00
font: activityTab.font
text: qsTr("Password:")
}
Flowee.TextField {
id: decryptPwd
2022-07-21 11:40:33 +02:00
focus: needsDecryptPane.visible
anchors.top: decryptText.bottom
anchors.left: decryptLabel.right
anchors.right: parent.right
anchors.margins: 6
echoMode: TextInput.Password
onAccepted: decryptButton.clicked()
}
Text {
id: decryptError
anchors.left: decryptPwd.left
anchors.verticalCenter: decryptButton.verticalCenter
color: "#830000"
2024-05-28 23:39:08 +02:00
font.pixelSize: activityTab.font.pixelSize
font.bold: true
text: qsTr("Invalid password")
visible: false
}
Flowee.Button {
id: decryptButton
text: qsTr("Open")
anchors.right: decryptText.right
anchors.top: decryptPwd.bottom
anchors.topMargin: 6
enabled: decryptPwd.text !== ""
onClicked: {
portfolio.current.decrypt(decryptPwd.text)
if (portfolio.current.isDecrypted) {
decryptPwd.text = ""
decryptError.visible = false
} else {
decryptPwd.selectAll();
decryptError.visible = true
decryptPwd.forceActiveFocus();
}
}
}
}
2022-04-05 17:39:19 +02:00
}
2021-04-21 00:11:57 +02:00
ListView {
id: activityView
2022-08-28 22:21:14 +02:00
model: isLoading ? 0 : portfolio.current.transactions
2021-04-21 00:11:57 +02:00
clip: true
2025-01-27 18:03:14 +01:00
delegate: Transaction {
width: activityView.width
color: (index % 2) == 0 ? palette.light : palette.alternateBase
}
2022-04-05 17:39:19 +02:00
anchors.top: activityHeader.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
2025-06-18 17:48:29 +02:00
QQC2.ScrollBar.vertical: Flowee.ScrollThumb {
2021-11-03 11:59:58 +01:00
id: thumb
minimumSize: 20 / activityView.height
visible: size < 0.9
2021-11-03 11:59:58 +01:00
preview: Rectangle {
2022-08-28 22:21:14 +02:00
width: label.width + 12
height: label.height + 12
2021-11-03 11:59:58 +01:00
radius: 5
2023-02-21 16:40:46 +01:00
color: palette.light
2025-06-18 17:48:29 +02:00
Flowee.Label {
2021-11-03 11:59:58 +01:00
id: label
anchors.centerIn: parent
2023-02-14 14:56:18 +01:00
color: palette.dark
text: isLoading || activityView.model === null ? "" : activityView.model.dateForItem(thumb.position);
2021-11-03 11:59:58 +01:00
}
}
2021-10-30 18:57:40 +02:00
}
2021-11-01 16:30:00 +01:00
onModelChanged: resetUnreadTimer.restart();
Timer {
id: resetUnreadTimer
2021-11-09 20:49:37 +01:00
interval: 90 * 1000
2021-11-01 16:30:00 +01:00
// remove the 'new transaction' indicator.
onTriggered: portfolio.current.transactions.lastSyncIndicator = undefined
running: activityView.enabled && activityView.visible
// copy the height so we know when the account height changes
// and we can restart our timer as a result
2022-04-06 18:18:49 +02:00
property int height: {
if (isLoading) return 0;
return portfolio.current.lastBlockSynched
}
2021-11-01 16:30:00 +01:00
onHeightChanged: restart();
}
2021-04-21 00:11:57 +02:00
}
2021-11-25 17:35:41 +01:00
Keys.forwardTo: Flowee.ListViewKeyHandler {
target: activityView
}
2021-04-20 17:41:35 +02:00
}
2021-04-26 19:50:45 +02:00
Loader {
id: sendTransactionPane
// Disable these tabs for archived accounts
enabled: !mainWindow.isLoading && !portfolio.current.isArchived
2022-06-29 14:23:54 +02:00
&& (!portfolio.current.needsPinToOpen || portfolio.current.isDecrypted)
2021-04-21 16:57:14 +02:00
anchors.fill: parent
property string title: qsTr("Send")
2021-11-02 19:38:36 +01:00
property string icon: "qrc:/sendIcon-light.png"
2021-04-21 16:57:14 +02:00
}
Loader {
id: receivePane
2022-07-06 22:06:58 +02:00
enabled: sendTransactionPane.enabled && (!portfolio.current.needSpinToOpen || portfolio.current.isDecrypted)
2021-04-21 16:57:14 +02:00
anchors.fill: parent
2021-11-02 19:38:36 +01:00
property string icon: "qrc:/receiveIcon.png"
2021-04-21 16:57:14 +02:00
property string title: qsTr("Receive")
}
2021-08-09 18:46:38 +02:00
SettingsPane {
2021-04-21 16:57:14 +02:00
anchors.fill: parent
2021-04-19 22:36:02 +02:00
}
}
Behavior on opacity { NumberAnimation { } }
visible: opacity > 0
}
Loader {
2022-04-05 16:37:09 +02:00
// This overlays the tabbed pane
id: accountOverlay
anchors.bottom: parent.bottom
anchors.left: overviewPane.right
anchors.right: parent.right
2021-07-31 14:16:28 +02:00
anchors.top: header.bottom
anchors.topMargin: -1 * tabbar.headerHeight
opacity: 0
Behavior on opacity { NumberAnimation { } }
states: [
State {
name: "showTransactions"
PropertyChanges { target: tabbedPane; opacity: 1 }
2021-11-30 22:19:40 +01:00
PropertyChanges { target: tabbar; focus: true }
PropertyChanges { target: accountOverlay;
2021-11-30 22:19:40 +01:00
opacity: 0;
source: "";
}
},
State {
name: "accountDetails"
PropertyChanges { target: accountOverlay;
2021-11-30 22:19:40 +01:00
source: "./AccountDetails.qml"
opacity: 1
focus: true
}
PropertyChanges { target: tabbedPane; opacity: 0 }
},
State {
name: "startWalletEncryption"
PropertyChanges { target: accountOverlay;
source: "./WalletEncryption.qml"
opacity: 1
focus: true
}
PropertyChanges { target: tabbedPane; opacity: 0 }
}
]
state: "showTransactions"
2021-04-19 22:36:02 +02:00
}
2022-08-14 00:05:40 +02:00
Item {
2022-04-05 16:37:09 +02:00
// the whole area left of the tabbed panels.
2021-04-20 15:52:11 +02:00
id: overviewPane
2021-07-30 21:47:15 +02:00
anchors.left: parent.left
2022-08-28 22:21:14 +02:00
anchors.leftMargin: 6
2021-07-30 21:47:15 +02:00
anchors.right: tabbedPane.left
2022-08-28 22:21:14 +02:00
anchors.rightMargin: 12
2021-07-30 21:47:15 +02:00
anchors.bottom: parent.bottom
2022-08-28 22:21:14 +02:00
anchors.bottomMargin: 6
2021-07-30 21:47:15 +02:00
anchors.top: header.bottom
2021-04-20 15:52:11 +02:00
Column {
2022-08-14 00:05:40 +02:00
id: balances
2022-08-28 22:21:14 +02:00
spacing: 3
width: parent.width
2021-04-20 15:52:11 +02:00
2021-05-01 16:21:58 +02:00
Item {
height: balanceLabel.height
width: parent.width
2025-06-18 17:48:29 +02:00
Flowee.Label {
2021-05-01 16:21:58 +02:00
id: balanceLabel
text: qsTr("Balance");
height: implicitHeight / 10 * 7
2021-04-19 22:36:02 +02:00
}
2021-05-01 16:21:58 +02:00
Image {
2021-10-25 16:23:32 +02:00
id: showBalanceButton
2021-05-01 16:21:58 +02:00
anchors.right: parent.right
source: {
2021-11-21 11:27:26 +01:00
var state = Pay.hideBalance ? "closed" : "open";
var skin = Pay.useDarkSkin ? "-light" : ""
return "qrc:/eye-" + state + skin + ".png";
2021-05-01 16:21:58 +02:00
}
smooth: true
opacity: 0.5
2022-08-28 22:21:14 +02:00
height: 14
width: 14
2021-05-01 16:21:58 +02:00
MouseArea {
anchors.fill: parent
2021-10-30 16:29:48 +02:00
cursorShape: Qt.PointingHandCursor
onClicked: {
2021-11-02 19:29:14 +01:00
Pay.hideBalance = !Pay.hideBalance;
balanceDetailsPane.showDetails = false;
}
2021-05-01 16:21:58 +02:00
}
2021-04-29 15:29:28 +02:00
}
2021-04-20 15:52:11 +02:00
}
2021-05-01 16:21:58 +02:00
Item {
id: balanceDetailsPane
2021-08-09 18:21:51 +02:00
property bool showDetails: false
2022-08-28 22:21:14 +02:00
width: parent.width
2024-01-05 18:19:06 +01:00
clip: !Pay.hideBalance // on to avoid the balance overlapping the tabbar.
2022-08-28 22:21:14 +02:00
height: balance.height + (showDetails ? extraBalances.height + 10 : 0)
Flowee.BitcoinAmountLabel {
2021-05-01 16:21:58 +02:00
id: balance
value: {
if (isLoading)
return 0;
var account = portfolio.current;
if (account === null)
return 0;
2021-11-02 19:29:14 +01:00
if (Pay.hideBalance)
2021-05-01 16:21:58 +02:00
return 88888888;
return account.balanceConfirmed + account.balanceUnconfirmed
}
colorize: false
2021-05-08 00:03:07 +02:00
showFiat: false
2023-02-21 16:40:46 +01:00
color: palette.windowText
2022-09-08 17:34:36 +02:00
fontPixelSize: {
if (leftColumn.width < 240) // max width is 252
2023-03-21 21:27:08 +01:00
return leftColumn.width / 9
return 27;
2021-05-01 16:21:58 +02:00
}
2024-02-04 21:30:34 +01:00
layer.enabled: effects.loaded && Pay.hideBalance
layer.effect: effects.item.biggerBlur
2021-05-01 16:21:58 +02:00
}
2022-08-20 18:23:51 +02:00
2021-10-14 16:10:31 +02:00
GridLayout {
2021-08-09 18:21:51 +02:00
id: extraBalances
visible: parent.showDetails
2022-08-28 22:21:14 +02:00
width: parent.width / 0.9
2021-08-09 18:21:51 +02:00
anchors.top: balance.bottom
2022-08-28 22:21:14 +02:00
anchors.topMargin: 5
2021-08-09 18:21:51 +02:00
columns: 2
2022-08-28 22:21:14 +02:00
scale: 0.9
transformOrigin: Item.TopLeft
clip: true
2021-08-09 18:21:51 +02:00
property QtObject account: mainWindow.isLoading ? null : portfolio.current
2025-06-18 17:48:29 +02:00
Flowee.Label {
2021-11-09 21:34:40 +01:00
text: qsTr("Main", "balance (money), non specified") + ":"
2021-10-14 16:10:31 +02:00
Layout.alignment: Qt.AlignRight
}
Flowee.BitcoinAmountLabel {
2021-10-14 16:10:31 +02:00
value: extraBalances.account == null ? 0 : extraBalances.account.balanceConfirmed
colorize: false
showFiat: false
2022-08-28 22:21:14 +02:00
Layout.fillWidth: true
2021-10-14 16:10:31 +02:00
}
2025-06-18 17:48:29 +02:00
Flowee.Label {
2021-11-09 21:34:40 +01:00
text: qsTr("Unconfirmed", "balance (money)") + ":"
2021-10-14 16:10:31 +02:00
Layout.alignment: Qt.AlignRight
2021-08-09 18:21:51 +02:00
}
Flowee.BitcoinAmountLabel {
2021-08-09 18:21:51 +02:00
value: extraBalances.account == null ? 0 : extraBalances.account.balanceUnconfirmed
colorize: false
showFiat: false
}
2025-06-18 17:48:29 +02:00
Flowee.Label {
2021-11-09 21:34:40 +01:00
text: qsTr("Immature", "balance (money)") + ":"
2021-10-14 16:10:31 +02:00
Layout.alignment: Qt.AlignRight
2021-08-09 18:21:51 +02:00
}
Flowee.BitcoinAmountLabel {
2021-08-09 18:21:51 +02:00
value: extraBalances.account == null ? 0 : extraBalances.account.balanceImmature
colorize: false
showFiat: false
}
}
MouseArea {
2022-06-29 14:23:54 +02:00
enabled: priceCover.visible === false
2021-08-09 18:21:51 +02:00
anchors.fill: parent
2021-12-01 18:15:54 +01:00
cursorShape: Qt.PointingHandCursor
onClicked: {
2021-11-02 19:29:14 +01:00
if (!Pay.hideBalance)
parent.showDetails = !parent.showDetails
}
2021-08-09 18:21:51 +02:00
}
2022-06-29 14:23:54 +02:00
Rectangle {
id: priceCover // this covers the prices while the wallet is encrypted.
2023-02-21 16:40:46 +01:00
color: palette.window
2022-06-29 14:23:54 +02:00
opacity: 0.8
anchors.fill: parent
2022-08-20 18:23:51 +02:00
anchors.topMargin: 2
2022-06-29 14:23:54 +02:00
visible: !mainWindow.isLoading && portfolio.current.needsPinToOpen && !portfolio.current.isDecrypted
}
2021-08-09 18:21:51 +02:00
Behavior on height { NumberAnimation {} }
2021-05-01 16:21:58 +02:00
}
2025-06-18 17:48:29 +02:00
Flowee.Label {
2021-05-01 17:22:19 +02:00
text: {
2022-09-08 17:34:36 +02:00
if (mainWindow.isLoading || !Pay.isMainChain)
2022-06-29 14:23:54 +02:00
return "";
2022-09-08 17:34:36 +02:00
if (Pay.hideBalance || (portfolio.current.needsPinToOpen && !portfolio.current.isDecrypted))
2022-06-29 14:23:54 +02:00
return "-- " + Fiat.currencyName;
return Fiat.formattedPrice(balance.value, Fiat.price);
2021-05-01 17:22:19 +02:00
}
opacity: 0.6
2024-02-04 21:30:34 +01:00
layer.enabled: effects.loaded && Pay.hideBalance
layer.effect: effects.item.simpleBlur
2021-04-20 15:52:11 +02:00
}
2022-09-07 20:32:05 +02:00
Item { width: 1; height: fiatValue.visible ? 10 : 0 } // spacer
Item {
width: parent.width
height: fiatValue.height
2025-06-18 17:48:29 +02:00
Flowee.Label {
id: fiatValue
property double prevPrice: 0
text: {
if (Fiat.hasPrice)
var price = Fiat.formattedPrice(100000000, Fiat.price);
else
price = "?";
qsTr("1 BCH is: %1").arg(price);
}
visible: Pay.isMainChain
2021-12-01 18:01:25 +01:00
Behavior on color { ColorAnimation { duration: 300 } }
onTextChanged: {
animTimer.start()
if (prevPrice > Fiat.price)
color = Pay.useDarkSkin ? "#5f1414" : "#ff3636"; // red
else
color = Pay.useDarkSkin ? "#154822" : "#4aff77"; // green
prevPrice = Fiat.price
}
Timer {
id: animTimer
interval: 305
2023-02-21 16:40:46 +01:00
onTriggered: fiatValue.color = palette.windowText
}
2021-12-01 18:01:25 +01:00
}
AccountConfigMenu {
anchors.right: parent.right
2022-09-07 20:32:05 +02:00
visible: isLoading ? false : portfolio.singleAccountSetup
account: isLoading ? null : portfolio.current
2021-12-01 18:01:25 +01:00
}
2021-06-07 23:30:21 +02:00
}
2022-08-14 00:05:40 +02:00
}
2021-04-20 15:52:11 +02:00
2022-08-14 00:05:40 +02:00
Flickable {
anchors {
left: balances.left
right: balances.right
top: balances.bottom
2022-08-28 22:21:14 +02:00
topMargin: 8
2022-08-14 00:05:40 +02:00
bottom: parent.bottom
2022-08-28 22:21:14 +02:00
bottomMargin: 8
2022-08-14 00:05:40 +02:00
}
contentWidth: leftColumn.width
contentHeight: leftColumn.height
flickableDirection: Flickable.VerticalFlick
clip: true
2021-04-29 12:12:12 +02:00
2022-08-14 00:05:40 +02:00
Column {
id: leftColumn
width: balances.width
2025-06-18 17:48:29 +02:00
Flowee.Label {
id: netStatus
2022-08-14 00:05:40 +02:00
text: qsTr("Network status")
opacity: 0.6
visible: isLoading || !portfolio.current.uptodate
2022-04-05 17:51:08 +02:00
}
2025-06-18 17:48:29 +02:00
Flowee.Label {
visible: netStatus.visible
2022-08-14 00:05:40 +02:00
id: syncIndicator
text: {
if (isLoading)
2022-08-14 00:05:40 +02:00
return "";
var account = portfolio.current;
if (account === null)
return "";
if (account.needsPinToOpen && !account.isDecrypted)
return qsTr("Offline");
return account.timeBehind;
}
font.italic: true
}
Item { // spacer
2022-08-28 22:21:14 +02:00
width: 1
height: 20
visible: netStatus.visible
2022-08-14 00:05:40 +02:00
}
Repeater { // the portfolio listing our accounts
width: parent.width
model: mainWindow.isLoading ? 0 : portfolio.accounts;
delegate: AccountListItem {
width: leftColumn.width
account: modelData
}
}
Item { // spacer
2022-08-28 22:21:14 +02:00
width: 1
height: 20
2022-08-14 00:05:40 +02:00
}
2024-05-03 12:11:45 +02:00
Flowee.BigButton { // button 'add bitcoin cash wallet'
text: qsTr("Add Bitcoin Cash wallet")
onClicked: newAccountPane.source = "./NewAccountPane.qml"
isMainButton: true
2022-08-14 00:05:40 +02:00
width: leftColumn.width
}
2024-05-03 12:11:45 +02:00
2022-08-14 00:05:40 +02:00
Item { // spacer
2022-08-28 22:21:14 +02:00
width: 1
height: 20
2022-08-14 00:05:40 +02:00
}
Item {
// archived wallets label with hide button
visible: !isLoading && portfolio.archivedAccounts.length > 0
height: archivedLabel.height
width: leftColumn.width
Flowee.ArrowPoint {
id: showArchivedWalletsList
property bool on: false
color: Pay.useDarkSkin ? "white" : "black"
rotation: on ? 90 : 0
transformOrigin: Item.Center
Behavior on rotation { NumberAnimation {} }
}
2025-06-18 17:48:29 +02:00
Flowee.Label {
2022-08-14 00:05:40 +02:00
id: archivedLabel
2022-08-28 22:21:14 +02:00
x: showArchivedWalletsList.width + 6
2022-08-14 00:05:40 +02:00
text: {
if (isLoading)
return ""
var walletCount = portfolio.archivedAccounts.length
return qsTr("Archived wallets [%1]", "Arg is wallet count", walletCount).arg(walletCount);
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: showArchivedWalletsList.on = !showArchivedWalletsList.on
}
2022-04-05 17:51:08 +02:00
}
2022-08-14 00:05:40 +02:00
Repeater { // the archived accounts
width: parent.width
model: showArchivedWalletsList.on ? portfolio.archivedAccounts : 0;
delegate: AccountListItem {
width: leftColumn.width
account: modelData
// archived accounts don't have access to anything but the activity tab
onClicked: tabbar.currentIndex = 0; // change to the 'activity' tab
}
2022-04-05 16:37:09 +02:00
}
}
2021-04-19 22:36:02 +02:00
}
2021-04-20 15:52:11 +02:00
}
Rectangle {
id: splashScreen
2023-02-21 16:40:46 +01:00
color: palette.window
2021-04-20 15:52:11 +02:00
anchors.fill: parent
2025-06-18 17:48:29 +02:00
Flowee.Label {
2021-04-29 16:33:46 +02:00
text: qsTr("Preparing...")
2021-04-20 15:52:11 +02:00
anchors.centerIn: parent
font.pointSize: 20
2021-04-19 22:36:02 +02:00
}
2021-04-20 15:52:11 +02:00
opacity: mainWindow.isLoading ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 300 } }
2021-04-19 22:36:02 +02:00
}
2022-09-07 20:32:05 +02:00
Keys.onPressed: (event)=> {
2021-04-20 19:30:56 +02:00
if ((event.modifiers & Qt.ControlModifier) !== 0) {
if (event.key === Qt.Key_Q) {
mainWindow.close()
2020-10-15 20:04:10 +02:00
}
}
2020-10-14 15:12:33 +02:00
}
2021-04-22 16:13:40 +02:00
// NetView (reachable from settings)
Loader {
id: netView
onLoaded: {
ControlColors.applySkin(item)
netViewHandler.target = item
2024-02-12 19:19:01 +01:00
item.font = mainWindow.font
2021-04-22 16:13:40 +02:00
}
Connections {
id: netViewHandler
function onVisibleChanged() {
if (!netView.item.visible)
netView.source = ""
}
}
}
2024-02-11 18:34:32 +01:00
Loader {
id: txDetailsWindow
function openTab(walletIndex) {
source = "./TransactionDetails.qml"
if (item.visible)
item.requestActivate();
2024-02-11 18:34:32 +01:00
item.openTab(walletIndex);
}
onLoaded: {
ControlColors.applySkin(item);
txDetailsHandler.target = item;
2024-02-12 19:19:01 +01:00
item.font = mainWindow.font
2024-02-11 18:34:32 +01:00
item.show();
}
Connections {
id: txDetailsHandler
function onVisibleChanged() {
if (!txDetailsWindow.item.visible)
txDetailsWindow.source = ""
}
}
}
2021-10-15 21:01:40 +02:00
// new accounts pane, corresponding to the big green button
2021-04-29 12:12:12 +02:00
Loader {
2021-10-15 21:01:40 +02:00
id: newAccountPane
anchors.fill: parent
2021-10-18 16:30:21 +02:00
onLoaded: {
tabbar.enabled = false // avoid it taking focus on tab
newAccountHandler.target = item // to unload on hide
}
2021-04-29 12:12:12 +02:00
Connections {
id: newAccountHandler
function onVisibleChanged() {
2021-10-15 21:01:40 +02:00
if (!newAccountPane.item.visible) {
newAccountPane.source = ""
2021-10-18 16:30:21 +02:00
tabbar.enabled = true // reenable
tabbar.focus = true;
2021-04-29 12:12:12 +02:00
}
}
}
}
2024-05-07 15:40:36 +02:00
// QRScanner window
QQC2.ApplicationWindow {
id: scannerWindow
visible: CameraController.visible
minimumWidth: 300
minimumHeight: 600
width: 400
height: 700
title: qsTr("QR-Scan")
flags: Qt.Dialog
onClosing: CameraController.abort();
Flowee.QRScanner {
anchors.fill: parent
}
}
2020-10-14 15:12:33 +02:00
}
2020-05-24 13:20:03 +02:00
}