BlueWallet/ios/Widgets/PriceWidget/PriceIntent.swift
Marcos Rodriguez Velez 3cd15744a4 wip
2024-10-28 12:20:40 -04:00

114 lines
3.8 KiB
Swift

import AppIntents
import SwiftUI
@available(iOS 16.0, *)
struct PriceIntent: AppIntent {
static var title: LocalizedStringResource = "Market Rate"
static var description = IntentDescription("View the current Bitcoin market rate.")
static var openAppWhenRun: Bool { false }
static var parameterSummary: some ParameterSummary {
Summary("View the current Bitcoin market rate.")
}
@MainActor
func perform() async throws -> some IntentResult & ReturnsValue<String> & ProvidesDialog & ShowsSnippetView {
let userPreferredCurrency = Currency.getUserPreferredCurrency()
let currencyCode = userPreferredCurrency.uppercased()
let dataSource = fiatUnit(currency: userPreferredCurrency)?.source ?? "Unknown Source"
if userPreferredCurrency != Currency.getLastSelectedCurrency() {
Currency.saveNewSelectedCurrency()
}
var lastUpdated = "--"
var resultValue: String = "--"
var priceDouble: Double = 0.0
do {
guard let data = try await MarketAPI.fetchPrice(currency: userPreferredCurrency) else {
throw NSError(domain: "PriceIntentErrorDomain", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to fetch price data."])
}
priceDouble = data.rateDouble
lastUpdated = formattedDate(from: data.lastUpdate)
resultValue = formatPrice(priceDouble, currencyCode: currencyCode)
} catch {
throw error
}
let view = CompactPriceView(
price: resultValue,
lastUpdated: lastUpdated,
currencyCode: currencyCode,
dataSource: dataSource
)
return .result(
value: resultValue,
dialog: "Current Bitcoin Market Rate",
view: view
)
}
private func formattedDate(from isoString: String?) -> String {
guard let isoString = isoString else { return "--" }
let isoFormatter = ISO8601DateFormatter()
if let date = isoFormatter.date(from: isoString) {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
return formatter.string(from: date)
}
return "--"
}
private func formatPrice(_ price: Double, currencyCode: String) -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyCode = currencyCode
formatter.locale = Locale.current
// Omit cents if they are zero
if price.truncatingRemainder(dividingBy: 1) == 0 {
formatter.maximumFractionDigits = 0
formatter.minimumFractionDigits = 0
} else {
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
}
return formatter.string(from: NSNumber(value: price)) ?? "--"
}
}
@available(iOS 16.0, *)
struct CompactPriceView: View {
let price: String
let lastUpdated: String
let currencyCode: String
let dataSource: String
var body: some View {
VStack(alignment: .center, spacing: 16) {
Text(price)
.font(.title)
.bold()
.multilineTextAlignment(.center)
.accessibilityLabel("Bitcoin price: \(price)")
VStack(alignment: .center, spacing: 4) {
Text("Currency: \(currencyCode)")
Text("Updated: \(lastUpdated)")
Text("Source: \(dataSource)")
}
.font(.subheadline)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.accessibilityElement(children: .combine)
}
.padding()
.frame(maxWidth: .infinity)
}
}