/* * This file is part of the Flowee project * Copyright (C) 2025-2026 Tom Zander * * 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 . */ import QtQuick import QtQuick.Controls.Basic as QQC2 import "../Flowee" as Flowee import "../Utils.js" as Utils import Flowee.org.pay ListView { id: root property bool hideQRScanButton: true property bool active: false // true when this is the current tab model: RepeatPaymentsModel { id: repeatPaymentsModel combineWallets: allWalletsEntrySelected currentAccount: portfolio.current } onActiveChanged: { if (!active) // move 'approved' items to the proper section model.updateOrdering() } clip: true focus: true section.property: "section" section.labelPositioning: ViewSection.InlineLabels + ViewSection.CurrentLabelAtStart section.delegate: Item { height: label.height + 3 width: root.width Flowee.Label { id: label x: 10 font.bold: true font.pixelSize: mainWindow.font.pixelSize * 1.1 text: { if (section == 1) // yes, 2 equals return qsTr("Payments to Approve") if (section == 2) // yes, 2 equals return qsTr("Approved Payments") return qsTr("Inactive Payments") } } MouseArea { anchors.fill: parent } // eat all taps } delegate: Rectangle { id: delegateRoot width: ListView.view.width height: 16 + amountFiat.height + 6 + comment.height + 6 + approvedLine.height + 6 + walletChoice.height + 24 color: palette.base property QtObject payment: model.payment Rectangle { anchors.fill: parent anchors.margins: 10 gradient: Gradient { GradientStop { position: Pay.useDarkSkin ? 2 : 1 color: Pay.useDarkSkin ? palette.midlight : palette.mid } GradientStop { position: 0 color: palette.base } } radius: 10 MouseArea { anchors.fill: parent onClicked: thePile.push("RepeatPaymentDetails.qml", { "savedPayment": model.payment }) } } Flowee.BitcoinAmountLabel { id: amountBch value: model.valueSats x: 16 y: 24 showFiat: false colorize: false anchors.top: nextDate.bottom anchors.topMargin: 6 visible: model.fiatFollows // check if the payment prefers fiat over sats } Flowee.Label { id: amountFiat text: { let txt = Fiat.formattedPrice(model.valueFiat) if (amountBch.visible) return "(" + txt + ")" return txt } x: 16 + (amountBch.visible ? amountBch.width + 10 : 0) y: 24 anchors.left: amountBch.visible ? amountBch.right : parent.left anchors.leftMargin: amountBch.visible ? 6 : 16 } Flowee.Label { id: comment text: model.comment width: parent.width - 32 elide: Text.ElideRight x: 16 anchors.top: amountFiat.bottom height: text === "" ? 0 : contentHeight } Item { id: approvedLine property bool isEnabled: delegateRoot.payment.enabled anchors.top: comment.bottom anchors.topMargin: 6 x: 16 width: checkLabel.contentWidth + 20 height: Math.max(24, checkLabel.contentHeight) Rectangle { radius: 4 color: palette.base border.color: palette.highlight border.width: 1.3 width: 24 height: 24 visible: approvedLine.isEnabled anchors.bottom: checkLabel.bottom } Flowee.Label { visible: approvedLine.isEnabled id: checkLabel x: 30 text: { let d = model.upcomingDate let now = new Date() // close to 'now', or in the past if (d - now < 18 * 3600 * 1000) // 18h in ms return qsTr("Approve to pay: today") return qsTr("Approve to pay on %1", "The arg is a date").arg(Pay.formatDate(d)) } } Flowee.CheckShape { id: check transformOrigin: Item.BottomLeft smooth: true scale: 1.6 anchors.bottom: parent.bottom anchors.bottomMargin: 3 visible: approvedLine.isEnabled && model.isApproved } MouseArea { anchors { margins: -10 left: parent.left top: parent.top right: checkLabel.right bottom: checkLabel.bottom } onClicked: delegateRoot.payment.approved = !delegateRoot.payment.approved } Flowee.Label { visible: !approvedLine.isEnabled text: qsTr("Paused") font.italic: true } } Flowee.Label { id: walletChoice anchors.left: approvedLine.left anchors.top: approvedLine.bottom anchors.topMargin: 6 visible: !portfolio.singleAccountSetup && allWalletsEntrySelected text: qsTr("From wallet: %1").arg(delegateRoot.payment.accountName) height: visible ? contentHeight : 0 } Flowee.HamburgerMenu { anchors.right: parent.right anchors.rightMargin: 25 anchors.top: amountBch.top MouseArea { id: mouseArea anchors.fill: parent anchors.margins: -20 onClicked: contextMenu.open() } Flowee.Popup { id: contextMenu x: -width - 5 width: Math.max(150, Math.max(button1.implicitWidth, button2.implicitWidth)) height: col.height Column { id: col width: parent.width - 20 x: 10 spacing: 10 TextButton { id: button1 text: delegateRoot.payment.enabled ? qsTr("Pause") : qsTr("Resume") onClicked: delegateRoot.payment.enabled = !delegateRoot.payment.enabled } TextButton { id: button2 text: qsTr("Delete...") onClicked: { contextMenu.close() okDeleteDiag.open() } } } } } Flowee.Dialog { id: okDeleteDiag title: qsTr("Confirm delete") text: qsTr("Do you really want to delete this repeating-payment?") onAccepted: Pay.removeRepeatPayment(delegateRoot.payment.payment) } } }