taler-ios

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

commit d55562269cd5835171591ffb7100f8ea0dffc3f2
parent 2387c4f4627d3ce7fc22d61beceb67573ea677b4
Author: Marc Stibane <marc@taler.net>
Date:   Wed, 13 Dec 2023 22:24:42 +0100

CurrencyInfo from Exchange

Diffstat:
MTalerWallet1/Controllers/Controller.swift | 31+++++++++++++++++++++++++++----
MTalerWallet1/Helper/Controller+playSound.swift | 19++++++++++++++-----
MTalerWallet1/Model/Model+Exchange.swift | 3++-
MTalerWallet1/Views/Exchange/ExchangeRowView.swift | 4++--
MTalerWallet1/Views/Main/MainView.swift | 4++--
5 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/TalerWallet1/Controllers/Controller.swift b/TalerWallet1/Controllers/Controller.swift @@ -35,7 +35,7 @@ class Controller: ObservableObject { private let symLog = SymLogC() @Published var backendState: BackendState = .none // only used for launch animation - @Published var currencyTicker: Int = 0 + @Published var currencyTicker: Int = 0 // updates whenever a new currency is added @AppStorage("useHaptics") var useHaptics: Bool = true // extension mustn't define this, so it must be here @AppStorage("playSounds") var playSounds: Int = 1 // extension mustn't define this, so it must be here @AppStorage("talerFont") var talerFont: Int = 0 // extension mustn't define this, so it must be here @@ -59,13 +59,13 @@ class Controller: ObservableObject { currencyInfos = [] } // MARK: - - func hasInfo(for currency: String) -> Bool { + func hasInfo(for currency: String) -> CurrencyInfo? { for info in currencyInfos { if info.scope.currency == currency { - return true + return info } } - return false + return nil } func info(for currency: String, _ ticker: Int) -> CurrencyInfo { @@ -81,6 +81,29 @@ class Controller: ObservableObject { } @MainActor + func getInfo(from exchangeBaseUrl: String, model: WalletModel) async -> CurrencyInfo? { + if let exchange = await model.getExchangeByUrl(url: exchangeBaseUrl) { + if let scopeInfo = exchange.scopeInfo { + if let info = hasInfo(for: scopeInfo.currency) { + return info + } + do { + let info = try await model.getCurrencyInfoM(scope: scopeInfo, delay: 0) + await setInfo(info) + return info + } catch { + return nil + } + } else { + // TODO: Error "Can't get scopeInfo" + } + } else { + // TODO: Error "Can't get Exchange Info" + } + return nil + } + + @MainActor func setInfo(_ newInfo: CurrencyInfo) async { await semaphore.wait() defer { semaphore.signal() } diff --git a/TalerWallet1/Helper/Controller+playSound.swift b/TalerWallet1/Helper/Controller+playSound.swift @@ -8,6 +8,19 @@ import UIKit extension Controller { + @MainActor + func hapticNotification(_ feedbackType: UINotificationFeedbackGenerator.FeedbackType) { + if useHaptics { + UINotificationFeedbackGenerator().notificationOccurred(feedbackType) + } + } + + @MainActor + func hapticFeedback(_ feedbackStyle: UIImpactFeedbackGenerator.FeedbackStyle) { + UIImpactFeedbackGenerator(style: feedbackStyle).impactOccurred() + } + + /// 0 = failure, 1 = received, 2 = sent @MainActor func playSound(_ number: Int) { let sysVolume = AVAudioSession.sharedInstance().outputVolume @@ -31,7 +44,6 @@ extension Controller { // logger.log("❗️sys:\(sysVolume) vol:\(volume)") var soundID: SystemSoundID = 0 - let notificationGenerator = useHaptics ? UINotificationFeedbackGenerator() : nil if number > 9 { soundID = UInt32(number) } else { @@ -58,9 +70,6 @@ extension Controller { AudioServicesPlaySystemSound(soundID); } } - if let notificationGenerator { - notificationGenerator.notificationOccurred(number == 0 ? .error : .success) - } - + hapticNotification(number == 0 ? .error : .success) } } diff --git a/TalerWallet1/Model/Model+Exchange.swift b/TalerWallet1/Model/Model+Exchange.swift @@ -199,7 +199,8 @@ extension WalletModel { _ = try await sendRequest(request) } - func getCurrencyInfo(scope: ScopeInfo, delay: UInt = 0) + @MainActor + func getCurrencyInfoM(scope: ScopeInfo, delay: UInt = 0) async throws -> CurrencyInfo { let request = GetCurrencySpecification(scope: scope) let response = try await sendRequest(request, ASYNCDELAY + delay) diff --git a/TalerWallet1/Views/Exchange/ExchangeRowView.swift b/TalerWallet1/Views/Exchange/ExchangeRowView.swift @@ -97,12 +97,12 @@ struct ExchangeRowView: View { } } .task { - if !controller.hasInfo(for: currency) { + if controller.hasInfo(for: currency) == nil { symLog.log("fetching info for \(currency)") // FIXME: remove fake ScopeInfo once the REAL one is in exchange.scopeInfo let scopeInfo = exchange.scopeInfo ?? ScopeInfo(type: .global, currency: currency) do { - let info = try await model.getCurrencyInfo(scope: scopeInfo, delay: delay) + let info = try await model.getCurrencyInfoM(scope: scopeInfo, delay: delay) // logger.info("got info: \(scope.currency, privacy: .public)") await controller.setInfo(info) } catch { // TODO: error handling - couldn't get CurrencyInfo diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift @@ -280,11 +280,11 @@ extension MainView { for balance in newArray { let scope = balance.scopeInfo logger.info("balance changed: \(scope.currency, privacy: .public)") - if !controller.hasInfo(for: scope.currency) { + if controller.hasInfo(for: scope.currency) == nil { Task { // runs on MainActor logger.info("Task to get info for: \(scope.currency, privacy: .public)") do { - let info = try await model.getCurrencyInfo(scope: scope, delay: delay) + let info = try await model.getCurrencyInfoM(scope: scope, delay: delay) logger.info("got info: \(scope.currency, privacy: .public)") await controller.setInfo(info) } catch { // TODO: error handling - couldn't get CurrencyInfo