mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-14 03:26:56 +01:00
wip
This commit is contained in:
parent
8c5ef2915c
commit
d4aeba9737
6 changed files with 573 additions and 97 deletions
|
@ -138,6 +138,12 @@
|
|||
B48630ED2CCEEEB000A8425C /* WalletAppShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = B48630EB2CCEEEA700A8425C /* WalletAppShortcuts.swift */; };
|
||||
B48630EE2CCEEEE900A8425C /* PriceIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = B48630D02CCEE3B300A8425C /* PriceIntent.swift */; };
|
||||
B48A6A292C1DF01000030AB9 /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = B48A6A282C1DF01000030AB9 /* KeychainSwift */; };
|
||||
B49A28BB2CD18999006B08E4 /* CompactPriceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49A28BA2CD18999006B08E4 /* CompactPriceView.swift */; };
|
||||
B49A28BC2CD18999006B08E4 /* CompactPriceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49A28BA2CD18999006B08E4 /* CompactPriceView.swift */; };
|
||||
B49A28BE2CD189B0006B08E4 /* FiatUnitEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49A28BD2CD189B0006B08E4 /* FiatUnitEnum.swift */; };
|
||||
B49A28BF2CD18A9A006B08E4 /* FiatUnitEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49A28BD2CD189B0006B08E4 /* FiatUnitEnum.swift */; };
|
||||
B49A28C02CD199C7006B08E4 /* MarketAPI+Electrum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6CA5142558EBA3009312A5 /* MarketAPI+Electrum.swift */; };
|
||||
B49A28C12CD199FC006B08E4 /* SwiftTCPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40FC3F829CCD1AC0007EBAC /* SwiftTCPClient.swift */; };
|
||||
B4AB225D2B02AD12001F4328 /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */; };
|
||||
B4AB225E2B02AD12001F4328 /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */; };
|
||||
B4B1A4622BFA73110072E3BB /* WidgetHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4B1A4612BFA73110072E3BB /* WidgetHelper.swift */; };
|
||||
|
@ -373,6 +379,8 @@
|
|||
B48630DF2CCEE7C800A8425C /* PriceWidgetEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceWidgetEntryView.swift; sourceTree = "<group>"; };
|
||||
B48630EB2CCEEEA700A8425C /* WalletAppShortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletAppShortcuts.swift; sourceTree = "<group>"; };
|
||||
B49038D82B8FBAD300A8164A /* BlueWalletUITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlueWalletUITest.swift; sourceTree = "<group>"; };
|
||||
B49A28BA2CD18999006B08E4 /* CompactPriceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactPriceView.swift; sourceTree = "<group>"; };
|
||||
B49A28BD2CD189B0006B08E4 /* FiatUnitEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiatUnitEnum.swift; sourceTree = "<group>"; };
|
||||
B4AB225C2B02AD12001F4328 /* XMLParserDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XMLParserDelegate.swift; sourceTree = "<group>"; };
|
||||
B4B1A4612BFA73110072E3BB /* WidgetHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetHelper.swift; sourceTree = "<group>"; };
|
||||
B4B31A352C77BBA000663334 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Interface.strings; sourceTree = "<group>"; };
|
||||
|
@ -544,6 +552,7 @@
|
|||
6D6CA4BB255872E3009312A5 /* PriceWidget */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B49A28BA2CD18999006B08E4 /* CompactPriceView.swift */,
|
||||
B48630DF2CCEE7C800A8425C /* PriceWidgetEntryView.swift */,
|
||||
B48630DC2CCEE7AC00A8425C /* PriceWidgetEntry.swift */,
|
||||
B48630D52CCEE67100A8425C /* PriceWidgetProvider.swift */,
|
||||
|
@ -598,6 +607,7 @@
|
|||
6DEB4BC1254FB98300E9F9AA /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B49A28BD2CD189B0006B08E4 /* FiatUnitEnum.swift */,
|
||||
6DEB4DD82552260200E9F9AA /* Views */,
|
||||
6D4AF18225D215D0009DD853 /* BlueWalletWatch-Bridging-Header.h */,
|
||||
B40FC3F829CCD1AC0007EBAC /* SwiftTCPClient.swift */,
|
||||
|
@ -1206,16 +1216,19 @@
|
|||
B48630E82CCEE92400A8425C /* PriceWidget.swift in Sources */,
|
||||
B44033DD2BCC36C300162242 /* LatestTransaction.swift in Sources */,
|
||||
6D32C5C62596CE3A008C077C /* EventEmitter.m in Sources */,
|
||||
B49A28C12CD199FC006B08E4 /* SwiftTCPClient.swift in Sources */,
|
||||
B44033FE2BCC37D700162242 /* MarketAPI.swift in Sources */,
|
||||
B450109C2C0FCD8A00619044 /* Utilities.swift in Sources */,
|
||||
B48630E52CCEE8B800A8425C /* PriceView.swift in Sources */,
|
||||
B48630E72CCEE91900A8425C /* PriceWidgetProvider.swift in Sources */,
|
||||
B49A28C02CD199C7006B08E4 /* MarketAPI+Electrum.swift in Sources */,
|
||||
B48630ED2CCEEEB000A8425C /* WalletAppShortcuts.swift in Sources */,
|
||||
B45010A62C1507DE00619044 /* CustomSegmentedControlManager.m in Sources */,
|
||||
B44033CE2BCC352900162242 /* UserDefaultsGroup.swift in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
B461B852299599F800E431AA /* AppDelegate.mm in Sources */,
|
||||
B44033F42BCC377F00162242 /* WidgetData.swift in Sources */,
|
||||
B49A28BF2CD18A9A006B08E4 /* FiatUnitEnum.swift in Sources */,
|
||||
B44033C42BCC332400162242 /* Balance.swift in Sources */,
|
||||
B48630EE2CCEEEE900A8425C /* PriceIntent.swift in Sources */,
|
||||
B44034072BCC38A000162242 /* FiatUnit.swift in Sources */,
|
||||
|
@ -1226,6 +1239,7 @@
|
|||
B44033DA2BCC369A00162242 /* Colors.swift in Sources */,
|
||||
B44033D32BCC368800162242 /* UserDefaultsGroupKey.swift in Sources */,
|
||||
32B5A32A2334450100F8D608 /* Bridge.swift in Sources */,
|
||||
B49A28BC2CD18999006B08E4 /* CompactPriceView.swift in Sources */,
|
||||
B44033D82BCC369500162242 /* UserDefaultsExtension.swift in Sources */,
|
||||
B44033E42BCC36FF00162242 /* WalletData.swift in Sources */,
|
||||
B44033BF2BCC32F800162242 /* BitcoinUnit.swift in Sources */,
|
||||
|
@ -1246,6 +1260,7 @@
|
|||
B48630EC2CCEEEA700A8425C /* WalletAppShortcuts.swift in Sources */,
|
||||
6DD410A1266CADF10087DE03 /* Widgets.swift in Sources */,
|
||||
B450109D2C0FCD9F00619044 /* Utilities.swift in Sources */,
|
||||
B49A28BE2CD189B0006B08E4 /* FiatUnitEnum.swift in Sources */,
|
||||
6DD410AC266CAE470087DE03 /* PriceWidget.swift in Sources */,
|
||||
B4B1A4642BFA73110072E3BB /* WidgetHelper.swift in Sources */,
|
||||
B44033D52BCC368800162242 /* UserDefaultsGroupKey.swift in Sources */,
|
||||
|
@ -1255,6 +1270,7 @@
|
|||
B44033CC2BCC350A00162242 /* Currency.swift in Sources */,
|
||||
6DD410B6266CAF5C0087DE03 /* PriceView.swift in Sources */,
|
||||
B48630DE2CCEE7AC00A8425C /* PriceWidgetEntry.swift in Sources */,
|
||||
B49A28BB2CD18999006B08E4 /* CompactPriceView.swift in Sources */,
|
||||
6DD410B3266CAF5C0087DE03 /* Colors.swift in Sources */,
|
||||
B44033C12BCC32F800162242 /* BitcoinUnit.swift in Sources */,
|
||||
6DD410BB266CAF5C0087DE03 /* MarketView.swift in Sources */,
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
{
|
||||
"sourceLanguage" : "en_US",
|
||||
"strings" : {
|
||||
"Argentina (Argentine Peso)" : {
|
||||
|
||||
},
|
||||
"Aruba (Aruban Florin)" : {
|
||||
|
||||
},
|
||||
"at %@" : {
|
||||
|
||||
},
|
||||
"Australia (Australian Dollar)" : {
|
||||
|
||||
},
|
||||
"Bahrain (Bahraini Dinar)" : {
|
||||
|
||||
},
|
||||
"Balance" : {
|
||||
|
||||
|
@ -12,12 +24,36 @@
|
|||
},
|
||||
"Bitcoin price: %@" : {
|
||||
|
||||
},
|
||||
"Brazil (Brazilian Real)" : {
|
||||
|
||||
},
|
||||
"BTC" : {
|
||||
|
||||
},
|
||||
"Canada (Canadian Dollar)" : {
|
||||
|
||||
},
|
||||
"Central African Republic (Central African Franc)" : {
|
||||
|
||||
},
|
||||
"Checked at %@" : {
|
||||
|
||||
},
|
||||
"Chile (Chilean Peso)" : {
|
||||
|
||||
},
|
||||
"China (Chinese Yuan)" : {
|
||||
|
||||
},
|
||||
"Colombia (Colombian Peso)" : {
|
||||
|
||||
},
|
||||
"Croatia (Croatian Kuna)" : {
|
||||
|
||||
},
|
||||
"Currency" : {
|
||||
|
||||
},
|
||||
"Currency: %@" : {
|
||||
|
||||
|
@ -27,12 +63,60 @@
|
|||
},
|
||||
"Current Bitcoin Price: %@" : {
|
||||
|
||||
},
|
||||
"Czech Republic (Czech Koruna)" : {
|
||||
|
||||
},
|
||||
"Denmark (Danish Krone)" : {
|
||||
|
||||
},
|
||||
"European Union (Euro)" : {
|
||||
|
||||
},
|
||||
"Failed to retrieve the Bitcoin market rate." : {
|
||||
|
||||
},
|
||||
"Fiat Currency" : {
|
||||
|
||||
},
|
||||
"from" : {
|
||||
|
||||
},
|
||||
"From %@" : {
|
||||
|
||||
},
|
||||
"Ghana (Ghanaian Cedi)" : {
|
||||
|
||||
},
|
||||
"Hungary (Hungarian Forint)" : {
|
||||
|
||||
},
|
||||
"Iceland (Icelandic Króna)" : {
|
||||
|
||||
},
|
||||
"India (Indian Rupee)" : {
|
||||
|
||||
},
|
||||
"Indonesia (Indonesian Rupiah)" : {
|
||||
|
||||
},
|
||||
"Iran (Iranian Rial)" : {
|
||||
|
||||
},
|
||||
"Iran (Iranian Toman)" : {
|
||||
|
||||
},
|
||||
"Israel (Israeli New Shekel)" : {
|
||||
|
||||
},
|
||||
"Japan (Japanese Yen)" : {
|
||||
|
||||
},
|
||||
"Kenya (Kenyan Shilling)" : {
|
||||
|
||||
},
|
||||
"Kuwait (Kuwaiti Dinar)" : {
|
||||
|
||||
},
|
||||
"Last Updated" : {
|
||||
|
||||
|
@ -49,33 +133,132 @@
|
|||
},
|
||||
"Latest transaction" : {
|
||||
|
||||
},
|
||||
"Lebanon (Lebanese Pound)" : {
|
||||
|
||||
},
|
||||
"Malaysia (Malaysian Ringgit)" : {
|
||||
|
||||
},
|
||||
"Market" : {
|
||||
|
||||
},
|
||||
"Market Rate" : {
|
||||
|
||||
},
|
||||
"Mexico (Mexican Peso)" : {
|
||||
|
||||
},
|
||||
"Mozambique (Mozambican Metical)" : {
|
||||
|
||||
},
|
||||
"New Zealand (New Zealand Dollar)" : {
|
||||
|
||||
},
|
||||
"Next Block" : {
|
||||
|
||||
},
|
||||
"Nigeria (Nigerian Naira)" : {
|
||||
|
||||
},
|
||||
"Norway (Norwegian Krone)" : {
|
||||
|
||||
},
|
||||
"Oman (Omani Rial)" : {
|
||||
|
||||
},
|
||||
"Philippines (Philippine Peso)" : {
|
||||
|
||||
},
|
||||
"Poland (Polish Zloty)" : {
|
||||
|
||||
},
|
||||
"Price" : {
|
||||
|
||||
},
|
||||
"Qatar (Qatari Riyal)" : {
|
||||
|
||||
},
|
||||
"receive" : {
|
||||
|
||||
},
|
||||
"Romania (Romanian Leu)" : {
|
||||
|
||||
},
|
||||
"Russia (Russian Ruble)" : {
|
||||
|
||||
},
|
||||
"Sats/%@" : {
|
||||
|
||||
},
|
||||
"Saudi Arabia (Saudi Riyal)" : {
|
||||
|
||||
},
|
||||
"send" : {
|
||||
|
||||
},
|
||||
"Singapore (Singapore Dollar)" : {
|
||||
|
||||
},
|
||||
"Source: %@" : {
|
||||
|
||||
},
|
||||
"South Africa (South African Rand)" : {
|
||||
|
||||
},
|
||||
"South Korea (South Korean Won)" : {
|
||||
|
||||
},
|
||||
"Sri Lanka (Sri Lankan Rupee)" : {
|
||||
|
||||
},
|
||||
"Sweden (Swedish Krona)" : {
|
||||
|
||||
},
|
||||
"Switzerland (Swiss Franc)" : {
|
||||
|
||||
},
|
||||
"Taiwan (New Taiwan Dollar)" : {
|
||||
|
||||
},
|
||||
"Tanzania (Tanzanian Shilling)" : {
|
||||
|
||||
},
|
||||
"Thailand (Thai Baht)" : {
|
||||
|
||||
},
|
||||
"Turkey (Turkish Lira)" : {
|
||||
|
||||
},
|
||||
"Uganda (Ugandan Shilling)" : {
|
||||
|
||||
},
|
||||
"Ukraine (Ukrainian Hryvnia)" : {
|
||||
|
||||
},
|
||||
"United Arab Emirates (UAE Dirham)" : {
|
||||
|
||||
},
|
||||
"United Kingdom (British Pound)" : {
|
||||
|
||||
},
|
||||
"United States of America (US Dollar)" : {
|
||||
|
||||
},
|
||||
"Updated: %@" : {
|
||||
|
||||
},
|
||||
"Uruguay (Uruguayan Peso)" : {
|
||||
|
||||
},
|
||||
"Venezuela (Venezuelan Bolívar Fuerte)" : {
|
||||
|
||||
},
|
||||
"Venezuela (Venezuelan Bolívar Soberano)" : {
|
||||
|
||||
},
|
||||
"View the current Bitcoin market rate in your preferred fiat currency." : {
|
||||
|
||||
},
|
||||
"View the current Bitcoin market rate." : {
|
||||
|
||||
|
|
32
ios/Widgets/PriceWidget/CompactPriceView.swift
Normal file
32
ios/Widgets/PriceWidget/CompactPriceView.swift
Normal file
|
@ -0,0 +1,32 @@
|
|||
import SwiftUI
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct CompactPriceView: View {
|
||||
let price: String
|
||||
let lastUpdated: String
|
||||
let currencySymbol: String
|
||||
let dataSource: String
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .center, spacing: 16) {
|
||||
Text(price)
|
||||
.font(.title)
|
||||
.bold()
|
||||
.multilineTextAlignment(.center)
|
||||
.dynamicTypeSize(.large ... .accessibility5)
|
||||
.accessibilityLabel("Bitcoin price: \(price)")
|
||||
|
||||
VStack(alignment: .center, spacing: 4) {
|
||||
Text("\(currencySymbol)")
|
||||
Text("\(lastUpdated)")
|
||||
Text("\(dataSource)")
|
||||
}
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
.accessibilityElement(children: .combine)
|
||||
}
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
|
@ -1,76 +1,96 @@
|
|||
//
|
||||
// PriceIntent.swift
|
||||
// BlueWallet
|
||||
//
|
||||
|
||||
import AppIntents
|
||||
import SwiftUI
|
||||
|
||||
|
||||
@available(iOS 16.0, *)
|
||||
struct PriceIntent: AppIntent {
|
||||
// MARK: - Intent Metadata
|
||||
|
||||
static var title: LocalizedStringResource = "Market Rate"
|
||||
static var description = IntentDescription("View the current Bitcoin market rate.")
|
||||
static var description = IntentDescription("View the current Bitcoin market rate in your preferred fiat currency.")
|
||||
static var openAppWhenRun: Bool { false }
|
||||
|
||||
static var parameterSummary: some ParameterSummary {
|
||||
Summary("View the current Bitcoin market rate.")
|
||||
}
|
||||
|
||||
// MARK: - Parameters
|
||||
|
||||
@Parameter(
|
||||
title: "Currency"
|
||||
)
|
||||
var fiatCurrency: FiatUnitEnum?
|
||||
|
||||
@MainActor
|
||||
func perform() async throws -> some IntentResult & ReturnsValue<Double> & ProvidesDialog & ShowsSnippetView {
|
||||
let userPreferredCurrency = Currency.getUserPreferredCurrency()
|
||||
let currencyCode = userPreferredCurrency.uppercased()
|
||||
let dataSource = fiatUnit(currency: userPreferredCurrency)?.source ?? "Unknown Source"
|
||||
|
||||
if userPreferredCurrency != Currency.getLastSelectedCurrency() {
|
||||
Currency.saveNewSelectedCurrency()
|
||||
// Determine the fiat currency to use:
|
||||
// 1. UserDefaults in Shared Group
|
||||
// 2. Device's preferred currency
|
||||
// 3. Default to USD
|
||||
let selectedFiatCurrency: FiatUnitEnum
|
||||
|
||||
if let sharedCurrencyCode = getSharedCurrencyCode(),
|
||||
let fiat = FiatUnitEnum(rawValue: sharedCurrencyCode.uppercased()) {
|
||||
selectedFiatCurrency = fiat
|
||||
} else if let preferredCurrencyCode = Locale.current.currencyCode,
|
||||
let fiat = FiatUnitEnum(rawValue: preferredCurrencyCode.uppercased()) {
|
||||
selectedFiatCurrency = fiat
|
||||
} else {
|
||||
selectedFiatCurrency = .USD
|
||||
}
|
||||
|
||||
let dataSource = selectedFiatCurrency.source
|
||||
|
||||
enum Constants {
|
||||
static let defaultValue = "--"
|
||||
static let initialValue = 0.0
|
||||
}
|
||||
|
||||
var lastUpdated = Constants.defaultValue
|
||||
var resultValue: Double = Constants.initialValue
|
||||
|
||||
enum PriceIntentError: LocalizedError {
|
||||
case fetchFailed
|
||||
case invalidData
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .fetchFailed:
|
||||
return "Failed to fetch price data"
|
||||
case .invalidData:
|
||||
return "Received invalid price data"
|
||||
}
|
||||
}
|
||||
}
|
||||
var lastUpdated = "--"
|
||||
var priceDouble: Double = 0.0
|
||||
|
||||
do {
|
||||
guard let data = try await MarketAPI.fetchPrice(currency: userPreferredCurrency) else {
|
||||
throw PriceIntentError.fetchFailed
|
||||
guard let fetchedData = try await MarketAPI.fetchPrice(currency: selectedFiatCurrency.rawValue) else {
|
||||
throw NSError(
|
||||
domain: "PriceIntentErrorDomain",
|
||||
code: -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Failed to fetch price data."]
|
||||
)
|
||||
}
|
||||
|
||||
resultValue = data.rateDouble
|
||||
lastUpdated = formattedDate(from: data.lastUpdate)
|
||||
priceDouble = fetchedData.rateDouble
|
||||
lastUpdated = formattedDate(from: fetchedData.lastUpdate)
|
||||
|
||||
} catch {
|
||||
throw PriceIntentError.fetchFailed
|
||||
let errorView = CompactPriceView(
|
||||
price: "N/A",
|
||||
lastUpdated: "--",
|
||||
currencySymbol: getCurrencySymbol(for: selectedFiatCurrency.rawValue),
|
||||
dataSource: "Error fetching data"
|
||||
)
|
||||
|
||||
return .result(
|
||||
value: 0.0,
|
||||
dialog: "Failed to retrieve the Bitcoin market rate.",
|
||||
view: errorView
|
||||
)
|
||||
}
|
||||
|
||||
let formattedPrice = formatPrice(resultValue, currencyCode: currencyCode)
|
||||
|
||||
let formattedPrice = formatPrice(priceDouble, currencyCode: selectedFiatCurrency.rawValue)
|
||||
|
||||
let currencySymbol = getCurrencySymbol(for: selectedFiatCurrency.rawValue)
|
||||
|
||||
let view = CompactPriceView(
|
||||
price: formattedPrice,
|
||||
lastUpdated: lastUpdated,
|
||||
currencyCode: currencyCode,
|
||||
currencySymbol: currencySymbol,
|
||||
dataSource: dataSource
|
||||
)
|
||||
|
||||
return .result(
|
||||
value: resultValue,
|
||||
value: priceDouble,
|
||||
dialog: "Current Bitcoin Market Rate",
|
||||
view: view
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Helper Methods
|
||||
|
||||
private func formattedDate(from isoString: String?) -> String {
|
||||
guard let isoString = isoString else { return "--" }
|
||||
let isoFormatter = ISO8601DateFormatter()
|
||||
|
@ -82,13 +102,12 @@ struct PriceIntent: AppIntent {
|
|||
}
|
||||
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 price is a whole number
|
||||
if price.truncatingRemainder(dividingBy: 1) == 0 {
|
||||
formatter.maximumFractionDigits = 0
|
||||
|
@ -98,37 +117,22 @@ struct PriceIntent: AppIntent {
|
|||
formatter.minimumFractionDigits = 2
|
||||
}
|
||||
|
||||
return formatter.string(from: NSNumber(value: price)) ?? "--"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
.dynamicTypeSize(.large ... .accessibility5)
|
||||
.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)
|
||||
guard let formattedNumber = formatter.string(from: NSNumber(value: price)) else {
|
||||
return "\(price)"
|
||||
}
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
return formattedNumber
|
||||
}
|
||||
|
||||
private func getCurrencySymbol(for currencyCode: String) -> String {
|
||||
let formatter = NumberFormatter()
|
||||
formatter.numberStyle = .currency
|
||||
formatter.currencyCode = currencyCode
|
||||
return formatter.currencySymbol
|
||||
}
|
||||
|
||||
private func getSharedCurrencyCode() -> String? {
|
||||
let sharedDefaults = UserDefaults(suiteName: UserDefaultsGroupKey.GroupName.rawValue)
|
||||
return sharedDefaults?.string(forKey: "selectedFiatCurrency")
|
||||
}
|
||||
}
|
||||
|
|
255
ios/Widgets/Shared/FiatUnitEnum.swift
Normal file
255
ios/Widgets/Shared/FiatUnitEnum.swift
Normal file
|
@ -0,0 +1,255 @@
|
|||
import AppIntents
|
||||
|
||||
@available(iOS 16.0, *)
|
||||
enum FiatUnitEnum: String, AppEnum, CaseIterable, Identifiable, Codable {
|
||||
|
||||
var id: String { self.rawValue }
|
||||
|
||||
case AED
|
||||
case ARS
|
||||
case AUD
|
||||
case AWG
|
||||
case BHD
|
||||
case BRL
|
||||
case CAD
|
||||
case CHF
|
||||
case CLP
|
||||
case CNY
|
||||
case COP
|
||||
case CZK
|
||||
case DKK
|
||||
case EUR
|
||||
case GBP
|
||||
case HRK
|
||||
case HUF
|
||||
case IDR
|
||||
case ILS
|
||||
case INR
|
||||
case IRR
|
||||
case IRT
|
||||
case ISK
|
||||
case JPY
|
||||
case KES
|
||||
case KRW
|
||||
case KWD
|
||||
case LBP
|
||||
case LKR
|
||||
case MXN
|
||||
case MYR
|
||||
case MZN
|
||||
case NGN
|
||||
case NOK
|
||||
case NZD
|
||||
case OMR
|
||||
case PHP
|
||||
case PLN
|
||||
case QAR
|
||||
case RON
|
||||
case RUB
|
||||
case SAR
|
||||
case SEK
|
||||
case SGD
|
||||
case THB
|
||||
case TRY
|
||||
case TWD
|
||||
case TZS
|
||||
case UAH
|
||||
case UGX
|
||||
case USD
|
||||
case UYU
|
||||
case VEF
|
||||
case VES
|
||||
case XAF
|
||||
case ZAR
|
||||
case GHS
|
||||
|
||||
var code: String {
|
||||
return self.rawValue
|
||||
}
|
||||
|
||||
var source: String {
|
||||
switch self {
|
||||
case .AED:
|
||||
return "CoinGecko"
|
||||
case .ARS:
|
||||
return "Yadio"
|
||||
case .AUD:
|
||||
return "CoinGecko"
|
||||
case .AWG:
|
||||
return "CoinDesk"
|
||||
case .BHD:
|
||||
return "CoinGecko"
|
||||
case .BRL:
|
||||
return "CoinGecko"
|
||||
case .CAD:
|
||||
return "CoinGecko"
|
||||
case .CHF:
|
||||
return "CoinGecko"
|
||||
case .CLP:
|
||||
return "Yadio"
|
||||
case .CNY:
|
||||
return "Coinbase"
|
||||
case .COP:
|
||||
return "CoinDesk"
|
||||
case .CZK:
|
||||
return "CoinGecko"
|
||||
case .DKK:
|
||||
return "CoinGecko"
|
||||
case .EUR:
|
||||
return "Kraken"
|
||||
case .GBP:
|
||||
return "Kraken"
|
||||
case .HRK:
|
||||
return "CoinDesk"
|
||||
case .HUF:
|
||||
return "CoinGecko"
|
||||
case .IDR:
|
||||
return "CoinGecko"
|
||||
case .ILS:
|
||||
return "CoinGecko"
|
||||
case .INR:
|
||||
return "coinpaprika"
|
||||
case .IRR:
|
||||
return "Exir"
|
||||
case .IRT:
|
||||
return "Exir"
|
||||
case .ISK:
|
||||
return "CoinDesk"
|
||||
case .JPY:
|
||||
return "CoinGecko"
|
||||
case .KES:
|
||||
return "CoinDesk"
|
||||
case .KRW:
|
||||
return "CoinGecko"
|
||||
case .KWD:
|
||||
return "CoinGecko"
|
||||
case .LBP:
|
||||
return "YadioConvert"
|
||||
case .LKR:
|
||||
return "CoinGecko"
|
||||
case .MXN:
|
||||
return "CoinGecko"
|
||||
case .MYR:
|
||||
return "CoinGecko"
|
||||
case .MZN:
|
||||
return "CoinDesk"
|
||||
case .NGN:
|
||||
return "CoinGecko"
|
||||
case .NOK:
|
||||
return "CoinGecko"
|
||||
case .NZD:
|
||||
return "CoinGecko"
|
||||
case .OMR:
|
||||
return "CoinDesk"
|
||||
case .PHP:
|
||||
return "CoinGecko"
|
||||
case .PLN:
|
||||
return "CoinGecko"
|
||||
case .QAR:
|
||||
return "CoinDesk"
|
||||
case .RON:
|
||||
return "BNR"
|
||||
case .RUB:
|
||||
return "CoinGecko"
|
||||
case .SAR:
|
||||
return "CoinGecko"
|
||||
case .SEK:
|
||||
return "CoinGecko"
|
||||
case .SGD:
|
||||
return "CoinGecko"
|
||||
case .THB:
|
||||
return "CoinGecko"
|
||||
case .TRY:
|
||||
return "CoinGecko"
|
||||
case .TWD:
|
||||
return "CoinGecko"
|
||||
case .TZS:
|
||||
return "CoinDesk"
|
||||
case .UAH:
|
||||
return "CoinGecko"
|
||||
case .UGX:
|
||||
return "CoinDesk"
|
||||
case .USD:
|
||||
return "Kraken"
|
||||
case .UYU:
|
||||
return "CoinDesk"
|
||||
case .VEF:
|
||||
return "CoinGecko"
|
||||
case .VES:
|
||||
return "Yadio"
|
||||
case .XAF:
|
||||
return "CoinDesk"
|
||||
case .ZAR:
|
||||
return "CoinGecko"
|
||||
case .GHS:
|
||||
return "CoinDesk"
|
||||
}
|
||||
}
|
||||
|
||||
static var typeDisplayRepresentation: TypeDisplayRepresentation {
|
||||
TypeDisplayRepresentation(stringLiteral: "Currency")
|
||||
}
|
||||
|
||||
static var caseDisplayRepresentations: [FiatUnitEnum: DisplayRepresentation] {
|
||||
return [
|
||||
.AED: DisplayRepresentation(stringLiteral: "United Arab Emirates (UAE Dirham)"),
|
||||
.ARS: DisplayRepresentation(stringLiteral: "Argentina (Argentine Peso)"),
|
||||
.AUD: DisplayRepresentation(stringLiteral: "Australia (Australian Dollar)"),
|
||||
.AWG: DisplayRepresentation(stringLiteral: "Aruba (Aruban Florin)"),
|
||||
.BHD: DisplayRepresentation(stringLiteral: "Bahrain (Bahraini Dinar)"),
|
||||
.BRL: DisplayRepresentation(stringLiteral: "Brazil (Brazilian Real)"),
|
||||
.CAD: DisplayRepresentation(stringLiteral: "Canada (Canadian Dollar)"),
|
||||
.CHF: DisplayRepresentation(stringLiteral: "Switzerland (Swiss Franc)"),
|
||||
.CLP: DisplayRepresentation(stringLiteral: "Chile (Chilean Peso)"),
|
||||
.CNY: DisplayRepresentation(stringLiteral: "China (Chinese Yuan)"),
|
||||
.COP: DisplayRepresentation(stringLiteral: "Colombia (Colombian Peso)"),
|
||||
.CZK: DisplayRepresentation(stringLiteral: "Czech Republic (Czech Koruna)"),
|
||||
.DKK: DisplayRepresentation(stringLiteral: "Denmark (Danish Krone)"),
|
||||
.EUR: DisplayRepresentation(stringLiteral: "European Union (Euro)"),
|
||||
.GBP: DisplayRepresentation(stringLiteral: "United Kingdom (British Pound)"),
|
||||
.HRK: DisplayRepresentation(stringLiteral: "Croatia (Croatian Kuna)"),
|
||||
.HUF: DisplayRepresentation(stringLiteral: "Hungary (Hungarian Forint)"),
|
||||
.IDR: DisplayRepresentation(stringLiteral: "Indonesia (Indonesian Rupiah)"),
|
||||
.ILS: DisplayRepresentation(stringLiteral: "Israel (Israeli New Shekel)"),
|
||||
.INR: DisplayRepresentation(stringLiteral: "India (Indian Rupee)"),
|
||||
.IRR: DisplayRepresentation(stringLiteral: "Iran (Iranian Rial)"),
|
||||
.IRT: DisplayRepresentation(stringLiteral: "Iran (Iranian Toman)"),
|
||||
.ISK: DisplayRepresentation(stringLiteral: "Iceland (Icelandic Króna)"),
|
||||
.JPY: DisplayRepresentation(stringLiteral: "Japan (Japanese Yen)"),
|
||||
.KES: DisplayRepresentation(stringLiteral: "Kenya (Kenyan Shilling)"),
|
||||
.KRW: DisplayRepresentation(stringLiteral: "South Korea (South Korean Won)"),
|
||||
.KWD: DisplayRepresentation(stringLiteral: "Kuwait (Kuwaiti Dinar)"),
|
||||
.LBP: DisplayRepresentation(stringLiteral: "Lebanon (Lebanese Pound)"),
|
||||
.LKR: DisplayRepresentation(stringLiteral: "Sri Lanka (Sri Lankan Rupee)"),
|
||||
.MXN: DisplayRepresentation(stringLiteral: "Mexico (Mexican Peso)"),
|
||||
.MYR: DisplayRepresentation(stringLiteral: "Malaysia (Malaysian Ringgit)"),
|
||||
.MZN: DisplayRepresentation(stringLiteral: "Mozambique (Mozambican Metical)"),
|
||||
.NGN: DisplayRepresentation(stringLiteral: "Nigeria (Nigerian Naira)"),
|
||||
.NOK: DisplayRepresentation(stringLiteral: "Norway (Norwegian Krone)"),
|
||||
.NZD: DisplayRepresentation(stringLiteral: "New Zealand (New Zealand Dollar)"),
|
||||
.OMR: DisplayRepresentation(stringLiteral: "Oman (Omani Rial)"),
|
||||
.PHP: DisplayRepresentation(stringLiteral: "Philippines (Philippine Peso)"),
|
||||
.PLN: DisplayRepresentation(stringLiteral: "Poland (Polish Zloty)"),
|
||||
.QAR: DisplayRepresentation(stringLiteral: "Qatar (Qatari Riyal)"),
|
||||
.RON: DisplayRepresentation(stringLiteral: "Romania (Romanian Leu)"),
|
||||
.RUB: DisplayRepresentation(stringLiteral: "Russia (Russian Ruble)"),
|
||||
.SAR: DisplayRepresentation(stringLiteral: "Saudi Arabia (Saudi Riyal)"),
|
||||
.SEK: DisplayRepresentation(stringLiteral: "Sweden (Swedish Krona)"),
|
||||
.SGD: DisplayRepresentation(stringLiteral: "Singapore (Singapore Dollar)"),
|
||||
.THB: DisplayRepresentation(stringLiteral: "Thailand (Thai Baht)"),
|
||||
.TRY: DisplayRepresentation(stringLiteral: "Turkey (Turkish Lira)"),
|
||||
.TWD: DisplayRepresentation(stringLiteral: "Taiwan (New Taiwan Dollar)"),
|
||||
.TZS: DisplayRepresentation(stringLiteral: "Tanzania (Tanzanian Shilling)"),
|
||||
.UAH: DisplayRepresentation(stringLiteral: "Ukraine (Ukrainian Hryvnia)"),
|
||||
.UGX: DisplayRepresentation(stringLiteral: "Uganda (Ugandan Shilling)"),
|
||||
.USD: DisplayRepresentation(stringLiteral: "United States of America (US Dollar)"),
|
||||
.UYU: DisplayRepresentation(stringLiteral: "Uruguay (Uruguayan Peso)"),
|
||||
.VEF: DisplayRepresentation(stringLiteral: "Venezuela (Venezuelan Bolívar Fuerte)"),
|
||||
.VES: DisplayRepresentation(stringLiteral: "Venezuela (Venezuelan Bolívar Soberano)"),
|
||||
.XAF: DisplayRepresentation(stringLiteral: "Central African Republic (Central African Franc)"),
|
||||
.ZAR: DisplayRepresentation(stringLiteral: "South Africa (South African Rand)"),
|
||||
.GHS: DisplayRepresentation(stringLiteral: "Ghana (Ghanaian Cedi)"),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -16,29 +16,15 @@ struct WalletAppShortcuts: AppShortcutsProvider {
|
|||
AppShortcut(
|
||||
intent: PriceIntent(),
|
||||
phrases: [
|
||||
"Market Rate through \(.applicationName)",
|
||||
"Get the current Bitcoin market rate using \(.applicationName)",
|
||||
"What's the current Bitcoin rate with \(.applicationName)?",
|
||||
"Show me the current Bitcoin price via \(.applicationName)",
|
||||
"Retrieve Bitcoin rate from \(.applicationName)",
|
||||
"Current Bitcoin price fetched by \(.applicationName)",
|
||||
"Bitcoin rate now through \(.applicationName)",
|
||||
"Tell me the Bitcoin market rate using \(.applicationName)",
|
||||
"Bitcoin price today via \(.applicationName)",
|
||||
"How much is Bitcoin worth now with \(.applicationName)?",
|
||||
"Show Bitcoin rate fetched by \(.applicationName)",
|
||||
"Get today's Bitcoin price using \(.applicationName)",
|
||||
"What's Bitcoin worth now via \(.applicationName)?",
|
||||
"Bitcoin market rate fetched by \(.applicationName)",
|
||||
"Latest Bitcoin price retrieved by \(.applicationName)",
|
||||
"Provide the current Bitcoin rate using \(.applicationName)",
|
||||
"Fetch the latest Bitcoin price through \(.applicationName)",
|
||||
"Retrieve Bitcoin market rate using \(.applicationName)",
|
||||
"Display the current Bitcoin price via \(.applicationName)",
|
||||
"Show the Bitcoin rate fetched by \(.applicationName)"
|
||||
AppShortcutPhrase<PriceIntent>("Market rate for Bitcoin in \(\.$fiatCurrency) using BlueWallet"),
|
||||
AppShortcutPhrase<PriceIntent>("Get the current Bitcoin market rate in \(\.$fiatCurrency) with BlueWallet"),
|
||||
AppShortcutPhrase<PriceIntent>("What's the current Bitcoin rate in \(\.$fiatCurrency) using BlueWallet?"),
|
||||
AppShortcutPhrase<PriceIntent>("Show me the current Bitcoin price in \(\.$fiatCurrency) via BlueWallet"),
|
||||
AppShortcutPhrase<PriceIntent>("Retrieve Bitcoin rate in \(\.$fiatCurrency) from BlueWallet")
|
||||
],
|
||||
shortTitle: "Market Rate",
|
||||
systemImageName: "bitcoinsign.circle"
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue