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:
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