Files
pay/guis/mobile/ActivityTab.qml
T
tomFlowee d81bf48984 Various UX fixes around the new tabs
This fixes the weird dialog not getting a press but just closing problem
which seems to stem from the horizontal listview getting its current
index set. So we just avoid doing that.

This fixes the bug in the last release where not having the payments tab
visible meant we didn't see the tabbar at all. The logic is now fixed to
include the fact that we can have a tokens tab too.
2026-03-16 20:16:38 +01:00

233 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: count > 1
function selectTab(index) {
// fast move
activityTabs.positionViewAtIndex(index, ListView.Beginning)
// slow scroll
currentIndex = index
}
clip: true
boundsBehavior: Flickable.StopAtBounds
model: ListModel {
id: tabsModel
ListElement {
title: qsTr("Activity")
qml: "AccountHistory.qml"
}
}
onHavePlannedTabChanged: {
if (!havePlannedTab)
return
tabBar.selectTab(0)
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: {
tabBar.selectTab(0)
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: tabBar.currentIndex = Math.round(contentX / width)
boundsBehavior: Flickable.StopAtBounds
onCurrentItemChanged: currentItem.makeActive()
delegate: Loader {
id: delegateRoot
width: activityTabs.width
height: activityTabs.height
clip: true
source: model.qml
function makeActive() {
if (item != null) {
if (typeof(item.active) != "undefined")
item.active = true
item.forceActiveFocus()
}
}
Connections {
target: tabBar
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 == tabBar.currentIndex
}
}
}
}
Rectangle {
id: startQRButton
width: height
height: {
let i = activityTabs.itemAtIndex(tabBar.currentIndex)
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 (tabBar.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)
}
}
}