Files
pay/guis/mobile/ActivityTab.qml
T
tomFlowee ac74aa90bb Tie the 'all wallets' to fungible tokens backend
Only show fungible token UTXOs that actually are in the selected wallet.
2026-03-15 14:57:30 +01:00

232 lines
7.7 KiB
QML

/*
* This file is part of the Flowee project
* Copyright (C) 2023-2026 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.Basic as QQC2
import "../Flowee" as Flowee
import "../Utils.js" as Utils
import Flowee.org.pay
Item {
property string icon: "qrc:/homeButtonIcon" + (Pay.useDarkSkin ? "-light.svg" : ".svg")
property string title: qsTr("Home")
property bool showFilterIcon: tabBar.currentIndex === 0
property bool showAllWalletsOption: tabBar.currentIndex !== 0
required property bool allWalletsEntrySelected
property bool itIsChristmas: {
var today = new Date()
return today.getMonth() == 11 && today.getDate() >= 24 && today.getDate() <= 31
}
Rectangle {
id: headerBg
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: tabBar.bottom
anchors.bottomMargin: -6
color: palette.window
property var headerGradient: Gradient {
GradientStop { position: 0.93; color: headerBg.color }
GradientStop { position: 1; color: {
let c = headerBg.color
return Qt.rgba(c.r, c.g, c.b, 0)
}
}
}
gradient: tabBar.visible ? undefined : headerGradient
}
ListView {
id: tabBar
orientation: Qt.Horizontal
width: parent.width
height: {
if (!visible || count <= 1 || currentItem === null)
return 0
return currentItem.height
}
property bool havePlannedTab: Pay.haveRepeatPayments
property bool haveTokensTab: tokens.showTokenTab !== Wallet.AlwaysOff
visible: havePlannedTab
function selectTab(index) {
// fast move
activityTabs.currentIndex = index
activityTabs.positionViewAtIndex(index, ListView.Beginning)
// slow scroll
currentIndex = index
}
clip: true
boundsBehavior: Flickable.StopAtBounds
currentIndex: activityTabs.currentIndex
model: ListModel {
id: tabsModel
ListElement {
title: qsTr("Activity")
qml: "AccountHistory.qml"
}
}
onHavePlannedTabChanged: {
if (!havePlannedTab)
return
for (let i = 1; i < tabsModel.count; ++i) {
let tab = tabsModel.get(i)
if (tab.qml === "PlannedPayments.qml")
return
}
tabsModel.append({ title: qsTr("Planned"), qml: "PlannedPayments.qml" })
}
onHaveTokensTabChanged: {
for (let i = 1; i < tabsModel.count; ++i) {
let tab = tabsModel.get(i)
if (tab.qml === "TokensTab.qml") {
if (!haveTokensTab)
tabsModel.remove(i)
return
}
}
if (haveTokensTab)
tabsModel.insert(1, { title: qsTr("Tokens"), qml: "TokensTab.qml" })
}
delegate: Item {
width: Math.max(tabName.width, 120)
height: tabName.height + 20
Rectangle {
x: 5
height: 4
width: parent.width - 10
color: palette.highlight
visible: index === tabBar.currentIndex
anchors.bottom: parent.bottom
}
Rectangle {
anchors.fill: parent
color: palette.highlight
visible: index === tabBar.currentIndex
opacity: 0.15
}
Text {
id: tabName
color: palette.windowText
text: model.title
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: tabBar.selectTab(index)
}
}
}
Rectangle {
color: palette.base // background is dark.
anchors.fill: activityTabs
}
ListView {
id: activityTabs
anchors.top: tabBar.bottom
anchors.topMargin: tabBar.visible ? 0 : 6
anchors.bottom: parent.bottom
width: parent.width
model: tabBar.model
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
onContentXChanged: currentIndex = Math.round(contentX / width)
boundsBehavior: Flickable.StopAtBounds
onCurrentItemChanged: currentItem.makeActive()
onCurrentIndexChanged: tabBar.currentIndex = currentIndex
delegate: Loader {
id: delegateRoot
width: activityTabs.width
height: activityTabs.height
clip: true
source: model.qml
function makeActive() {
if (item != null) {
item.forceActiveFocus()
}
}
Connections {
target: activityTabs
function onCurrentIndexChanged() {
// let a tab know if it is currently active.
// as the user can slide between them, we can't use visible and tabs have
// a right to know if they are actually visible.
if (item != null && typeof(item.active) != "undefined")
item.active = index == activityTabs.currentIndex
}
}
}
}
Rectangle {
id: startQRButton
width: height
height: {
let i = activityTabs.currentItem
if (i != null && i.item !== null) { // at creation this is the case.
let hide = i.item.hideQRScanButton
if (typeof(hide) === "boolean" && hide)
return 0
}
return 70
}
radius: 35
clip: true
x: parent.width - width - 30 - (70 / 2 - width / 2) // almost right, but keep this centered around the max width
y: parent.height - height - 15 - (70 / 2 - height / 2)
color: mainWindow.floweeBlue
Image {
source: "qrc:/qr-code-scan-light.svg"
anchors.centerIn: parent
width: 40
height: 40
}
MouseArea {
anchors.fill: parent
onClicked: thePile.push("ScanQRPage.qml")
}
Behavior on height { NumberAnimation { } }
}
Keys.onPressed: (event)=> {
if (event.key === Qt.Key_Escape || event.key === Qt.Key_Back) {
// when we are on another tab, we can go to 'main' on back.
if (activityTabs.currentIndex !== 0) {
event.accepted = true
tabBar.selectTab(0)
}
}
}
// should the app be started with the intent to open the "Planned Payment" screen,
// we handle that here.
Connections {
target: intent
function onGenericIntentChanged() { // it only ever changes at most once
if (intent.genericIntent === Intent.OpenPlannedPaymentScreen)
tabBar.selectTab(1)
}
}
}