Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flags currency #32

Merged
merged 5 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Gem.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
481152C22B54F46800377C75 /* Gemstone in Frameworks */ = {isa = PBXBuildFile; productRef = 481152C12B54F46800377C75 /* Gemstone */; };
481152C82B566AC200377C75 /* Gemstone in Frameworks */ = {isa = PBXBuildFile; productRef = 481152C72B566AC200377C75 /* Gemstone */; };
487A27EB2B633FED00BEEADB /* GemstoneSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 487A27EA2B633FED00BEEADB /* GemstoneSwift */; };
8325539A2C0FB11C00C9CA0C /* CurrencySceneViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832553992C0FB11C00C9CA0C /* CurrencySceneViewModelTests.swift */; };
832553982C0F27F000C9CA0C /* ChartScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832553972C0F27F000C9CA0C /* ChartScene.swift */; };
C30952B4299C39D70004C0F9 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = C30952B3299C39D70004C0F9 /* App.swift */; };
C30952B8299C39D80004C0F9 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C30952B7299C39D80004C0F9 /* Images.xcassets */; };
Expand Down Expand Up @@ -250,6 +251,7 @@

/* Begin PBXFileReference section */
487A27E82B632CCE00BEEADB /* Gemstone */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Gemstone; sourceTree = "<group>"; };
832553992C0FB11C00C9CA0C /* CurrencySceneViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencySceneViewModelTests.swift; sourceTree = "<group>"; };
832553972C0F27F000C9CA0C /* ChartScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartScene.swift; sourceTree = "<group>"; };
C30952B0299C39D70004C0F9 /* Gem.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Gem.app; sourceTree = BUILT_PRODUCTS_DIR; };
C30952B3299C39D70004C0F9 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -531,6 +533,22 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
8325539B2C0FB22000C9CA0C /* Settings */ = {
isa = PBXGroup;
children = (
8325539C2C0FB23500C9CA0C /* ViewModels */,
);
path = Settings;
sourceTree = "<group>";
};
8325539C2C0FB23500C9CA0C /* ViewModels */ = {
isa = PBXGroup;
children = (
832553992C0FB11C00C9CA0C /* CurrencySceneViewModelTests.swift */,
);
path = ViewModels;
sourceTree = "<group>";
};
832553962C0F27D300C9CA0C /* Scenes */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -594,6 +612,7 @@
C30952C4299C39D80004C0F9 /* GemTests */ = {
isa = PBXGroup;
children = (
8325539B2C0FB22000C9CA0C /* Settings */,
D8A1F8832B17F8E900B15F54 /* Core */,
C3549B3229C4395B00B4BE01 /* Assets */,
C3549B2E29C42E6C00B4BE01 /* Wallet */,
Expand Down Expand Up @@ -1855,6 +1874,7 @@
C30952C6299C39D80004C0F9 /* walletTests.swift in Sources */,
C3A7CB9929D35EC200431341 /* WalletSceneViewModelTests.swift in Sources */,
C3A7CB9729D3569C00431341 /* PriceViewModelTests.swift in Sources */,
8325539A2C0FB11C00C9CA0C /* CurrencySceneViewModelTests.swift in Sources */,
C3549B3529C4396A00B4BE01 /* AssetViewModelTests.swift in Sources */,
C3549B3129C42E8F00B4BE01 /* AssetListViewModelTests.swift in Sources */,
);
Expand Down
8 changes: 3 additions & 5 deletions Gem/Settings/Scenes/CurrencyScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ struct CurrencyScene: View {
}
}

//struct CurrencyScene_Previews: PreviewProvider {
// static var previews: some View {
// CurrencyScene()
// }
//}
#Preview {
CurrencyScene(model: .init())
}
2 changes: 1 addition & 1 deletion Gem/Settings/Scenes/SettingsScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ struct SettingsScene: View {
ListItemView(title: Localized.Settings.Notifications.title, image: Image(.settingsNotifications))
}
NavigationLink(value: Scenes.Currency()) {
ListItemView(title: Localized.Settings.currency, subtitle: model.currencyModel.currency, image: Image(.settingsCurrency))
ListItemView(title: Localized.Settings.currency, subtitle: model.currencyValue, image: Image(.settingsCurrency))
}
NavigationLink(value: Scenes.Chains()) {
ListItemView(title: Localized.Settings.Networks.title, image: Image(.settingsNetworks))
Expand Down
85 changes: 77 additions & 8 deletions Gem/Settings/ViewModels/CurrencySceneViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,30 @@ import Components
import Store

class CurrencySceneViewModel: ObservableObject {

let preferences: Preferences

@Published var currency: String {
didSet {
preferences.currency = currency
}
}

init(
preferences: Preferences = .standard
) {
self.currency = preferences.currency
self.preferences = preferences
}

var title: String {
return Localized.Settings.currency
}


var emojiFlag: String? {
Locale.Currency.flag(for: currency)
}

var defaultCurrencies: [String] {
return [
Currency.usd.rawValue,
Expand All @@ -38,14 +42,14 @@ class CurrencySceneViewModel: ObservableObject {
currency,
]
}

var recommendedCurrencies: [Locale.Currency] {
let values = defaultCurrencies.map {
Locale.Currency($0)
}
return ([Locale.current.currency] + values).compactMap { $0 }.unique()
}

var list: [ListItemValueSection<String>] {
return [
ListItemValueSection(
Expand All @@ -66,6 +70,71 @@ class CurrencySceneViewModel: ObservableObject {

extension Locale.Currency {
var title: String {
return String(format: "%@ - %@", identifier, Locale.current.localizedString(forCurrencyCode: identifier) ?? .empty)
let localizedCurrencyId = Locale.current.localizedString(forCurrencyCode: identifier) ?? .empty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add unit test for this one? to make sure we properly present the title

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add

let currencyIdenifier = identifier

if let emojiFlag = emojiFlag {
return "\(emojiFlag) \(currencyIdenifier) - \(localizedCurrencyId)"
} else {
return "\(currencyIdenifier) - \(localizedCurrencyId)"
}
}

private var emojiFlag: String? {
return Self.flag(for: identifier)
}

fileprivate static func flag(for identifier: String) -> String? {
return Self.emojiFlags[identifier]
}

fileprivate static let emojiFlags: [String: String] = [
"MXN": "🇲🇽",
"CHF": "🇨🇭",
"CNY": "🇨🇳",
"THB": "🇹🇭",
"HUF": "🇭🇺",
"AUD": "🇦🇺",
"IDR": "🇮🇩",
"RUB": "🇷🇺",
"ZAR": "🇿🇦",
"EUR": "🇪🇺",
"NZD": "🇳🇿",
"SAR": "🇸🇦",
"SGD": "🇸🇬",
"BMD": "🇧🇲",
"KWD": "🇰🇼",
"HKD": "🇭🇰",
"JPY": "🇯🇵",
"GBP": "🇬🇧",
"DKK": "🇩🇰",
"KRW": "🇰🇷",
"PHP": "🇵🇭",
"CLP": "🇨🇱",
"TWD": "🇹🇼",
"PKR": "🇵🇰",
"BRL": "🇧🇷",
"CAD": "🇨🇦",
"BHD": "🇧🇭",
"MMK": "🇲🇲",
"VEF": "🇻🇪",
"VND": "🇻🇳",
"CZK": "🇨🇿",
"TRY": "🇹🇷",
"INR": "🇮🇳",
"ARS": "🇦🇷",
"BDT": "🇧🇩",
"NOK": "🇳🇴",
"USD": "🇺🇸",
"LKR": "🇱🇰",
"ILS": "🇮🇱",
"PLN": "🇵🇱",
"NGN": "🇳🇬",
"UAH": "🇺🇦",
"XDR": "🏳️",
"MYR": "🇲🇾",
"AED": "🇦🇪",
"SEK": "🇸🇪",
"BTC": "₿"
]
}
11 changes: 10 additions & 1 deletion Gem/Settings/ViewModels/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ class SettingsViewModel: ObservableObject {
var walletsText: String {
"\(keystore.wallets.count)"
}


var currencyValue: String {
let currentCurrency = currencyModel.currency

if let currentFlag = currencyModel.emojiFlag {
return "\(currentFlag) \(currentCurrency)"
}
return currentCurrency
}

var versionText: String {
return String(format: "%@ (%d)", Bundle.main.releaseVersionNumber, Bundle.main.buildVersionNumber)
}
Expand Down
56 changes: 56 additions & 0 deletions GemTests/Settings/ViewModels/CurrencySceneViewModelTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import XCTest
import Primitives
@testable import Gem

final class CurrencySceneViewModelTests: XCTestCase {
func testCurrencyText() {
let usdCurrency = CurrencySceneViewModelTests.nativeCurrency(currency: .usd)

let usdCurrencyTitle = usdCurrency?.title
let mockUsdCurrencyTitle = "🇺🇸 USD - US Dollar"
XCTAssertEqual(usdCurrencyTitle, mockUsdCurrencyTitle)

let uahCurrency = CurrencySceneViewModelTests.nativeCurrency(identifier: "UAH")
let uahCurrencyTitle = uahCurrency?.title

let mockUAHCurrencyTitle = "🇺🇦 UAH - Ukrainian Hryvnia"
XCTAssertEqual(uahCurrencyTitle, mockUAHCurrencyTitle)
}

func testCurrencyTextWithXDREmojiFlag() {
let xdrCurrency = CurrencySceneViewModelTests.nativeCurrency(identifier: "XDR")
let xdrCurrencyTitle = xdrCurrency?.title

let mockXdrCurrencyTitle = "🏳️ XDR - Special Drawing Rights"
XCTAssertEqual(xdrCurrencyTitle, mockXdrCurrencyTitle)
}

func testUnknownCurrency() {
let unknownCurrency = CurrencySceneViewModelTests.nativeCurrency(identifier: "XYZ")
let unknownCurrencyTitle = unknownCurrency?.title

// unknown currency not supported, it's managed by Currency raw vlaue from primitives
XCTAssertEqual(unknownCurrencyTitle, nil)
}

func testBitcoinCurrency() {
let btcCurrency = CurrencySceneViewModelTests.nativeCurrency(identifier: "BTC")
let btcCurrencyTitle = btcCurrency?.title

/* not supported yet
let mockBtcCurrencyTitle = "₿ BTC - Bitcoin"
XCTAssertEqual(btcCurrencyTitle, mockBtcCurrencyTitle)
*/
XCTAssertEqual(btcCurrencyTitle, nil)
}
}

extension CurrencySceneViewModelTests {
static func nativeCurrency(identifier: String.ID) -> Locale.Currency? {
Currency.nativeCurrencies.first(where: { $0.identifier == identifier })
}

static func nativeCurrency(currency: Currency) -> Locale.Currency? {
Currency.nativeCurrencies.first(where: { $0.identifier == currency.rawValue })
}
}
Loading