taler-ios

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

commit 416553aa0079b6d40bc2b67bb41e6dc410218f70
parent 4b12e4a8b1cc48f99362aab1b87fc7b5c8219341
Author: Marc Stibane <marc@taler.net>
Date:   Wed, 28 Aug 2024 00:06:24 +0200

deleteExchange

Diffstat:
MTalerWallet1/Localizable.xcstrings | 28++++++++++++++++++++++++++++
MTalerWallet1/Model/Model+Exchange.swift | 23+++++++++++++++++++++++
MTalerWallet1/Views/Banking/ExchangeSectionView.swift | 25+++++++++++++++++++++++++
MTalerWallet1/Views/HelperViews/TransactionButton.swift | 93++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
4 files changed, 133 insertions(+), 36 deletions(-)

diff --git a/TalerWallet1/Localizable.xcstrings b/TalerWallet1/Localizable.xcstrings @@ -1348,6 +1348,16 @@ } } }, + "Are you sure you want to delete this payment provider?" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sind Sie sicher, dass Sie diesen Zahlungsdienst löschen wollen?" + } + } + } + }, "Are you sure you want to delete this transaction?" : { "localizations" : { "de" : { @@ -2832,6 +2842,24 @@ } } }, + "Exchange.Delete" : { + "comment" : "Action button", + "extractionState" : "extracted_with_value", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zahlungsdienst löschen" + } + }, + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Delete Payment Provider" + } + } + } + }, "Expires in:" : { "localizations" : { "de" : { diff --git a/TalerWallet1/Model/Model+Exchange.swift b/TalerWallet1/Model/Model+Exchange.swift @@ -161,6 +161,21 @@ fileprivate struct AddExchange: WalletBackendFormattedRequest { } } +/// A request to delete an exchange. +fileprivate struct DeleteExchange: WalletBackendFormattedRequest { + struct Response: Decodable {} // no result - getting no error back means success + func operation() -> String { "deleteExchange" } + func args() -> Args { Args(exchangeBaseUrl: exchangeBaseUrl, purge: purge) } + + var exchangeBaseUrl: String + var purge: Bool + + struct Args: Encodable { + var exchangeBaseUrl: String + var purge: Bool + } +} + /// A request to get info about a currency fileprivate struct GetCurrencySpecification: WalletBackendFormattedRequest { struct Response: Codable, Sendable { @@ -214,6 +229,14 @@ extension WalletModel { _ = try await sendRequest(request, viewHandles: viewHandles) } + /// add a new exchange with URL to the wallet's list of known exchanges + func deleteExchange(url: String, purge: Bool = false, viewHandles: Bool = false) + async throws { + let request = DeleteExchange(exchangeBaseUrl: url, purge: purge) + logger.info("deleting exchange: \(url, privacy: .public)") + _ = try await sendRequest(request, viewHandles: viewHandles) + } + /// ask wallet-core to update an existing exchange by querying it for denominations, fees, and scoped currency info // func updateExchange(scopeInfo: ScopeInfo) // func updateExchange(scopeInfo: ScopeInfo, viewHandles: Bool = false) diff --git a/TalerWallet1/Views/Banking/ExchangeSectionView.swift b/TalerWallet1/Views/Banking/ExchangeSectionView.swift @@ -16,6 +16,7 @@ struct ExchangeSectionView: View { // @Binding var depositIBAN: String // @Binding var accountHolder: String @Binding var amountToTransfer: Amount // does still have the wrong currency + @EnvironmentObject private var model: WalletModel @EnvironmentObject private var controller: Controller @AppStorage("minimalistic") var minimalistic: Bool = false @@ -23,6 +24,9 @@ struct ExchangeSectionView: View { @State private var currencyInfo: CurrencyInfo = CurrencyInfo.zero(UNKNOWN) @State private var currencyName: String = UNKNOWN @State private var currencySymbol: String = UNKNOWN + @State private var didDelete: Bool = false + @State private var disabled: Bool = false + @State private var purge: Bool = false func amountAvailable(_ exchange: Exchange?, currency: String?) -> Amount? { if let exchange { @@ -41,6 +45,19 @@ struct ExchangeSectionView: View { return nil } + private func deleteExchange() { + disabled = true // don't try this more than once + Task { // runs on MainActor + if let _ = try? await model.deleteExchange(url: exchange.exchangeBaseUrl, purge: purge) { +// symLog.log("\(executed) \(transactionId)") + didDelete = true // change button text + } else { + purge = true + disabled = false + } + } + } + var body: some View { #if PRINT_CHANGES let _ = Self._printChanges() @@ -76,6 +93,14 @@ struct ExchangeSectionView: View { .accessibilityLabel(bankingHint + " " + linkTitle) .padding(.top) } + + let buttonTitle = String(localized: "Exchange.Delete", defaultValue: "Delete Payment Provider", comment: "Action button") + WarningButton(warningText: String(localized: "Are you sure you want to delete this payment provider?"), + buttonTitle: buttonTitle, + buttonIcon: "trash", + role: .destructive, + disabled: $disabled, + action: deleteExchange) } header: { BarGraphHeader(stack: stack.push(), scopeInfo: scopeInfo, diff --git a/TalerWallet1/Views/HelperViews/TransactionButton.swift b/TalerWallet1/Views/HelperViews/TransactionButton.swift @@ -6,24 +6,69 @@ import SwiftUI import taler_swift import AVFoundation +struct WarningButton: View { + let warningText: String? + let buttonTitle: String + let buttonIcon: String? + let role: ButtonRole? + @Binding var disabled: Bool + let action: () -> Void + + @AppStorage("shouldShowWarning") var shouldShowWarning: Bool = true + @State private var showAlert: Bool = false + + var body: some View { + Button(role: role, + action: { + if !disabled { + if shouldShowWarning && (role == .destructive || role == .cancel) { + showAlert = true + } else { + action() + } + } + }) { + HStack(spacing: 50) { + Text(buttonTitle) + if let buttonIcon { + Image(systemName: buttonIcon) + } + } + } + .talerFont(.title2) + .frame(maxWidth: .infinity) + .buttonStyle(.bordered) + .controlSize(.large) + .disabled(disabled) + .alert(warningText ?? EMPTYSTRING, isPresented: $showAlert, actions: { + Button("Cancel", role: .cancel) { + showAlert = false + } + Button(buttonTitle) { + showAlert = false + action() + } + }, message: { Text("This operation cannot be undone") } + ) + } +} +// MARK: - struct TransactionButton: View { let transactionId: String let command: TxAction let warning: String? let action: (_ transactionId: String, _ viewHandles: Bool) async throws -> Void - @AppStorage("shouldShowWarning") var shouldShowWarning: Bool = true - @State private var disabled: Bool = false @State private var executed: Bool = false - @State private var showAlert: Bool = false + @State private var buttonTitle: String = EMPTYSTRING private func doAction() { disabled = true // don't try this more than once Task { // runs on MainActor if let _ = try? await action(transactionId, false) { // symLog.log("\(executed) \(transactionId)") - executed = true + executed = true // change button text } } } @@ -34,38 +79,14 @@ struct TransactionButton: View { let role: ButtonRole? = isDestructive ? .destructive : isCancel ? .cancel : nil - Button(role: role, action: { - if !disabled { - if shouldShowWarning && (isDestructive || isCancel) { - showAlert = true - } else { - doAction() - } - } - }, label: { - HStack(spacing: 50) { - Text(executed ? command.localizedActionExecuted - : command.localizedActionTitle) - if let imageName = command.localizedActionImage { - Image(systemName: imageName) - } - } - .talerFont(.title2) - .frame(maxWidth: .infinity) - }) - .buttonStyle(.bordered) - .controlSize(.large) - .disabled(disabled) - .alert(warning ?? EMPTYSTRING, isPresented: $showAlert, actions: { - Button("Cancel", role: .cancel) { - showAlert = false - } - Button(command.localizedActionTitle) { - showAlert = false - doAction() - } - }, message: { Text("This operation cannot be undone") } - ) + let buttonTitle = executed ? command.localizedActionExecuted + : command.localizedActionTitle + WarningButton(warningText: warning, + buttonTitle: command.localizedActionTitle, + buttonIcon: command.localizedActionImage, + role: role, + disabled: $disabled, + action: doAction) } } // MARK: -