taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit d948bb6a33a2b0e9a9015b96054642e5fade0c1b
parent f8cbf4d6f3e915c846485a729faf276ceef82593
Author: Marc Stibane <marc@taler.net>
Date:   Mon, 18 Sep 2023 08:32:22 +0200

Bargraph shows the last transactions visually

Diffstat:
MTalerWallet.xcodeproj/project.pbxproj | 12++++++++++++
ATalerWallet1/Helper/View+flippedDirection.swift | 21+++++++++++++++++++++
MTalerWallet1/Views/Balances/BalancesSectionView.swift | 9++++++---
ATalerWallet1/Views/HelperViews/BarGraph.swift | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj @@ -145,6 +145,10 @@ 4E605D932AA8B407002FB9A7 /* Nunito-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4E605D8F2AA8B407002FB9A7 /* Nunito-BlackItalic.ttf */; }; 4E605DAF2AADDD13002FB9A7 /* UIScreen+screenSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E605DAE2AADDD13002FB9A7 /* UIScreen+screenSize.swift */; }; 4E605DB02AADDD13002FB9A7 /* UIScreen+screenSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E605DAE2AADDD13002FB9A7 /* UIScreen+screenSize.swift */; }; + 4E605DB72AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E605DB62AB05E48002FB9A7 /* View+flippedDirection.swift */; }; + 4E605DB82AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E605DB62AB05E48002FB9A7 /* View+flippedDirection.swift */; }; + 4E605DBA2AB05FB6002FB9A7 /* BarGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */; }; + 4E605DBB2AB05FB6002FB9A7 /* BarGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */; }; 4E6EDD852A3615BE0031D520 /* ManualDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E6EDD842A3615BE0031D520 /* ManualDetails.swift */; }; 4E6EDD872A363D8D0031D520 /* ListStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E6EDD862A363D8D0031D520 /* ListStyle.swift */; }; 4E753A062A0952F8002D9328 /* DebugViewC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E753A052A0952F7002D9328 /* DebugViewC.swift */; }; @@ -304,6 +308,8 @@ 4E605D8E2AA8B407002FB9A7 /* Nunito-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-Black.ttf"; sourceTree = "<group>"; }; 4E605D8F2AA8B407002FB9A7 /* Nunito-BlackItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Nunito-BlackItalic.ttf"; sourceTree = "<group>"; }; 4E605DAE2AADDD13002FB9A7 /* UIScreen+screenSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIScreen+screenSize.swift"; sourceTree = "<group>"; }; + 4E605DB62AB05E48002FB9A7 /* View+flippedDirection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+flippedDirection.swift"; sourceTree = "<group>"; }; + 4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarGraph.swift; sourceTree = "<group>"; }; 4E6EDD842A3615BE0031D520 /* ManualDetails.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManualDetails.swift; sourceTree = "<group>"; }; 4E6EDD862A363D8D0031D520 /* ListStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListStyle.swift; sourceTree = "<group>"; }; 4E753A042A08E720002D9328 /* transactions.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = transactions.json; sourceTree = "<group>"; }; @@ -558,6 +564,7 @@ 4E3EAEA72AA70157009F1BE8 /* Binding+onChange.swift */, 4E3EAE8B2AA0933C009F1BE8 /* Font+Taler.swift */, 4EB095082989CB7C0043A8A1 /* View+dismissTop.swift */, + 4E605DB62AB05E48002FB9A7 /* View+flippedDirection.swift */, 4E3B4BC62A429F2A00CC88B8 /* View+Notification.swift */, 4E605DAE2AADDD13002FB9A7 /* UIScreen+screenSize.swift */, 4E363CBB2A237E0900D7E98C /* URL+id+iban.swift */, @@ -703,6 +710,7 @@ isa = PBXGroup; children = ( 4E97968F2A3765ED006F73BC /* AgePicker.swift */, + 4E605DB92AB05FB6002FB9A7 /* BarGraph.swift */, 4EB095472989CBFE0043A8A1 /* Buttons.swift */, 4EF840A62A0B85F400EE0D47 /* CopyShare.swift */, 4ECB62812A0BB01D004ABBB7 /* SelectDays.swift */, @@ -1010,6 +1018,7 @@ 4E3EAE242A990778009F1BE8 /* QRGeneratorView.swift in Sources */, 4E3EAE252A990778009F1BE8 /* WithdrawAcceptDone.swift in Sources */, 4E3EAE262A990778009F1BE8 /* Transaction.swift in Sources */, + 4E605DB72AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */, 4E3EAE272A990778009F1BE8 /* WalletColors.swift in Sources */, 4E3EAE282A990778009F1BE8 /* BalancesListView.swift in Sources */, 4E3EAE292A990778009F1BE8 /* WalletBackendError.swift in Sources */, @@ -1049,6 +1058,7 @@ 4E3EAE4A2A990778009F1BE8 /* PaymentPurpose.swift in Sources */, 4E3EAE4B2A990778009F1BE8 /* ShareSheet.swift in Sources */, 4E3EAE4C2A990778009F1BE8 /* AmountView.swift in Sources */, + 4E605DBA2AB05FB6002FB9A7 /* BarGraph.swift in Sources */, 4E3EAE4D2A990778009F1BE8 /* P2pAcceptDone.swift in Sources */, 4E3EAE4E2A990778009F1BE8 /* AnyTransition+backslide.swift in Sources */, 4EFA39602AA7946B00742548 /* ToSButtonView.swift in Sources */, @@ -1109,6 +1119,7 @@ 4EEC157329F8242800D46A03 /* QRGeneratorView.swift in Sources */, 4E5A88F72A3B9E5B00072618 /* WithdrawAcceptDone.swift in Sources */, 4EB095222989CBCB0043A8A1 /* Transaction.swift in Sources */, + 4E605DB82AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */, 4E9320432A14F6EA00A87B0E /* WalletColors.swift in Sources */, 4EB0955D2989CBFE0043A8A1 /* BalancesListView.swift in Sources */, 4EB095212989CBCB0043A8A1 /* WalletBackendError.swift in Sources */, @@ -1148,6 +1159,7 @@ 4E9320472A164BC700A87B0E /* PaymentPurpose.swift in Sources */, 4E753A082A0B6A5F002D9328 /* ShareSheet.swift in Sources */, 4EB0956C2989CBFE0043A8A1 /* AmountView.swift in Sources */, + 4E605DBB2AB05FB6002FB9A7 /* BarGraph.swift in Sources */, 4E3B4BC32A42252300CC88B8 /* P2pAcceptDone.swift in Sources */, 4E363CBE2A23CB2100D7E98C /* AnyTransition+backslide.swift in Sources */, 4EFA39612AA7946B00742548 /* ToSButtonView.swift in Sources */, diff --git a/TalerWallet1/Helper/View+flippedDirection.swift b/TalerWallet1/Helper/View+flippedDirection.swift @@ -0,0 +1,21 @@ +/* + * This file is part of GNU Taler, ©2022-23 Taler Systems S.A. + * See LICENSE.md + */ +import SwiftUI + +struct FlippedDirection: ViewModifier { + @Environment(\.layoutDirection) var layoutDirection + + func body(content: Content) -> some View { + let isLeft = layoutDirection == .leftToRight + content + .environment(\.layoutDirection, isLeft ? .rightToLeft : .leftToRight) + } +} + +extension View { + func flippedDirection() -> some View { + self.modifier(FlippedDirection()) + } +} diff --git a/TalerWallet1/Views/Balances/BalancesSectionView.swift b/TalerWallet1/Views/Balances/BalancesSectionView.swift @@ -142,8 +142,11 @@ struct BalancesSectionView: View { } } header: { - Text(currency) - .accessibilityFont(.title2) + HStack (alignment: .bottom, spacing: 10) { + BarGraph(transactions: $completedTransactions, barHeight: 10) + Text(currency) + .accessibilityFont(.title2) + } }.id(sectionID) .task { // if shownSectionID != sectionID { @@ -233,7 +236,7 @@ fileprivate struct NavigationLinksView : View { } } // MARK: - -#if DEBUG +#if false // model crashes fileprivate struct BindingViewContainer : View { @State var centsToTransfer: UInt64 = 333 @State private var summary: String = "bla-bla" diff --git a/TalerWallet1/Views/HelperViews/BarGraph.swift b/TalerWallet1/Views/HelperViews/BarGraph.swift @@ -0,0 +1,87 @@ +/* + * This file is part of GNU Taler, ©2022-23 Taler Systems S.A. + * See LICENSE.md + */ +import SwiftUI + +struct BarGraph: View { + @Binding var transactions: [Transaction] + let barHeight : Double + + func maxValue(_ someTransactions: [Transaction]) -> Double { + var maxValue = 0.0 + for transaction in someTransactions { + let value = transaction.common.amountEffective.value + if value > maxValue { + maxValue = value + } + } + return maxValue + } + + var body: some View { + let slice = transactions.prefix(8) + let eightTransactions: [Transaction] = Array(slice) + let count = eightTransactions.count + let maxValue = maxValue(eightTransactions) + + HStack(alignment: .firstTextBaseline, spacing: 1) { +#if DEBUG +// Text("first") +#endif + if count > 0 { + ForEach(Array(eightTransactions.enumerated()), id: \.element) { index, transaction in + let common = transaction.common + let incoming = common.incoming() + let netto = common.amountEffective.value + let valueColored = barHeight * netto / maxValue + let valueTransparent = barHeight - valueColored +// let _ = print("max: \(maxValue), ", incoming ? "+" : "-", netto) + VStack(spacing: 0) { + Rectangle() + .opacity(0.001) + .frame (width: 3, height: incoming ? valueTransparent : barHeight ) + Rectangle() + .foregroundColor(incoming ? .green : .red) + .frame (width: 3, height: valueColored ) + Rectangle() + .opacity(0.001) + .frame (width: 3, height: incoming ? barHeight : valueTransparent) + } + } + } +// if count < 8 { +// ForEach(count...8, id: \.self) {_ in +// Rectangle() +// .opacity(0.001) +// .frame (width: 3, height: barHeight * 2 ) +// } +// } +#if DEBUG +// Text("last") +#endif + } + .accessibilityHidden(true) // cannot speak out this bar chart info +// .flippedDirection() // draw first array item on trailing edge + } +} + + + +#if false +#Preview { + var sampleBars: [BarData] { + var tempBars = [BarData]() + + for _ in 1...8 { + let rand = Double.random(in: -100.0...100.0) + + let bar = BarData(value: rand) + tempBars.append(bar) + } + return tempBars + } + + return BarGraph(bars: sampleBars) +} +#endif