summaryrefslogtreecommitdiff
path: root/TalerWallet1/Views/Peer2peer/P2PSubjectV.swift
blob: 1e1550e62a27ee82ad52f55660c11e01876f210f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 * This file is part of GNU Taler, ©2022-23 Taler Systems S.A.
 * See LICENSE.md
 */
import SwiftUI
import taler_swift
import SymLog

func p2pFee(ppCheck: CheckPeerPushDebitResponse) -> Amount? {
    do {
        // Outgoing: fee = effective - raw
        let fee = try ppCheck.amountEffective - ppCheck.amountRaw
        return fee
    } catch {}
    return nil
}

struct P2PSubjectV: View {
    private let symLog = SymLogV(0)
    let stack: CallStack
    let feeLabel: String?
    let feeIsNotZero: Bool?             // nil = no fees at all, false = no fee for this tx
    let currencyInfo: CurrencyInfo
    let amountToSend: Bool
    @Binding var amountToTransfer: Amount
    @Binding var summary: String
    @Binding var expireDays: UInt

    @EnvironmentObject private var model: WalletModel
    @Environment(\.colorScheme) private var colorScheme
    @Environment(\.colorSchemeContrast) private var colorSchemeContrast
    @AppStorage("minimalistic") var minimalistic: Bool = false

    @State private var myFeeLabel: String = EMPTYSTRING
    @State private var transactionStarted: Bool = false
    @FocusState private var isFocused: Bool

    private func buttonTitle(_ amount: Amount, _ currencyInfo: CurrencyInfo) -> String {
        let amountWithCurrency = amount.string(currencyInfo, useSymbol: false)
        return amountToSend ? String(localized: "Send \(amountWithCurrency) now",
                                       comment: "amount with currency")
                            : String(localized: "Request \(amountWithCurrency)",
                                       comment: "amount with currency")
    }

    private func subjectTitle(_ amount: Amount, _ currencyInfo: CurrencyInfo) -> String {
        let amountStr = amount.string(currencyInfo)
        return amountToSend ? String(localized: "NavTitle_Send_AmountStr",
                                  defaultValue: "Send \(amountStr)",
                                       comment: "NavTitle: Send 'amountStr'")
                            : String(localized: "NavTitle_Request_AmountStr",
                                  defaultValue: "Request \(amountStr)",
                                       comment: "NavTitle: Request 'amountStr'")
    }

    var body: some View {
#if PRINT_CHANGES
        let _ = Self._printChanges()
        let _ = symLog.vlog(amountToTransfer.readableDescription)       // just to get the # to compare it with .onAppear & onDisappear
#endif
        ScrollView { VStack (alignment: .leading, spacing: 6) {
            if let feeIsNotZero {       // don't show fee if nil
                let label = feeLabel ?? myFeeLabel
                if label.count > 0 {
                    Text(label)
                        .frame(maxWidth: .infinity, alignment: .trailing)
                        .foregroundColor(feeIsNotZero ? .red : WalletColors().secondary(colorScheme, colorSchemeContrast))
                        .talerFont(.body)
                }
            }
                if !minimalistic {
                    Text("Enter subject:")    // Purpose
                        .talerFont(.title3)
                        .accessibilityAddTraits(.isHeader)
                        .accessibilityRemoveTraits(.isStaticText)
                        .padding(.top)
                }
                Group { if #available(iOS 16.0, *) {
                    TextField(minimalistic ? "Subject" : EMPTYSTRING, text: $summary, axis: .vertical)
                        .focused($isFocused)
                        .lineLimit(2...)
                } else {
                    TextField("Subject", text: $summary)
                        .focused($isFocused)
//                      .lineLimit(2...5)   // lineLimit' is only available in iOS 16.0 or newer
                } } // Group for iOS16+ & iOS15
                    .talerFont(.title2)
                    .foregroundColor(WalletColors().fieldForeground)     // text color
                    .background(WalletColors().fieldBackground)
                    .textFieldStyle(.roundedBorder)
                    .onAppear {
                        if !UIAccessibility.isVoiceOverRunning {
                            symLog.log("dispatching kbd...")
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) {
                                isFocused = true        // make first responder - raise keybord
                                symLog.log("...kbd isFocused")
                            }
                        }
                    }
                Text(verbatim: "\(summary.count)/100")                          // maximum 100 characters
                    .frame(maxWidth: .infinity, alignment: .trailing)
                    .talerFont(.body)
                    .accessibilityValue(String(localized: "\(summary.count) characters of 100"))

                // TODO: compute max Expiration day from peerPushCheck to disable 30 (and even 7)
                SelectDays(selected: $expireDays, maxExpiration: THIRTYDAYS)
                    .disabled(false)
                    .padding(.bottom)

                let disabled = (expireDays == 0) || (summary.count < 1)    // TODO: check amountAvailable
                NavigationLink(destination: LazyView {
                    P2PReadyV(stack: stack.push(),
                            summary: summary,
                         expireDays: expireDays,
                       amountToSend: amountToSend,
                   amountToTransfer: amountToTransfer,
                 transactionStarted: $transactionStarted)
                }) {
                    Text(buttonTitle(amountToTransfer, currencyInfo))
                }
                .buttonStyle(TalerButtonStyle(type: .prominent, disabled: disabled))
                .disabled(disabled)
                .accessibilityHint(disabled ? String(localized: "enabled when subject and expiration are set") : EMPTYSTRING)
        }.padding(.horizontal) } // ScrollVStack
//        .scrollBounceBehavior(.basedOnSize)  needs iOS 16.4
        .navigationTitle(subjectTitle(amountToTransfer, currencyInfo))
        .background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.all))
        .onAppear {
            DebugViewC.shared.setViewID(VIEW_P2P_SUBJECT, stack: stack.push())
//            print("❗️ P2PSubjectV onAppear")
        }
        .onDisappear {
//            print("❗️ P2PSubjectV onDisappear")
        }
        .task(id: amountToTransfer.value) {
            if amountToSend && feeLabel == nil {
                if let ppCheck = try? await model.checkPeerPushDebitM(amountToTransfer) {
                    if let feeAmount = p2pFee(ppCheck: ppCheck) {
                        let feeStr = feeAmount.string(currencyInfo)
                        myFeeLabel = String(localized: "+ \(feeStr) fee")
                    } else { myFeeLabel = EMPTYSTRING }
                }
            }
        }
    }
}
// MARK: -
#if DEBUG
//struct SendPurpose_Previews: PreviewProvider {
//    static var previews: some View {
//        @State var summary: String = ""
//        @State var expireDays: UInt = 0
//        let amount = Amount(currency: LONGCURRENCY, integer: 10, fraction: 0)
//        SendPurpose(amountAvailable: amount,
//                   amountToTransfer: 543,
//                                fee: "0,43",
//                            summary: $summary,
//                         expireDays: $expireDays)
//    }
//}
#endif