diff --git a/Bitkit/Components/MoneyText.swift b/Bitkit/Components/MoneyText.swift
index 826f3168..ea2b1b34 100644
--- a/Bitkit/Components/MoneyText.swift
+++ b/Bitkit/Components/MoneyText.swift
@@ -51,8 +51,14 @@ struct MoneyText: View {
private var displayText: String {
if showSymbol {
let baseSymbol = unit == .bitcoin ? "₿" : fiatSymbol
- let symbolPart = prefix != nil ? "\(prefix!) \(baseSymbol)" : "\(baseSymbol)"
- return "\(symbolPart) \(formattedValue)"
+ let isSuffix = unit == .fiat && isFiatSymbolSuffix
+ if isSuffix {
+ let prefixPart = prefix != nil ? "\(prefix!) " : ""
+ return "\(prefixPart)\(formattedValue) \(baseSymbol)"
+ } else {
+ let symbolPart = prefix != nil ? "\(prefix!) \(baseSymbol)" : "\(baseSymbol)"
+ return "\(symbolPart) \(formattedValue)"
+ }
} else {
return prefix != nil ? "\(prefix!) \(formattedValue)" : formattedValue
}
@@ -118,6 +124,10 @@ extension MoneyText {
return converted.symbol
}
+ private var isFiatSymbolSuffix: Bool {
+ isSuffixSymbolCurrency(currency.selectedCurrency)
+ }
+
private var formattedValue: String {
if hideBalance {
return displayDots
diff --git a/Bitkit/Components/NumberPadTextField.swift b/Bitkit/Components/NumberPadTextField.swift
index f32c7f35..63c11e52 100644
--- a/Bitkit/Components/NumberPadTextField.swift
+++ b/Bitkit/Components/NumberPadTextField.swift
@@ -77,11 +77,15 @@ struct NumberPadTextField: View {
@ViewBuilder
private var primaryDisplayView: some View {
+ let isSuffix = currency.primaryDisplay == .fiat && isSuffixSymbolCurrency(currency.selectedCurrency)
+ let symbolText = currency.primaryDisplay == .bitcoin ? "₿" : currency.symbol
+
HStack(spacing: 6) {
- // Symbol
- Text(currency.primaryDisplay == .bitcoin ? "₿" : currency.symbol)
- .font(.custom(Fonts.extraBold, size: 44))
- .foregroundColor(.textSecondary)
+ if !isSuffix {
+ Text(symbolText)
+ .font(.custom(Fonts.extraBold, size: 44))
+ .foregroundColor(.textSecondary)
+ }
// Value and placeholder
(Text(viewModel.displayText)
@@ -89,6 +93,12 @@ struct NumberPadTextField: View {
+ Text(viewModel.getPlaceholder(currency: currency))
.foregroundColor(isFocused ? .textSecondary : .textPrimary))
.font(.custom(Fonts.black, size: 44))
+
+ if isSuffix {
+ Text(symbolText)
+ .font(.custom(Fonts.extraBold, size: 44))
+ .foregroundColor(.textSecondary)
+ }
}
}
}
diff --git a/Bitkit/Models/Currency.swift b/Bitkit/Models/Currency.swift
index 6e8a7eb8..464e2d24 100644
--- a/Bitkit/Models/Currency.swift
+++ b/Bitkit/Models/Currency.swift
@@ -40,6 +40,8 @@ struct ConvertedAmount {
let sats: UInt64
let btcValue: Decimal
+ var isSymbolSuffix: Bool { isSuffixSymbolCurrency(currency) }
+
init(value: Decimal, formatted: String, symbol: String, currency: String, flag: String, sats: UInt64) {
self.value = value
self.formatted = formatted
@@ -50,6 +52,11 @@ struct ConvertedAmount {
btcValue = Decimal(sats) / 100_000_000
}
+ func formattedWithSymbol(withSpace: Bool = false) -> String {
+ let separator = withSpace ? " " : ""
+ return isSymbolSuffix ? "\(formatted)\(separator)\(symbol)" : "\(symbol)\(separator)\(formatted)"
+ }
+
struct BitcoinDisplayComponents {
let symbol: String
let value: String
@@ -75,3 +82,23 @@ struct ConvertedAmount {
}
}
}
+
+func isSuffixSymbolCurrency(_ currencyCode: String) -> Bool {
+ suffixSymbolCurrencies.contains(currencyCode)
+}
+
+private let suffixSymbolCurrencies: Set = [
+ "BGN", // Bulgarian Lev (10,00 лв)
+ "CHF", // Swiss Franc (10.00 CHF)
+ "CZK", // Czech Koruna (10,00 Kč)
+ "DKK", // Danish Krone (10,00 kr)
+ "HRK", // Croatian Kuna (10,00 kn)
+ "HUF", // Hungarian Forint (10 000 Ft)
+ "ISK", // Icelandic Króna (10.000 kr)
+ "NOK", // Norwegian Krone (10,00 kr)
+ "PLN", // Polish Złoty (0,35 zł)
+ "RON", // Romanian Leu (10,00 lei)
+ "RUB", // Russian Ruble (10,00 ₽)
+ "SEK", // Swedish Krona (10,00 kr)
+ "TRY", // Turkish Lira (10,00 ₺)
+]
diff --git a/Bitkit/ViewModels/Widgets/WeatherViewModel.swift b/Bitkit/ViewModels/Widgets/WeatherViewModel.swift
index 7342519c..f25f70aa 100644
--- a/Bitkit/ViewModels/Widgets/WeatherViewModel.swift
+++ b/Bitkit/ViewModels/Widgets/WeatherViewModel.swift
@@ -166,7 +166,7 @@ class WeatherViewModel: ObservableObject {
throw AppError(message: "Currency conversion unavailable", debugMessage: "Failed to convert \(fee) satoshis to fiat currency")
}
- return "\(converted.symbol) \(converted.formatted)"
+ return converted.formattedWithSymbol(withSpace: true)
}
deinit {
diff --git a/Bitkit/Views/Wallets/Receive/ReceiveCjitConfirmation.swift b/Bitkit/Views/Wallets/Receive/ReceiveCjitConfirmation.swift
index 704823fe..7158683a 100644
--- a/Bitkit/Views/Wallets/Receive/ReceiveCjitConfirmation.swift
+++ b/Bitkit/Views/Wallets/Receive/ReceiveCjitConfirmation.swift
@@ -14,14 +14,14 @@ struct ReceiveCjitConfirmation: View {
guard let converted = currency.convert(sats: entry.networkFeeSat) else {
return String(entry.networkFeeSat)
}
- return "\(converted.symbol)\(converted.formatted)"
+ return converted.formattedWithSymbol()
}
private func formattedServiceFee() -> String {
guard let converted = currency.convert(sats: entry.serviceFeeSat) else {
return String(entry.serviceFeeSat)
}
- return "\(converted.symbol)\(converted.formatted)"
+ return converted.formattedWithSymbol()
}
var receiveAmount: Int {
diff --git a/Bitkit/Views/Wallets/Sheets/BoostSheet.swift b/Bitkit/Views/Wallets/Sheets/BoostSheet.swift
index 9ee5af76..41403cef 100644
--- a/Bitkit/Views/Wallets/Sheets/BoostSheet.swift
+++ b/Bitkit/Views/Wallets/Sheets/BoostSheet.swift
@@ -82,7 +82,7 @@ struct BoostSheet: View {
else {
return ""
}
- return "\(converted.symbol)\(converted.formatted)"
+ return converted.formattedWithSymbol()
}
var body: some View {
diff --git a/BitkitTests/CurrencyTests.swift b/BitkitTests/CurrencyTests.swift
new file mode 100644
index 00000000..43945eb9
--- /dev/null
+++ b/BitkitTests/CurrencyTests.swift
@@ -0,0 +1,114 @@
+@testable import Bitkit
+import XCTest
+
+final class CurrencyTests: XCTestCase {
+ // MARK: - isSuffixSymbolCurrency
+
+ func testIsSuffixSymbolCurrency_ReturnsTrueForPLN() {
+ XCTAssertTrue(isSuffixSymbolCurrency("PLN"))
+ }
+
+ func testIsSuffixSymbolCurrency_ReturnsTrueForCZK() {
+ XCTAssertTrue(isSuffixSymbolCurrency("CZK"))
+ }
+
+ func testIsSuffixSymbolCurrency_ReturnsTrueForSEK() {
+ XCTAssertTrue(isSuffixSymbolCurrency("SEK"))
+ }
+
+ func testIsSuffixSymbolCurrency_ReturnsTrueForCHF() {
+ XCTAssertTrue(isSuffixSymbolCurrency("CHF"))
+ }
+
+ func testIsSuffixSymbolCurrency_ReturnsFalseForUSD() {
+ XCTAssertFalse(isSuffixSymbolCurrency("USD"))
+ }
+
+ func testIsSuffixSymbolCurrency_ReturnsFalseForEUR() {
+ XCTAssertFalse(isSuffixSymbolCurrency("EUR"))
+ }
+
+ func testIsSuffixSymbolCurrency_ReturnsFalseForGBP() {
+ XCTAssertFalse(isSuffixSymbolCurrency("GBP"))
+ }
+
+ func testIsSuffixSymbolCurrency_ReturnsFalseForUnknownCurrency() {
+ XCTAssertFalse(isSuffixSymbolCurrency("XYZ"))
+ }
+
+ // MARK: - ConvertedAmount.isSymbolSuffix
+
+ func testConvertedAmount_IsSymbolSuffix_TrueForPLN() {
+ let converted = ConvertedAmount(
+ value: 0.35, formatted: "0.35", symbol: "zł",
+ currency: "PLN", flag: "🇵🇱", sats: 100
+ )
+ XCTAssertTrue(converted.isSymbolSuffix)
+ }
+
+ func testConvertedAmount_IsSymbolSuffix_FalseForUSD() {
+ let converted = ConvertedAmount(
+ value: 10.50, formatted: "10.50", symbol: "$",
+ currency: "USD", flag: "🇺🇸", sats: 1000
+ )
+ XCTAssertFalse(converted.isSymbolSuffix)
+ }
+
+ // MARK: - ConvertedAmount.formattedWithSymbol
+
+ func testFormattedWithSymbol_PrefixCurrency() {
+ let converted = ConvertedAmount(
+ value: 10.50, formatted: "10.50", symbol: "$",
+ currency: "USD", flag: "🇺🇸", sats: 1000
+ )
+ XCTAssertEqual(converted.formattedWithSymbol(), "$10.50")
+ }
+
+ func testFormattedWithSymbol_SuffixCurrency() {
+ let converted = ConvertedAmount(
+ value: 0.35, formatted: "0.35", symbol: "zł",
+ currency: "PLN", flag: "🇵🇱", sats: 100
+ )
+ XCTAssertEqual(converted.formattedWithSymbol(), "0.35zł")
+ }
+
+ func testFormattedWithSymbol_SuffixCurrencyCZK() {
+ let converted = ConvertedAmount(
+ value: 250.00, formatted: "250.00", symbol: "Kč",
+ currency: "CZK", flag: "🇨🇿", sats: 50000
+ )
+ XCTAssertEqual(converted.formattedWithSymbol(), "250.00Kč")
+ }
+
+ func testFormattedWithSymbol_PrefixCurrencyEUR() {
+ let converted = ConvertedAmount(
+ value: 10.00, formatted: "10.00", symbol: "€",
+ currency: "EUR", flag: "🇪🇺", sats: 1000
+ )
+ XCTAssertEqual(converted.formattedWithSymbol(), "€10.00")
+ }
+
+ func testFormattedWithSymbol_SuffixCurrencyCHF() {
+ let converted = ConvertedAmount(
+ value: 50.00, formatted: "50.00", symbol: "CHF",
+ currency: "CHF", flag: "🇨🇭", sats: 10000
+ )
+ XCTAssertEqual(converted.formattedWithSymbol(), "50.00CHF")
+ }
+
+ func testFormattedWithSymbol_PrefixCurrency_WithSpace() {
+ let converted = ConvertedAmount(
+ value: 10.50, formatted: "10.50", symbol: "$",
+ currency: "USD", flag: "🇺🇸", sats: 1000
+ )
+ XCTAssertEqual(converted.formattedWithSymbol(withSpace: true), "$ 10.50")
+ }
+
+ func testFormattedWithSymbol_SuffixCurrency_WithSpace() {
+ let converted = ConvertedAmount(
+ value: 0.35, formatted: "0.35", symbol: "zł",
+ currency: "PLN", flag: "🇵🇱", sats: 100
+ )
+ XCTAssertEqual(converted.formattedWithSymbol(withSpace: true), "0.35 zł")
+ }
+}