OIMviews.swift (4343B)
1 /* 2 * This file is part of GNU Taler, ©2022-25 Taler Systems S.A. 3 * See LICENSE.md 4 */ 5 /** 6 * @author Marc Stibane 7 */ 8 import SwiftUI 9 import taler_swift 10 11 let OIMbuttonSize = 80.0 12 let OIMactionSize = 120.0 13 14 let OIMACTION = "OIMaction" // Position: trailing edge of the title row 15 let OIMACTION2 = "OIMaction2" // currently unused 16 let OIMNUMBER = "OIMnumber" // center-top 17 let OIMCHEST = "OIMchest" // middle 18 let OIMBACK = "OIMback" // Back Button, QR 19 let OIMLINE = "OIMline" // unused, middle, OIMlineView 20 let OIMSIDE = "OIMside" // trailing-center, money (history) 21 22 // MARK: - 23 struct OIMnavBack<Content: View>: View { 24 let stack: CallStack 25 let chest: String 26 let type: OIMactions 27 let isFinal: Bool // bordered action button 28 let isSending: Bool // move action button 29 let action: (() -> Void)? 30 let actDisabled: Bool 31 var content: () -> Content 32 33 @Environment(\.dismiss) var dismiss // pop back once 34 @EnvironmentObject private var wrapper: NamespaceWrapper 35 36 var body: some View { 37 OIMbackground() { 38 ZStack(alignment: .top) { 39 content() 40 VStack { 41 HStack { // top: chest <-> action 42 OIMbalanceButton(isOpen: true, chest: chest, isFinal: false) { 43 var transaction = Transaction() 44 transaction.disablesAnimations = true // doesn't work with NavigationView 45 withTransaction(transaction) { 46 dismiss() 47 } 48 // withAnimation(nil) { doesn't work either 49 // dismiss() 50 // } 51 } 52 .frame(width: OIMbuttonSize, height: OIMbuttonSize) 53 Spacer() 54 OIMactionButton(type: type, 55 isFinal: isFinal, 56 action: actDisabled ? nil : action) 57 .frame(width: OIMactionSize, height: OIMbuttonSize) 58 .matchedGeometryEffect(id: isSending ? OIMACTION : OIMACTION2, 59 in: wrapper.namespace, isSource: false) 60 } 61 } 62 // .border(.blue) 63 } 64 } 65 } 66 } 67 // MARK: - 68 struct OIMtitleView: View { 69 let cash: OIMcash 70 let amount: Amount? 71 let history: Bool 72 let secondAmount: Amount? 73 74 @EnvironmentObject private var wrapper: NamespaceWrapper 75 76 var body: some View { 77 let chest = cash.currency.chest 78 HStack(alignment: .top) { 79 // invisible - source where the selected balance chest (target) moves to 80 OIMbalanceButton(isOpen: true, chest: chest, isFinal: false) {} 81 .frame(width: OIMbuttonSize, height: history ? OIMbuttonSize / 2 : OIMbuttonSize) 82 .disabled(true) 83 .opacity(INVISIBLE) 84 .matchedGeometryEffect(id: OIMNUMBER, in: wrapper.namespace, isSource: true) 85 .accessibilityHidden(true) 86 // .border(.red) 87 if history { 88 Spacer() 89 } 90 // balance 91 OIMamountV(amount: amount, currencyName: cash.currency.currencyStr, factor: cash.currency.factor) 92 if !history { 93 if let secondAmount { 94 Spacer() 95 // amountToSend 96 OIMamountV(amount: secondAmount, currencyName: cash.currency.currencyStr, factor: cash.currency.factor) 97 } 98 // invisible - source for money (target) flying out of and back in the open chest 99 // Position: trailing edge of the title row 100 OIMactionButton(type: .sendP2P, isFinal: false, action: nil) 101 .frame(width: OIMactionSize, height: OIMbuttonSize) 102 .disabled(true) 103 .opacity(INVISIBLE) 104 .matchedGeometryEffect(id: OIMACTION, in: wrapper.namespace, isSource: true) 105 .accessibilityHidden(true) 106 } 107 } 108 } 109 }