Mercurial > public > simoleon
changeset 160:0c589138a6f3
Implement Conversion Box
author | Dennis Concepcion Martin <dennisconcepcionmartin@gmail.com> |
---|---|
date | Sun, 29 Aug 2021 19:04:34 +0100 |
parents | 35628bac01f5 |
children | 3913aff613e8 |
files | Simoleon.xcodeproj/project.pbxproj Simoleon/ContentView.swift Simoleon/ConversionView.swift Simoleon/Helpers/ErrorHandling.swift Simoleon/Helpers/FileHelper.swift Simoleon/Helpers/NetworkHelper.swift Simoleon/Info.plist Simoleon/Models/CurrencyPair.swift Simoleon/Models/CurrencyPairModel.swift Simoleon/Models/CurrencyQuoteModel.swift Simoleon/SimoleonApp.swift Simoleon/UI/ConversionBox.swift Simoleon/UI/ConversionTextfield.swift Simoleon/UI/CurrencyButton.swift Simoleon/UI/CurrencyList.swift Simoleon/UI/CurrencySelector.swift Simoleon/UI/FavoriteButton.swift Simoleon/UI/Flag.swift SimoleonTests/SimoleonTests.swift |
diffstat | 19 files changed, 210 insertions(+), 194 deletions(-) [+] |
line wrap: on
line diff
--- a/Simoleon.xcodeproj/project.pbxproj Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon.xcodeproj/project.pbxproj Sun Aug 29 19:04:34 2021 +0100 @@ -15,11 +15,12 @@ 9522CD9D26CED2E100DD9D03 /* ErrorHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9522CD9C26CED2E100DD9D03 /* ErrorHandling.swift */; }; 9531D44226D8E4CF00665D2A /* SimoleonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9531D44126D8E4CF00665D2A /* SimoleonTests.swift */; }; 953B8B1726D3A970003CF530 /* CurrencyDetailsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 953B8B1626D3A970003CF530 /* CurrencyDetailsModel.swift */; }; + 9547423526DBE56600415B3F /* ConversionTextfield.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9547423426DBE56600415B3F /* ConversionTextfield.swift */; }; 95561E3F26AF25EF00CCB543 /* SubscriptionFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95561E3E26AF25EF00CCB543 /* SubscriptionFeature.swift */; }; 95562D4D26A8962A0047E778 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95562D4C26A8962A0047E778 /* StoreKit.framework */; }; 95562D5226A8AEF60047E778 /* Purchases in Frameworks */ = {isa = PBXBuildFile; productRef = 95562D5126A8AEF60047E778 /* Purchases */; }; 957065E226A5FE0400523E68 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957065E126A5FE0400523E68 /* SettingsView.swift */; }; - 957DCF3326D7ADEA00BCAB1E /* CurrencyPairModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957DCF3226D7ADEA00BCAB1E /* CurrencyPairModel.swift */; }; + 957DCF3326D7ADEA00BCAB1E /* CurrencyPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957DCF3226D7ADEA00BCAB1E /* CurrencyPair.swift */; }; 95851CE326D4DAAE004ADA79 /* CurrencyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95851CE226D4DAAE004ADA79 /* CurrencyButton.swift */; }; 95851CE526D4DB4C004ADA79 /* Flag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95851CE426D4DB4C004ADA79 /* Flag.swift */; }; 9585BB1426A6B7F400E3193E /* NetworkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9585BB1326A6B7F400E3193E /* NetworkHelper.swift */; }; @@ -119,11 +120,12 @@ 9531D44126D8E4CF00665D2A /* SimoleonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimoleonTests.swift; sourceTree = "<group>"; }; 9531D44326D8E4CF00665D2A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 953B8B1626D3A970003CF530 /* CurrencyDetailsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyDetailsModel.swift; sourceTree = "<group>"; }; + 9547423426DBE56600415B3F /* ConversionTextfield.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversionTextfield.swift; sourceTree = "<group>"; }; 95561E3E26AF25EF00CCB543 /* SubscriptionFeature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionFeature.swift; sourceTree = "<group>"; }; 95562D4C26A8962A0047E778 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; 956088B526B9307600A4FD6C /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = "<group>"; }; 957065E126A5FE0400523E68 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; }; - 957DCF3226D7ADEA00BCAB1E /* CurrencyPairModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyPairModel.swift; sourceTree = "<group>"; }; + 957DCF3226D7ADEA00BCAB1E /* CurrencyPair.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyPair.swift; sourceTree = "<group>"; }; 95851CE226D4DAAE004ADA79 /* CurrencyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyButton.swift; sourceTree = "<group>"; }; 95851CE426D4DB4C004ADA79 /* Flag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Flag.swift; sourceTree = "<group>"; }; 9585BB0F26A6B58500E3193E /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; }; @@ -257,7 +259,7 @@ 95AC820626DAA3ED00CD5C3F /* FavoritePair+CoreDataProperties.swift */, 95AEBCA226A0900E00613729 /* CurrencyQuoteModel.swift */, 953B8B1626D3A970003CF530 /* CurrencyDetailsModel.swift */, - 957DCF3226D7ADEA00BCAB1E /* CurrencyPairModel.swift */, + 957DCF3226D7ADEA00BCAB1E /* CurrencyPair.swift */, ); path = Models; sourceTree = "<group>"; @@ -399,6 +401,7 @@ 95CE6A3526D50B7700D9DCBD /* CurrencyList.swift */, 95C5179826A5EC9F00BC2B24 /* FavoriteButton.swift */, 95B54F4926A4A450001DC0D8 /* ConversionBox.swift */, + 9547423426DBE56600415B3F /* ConversionTextfield.swift */, 95AEBC9C26A04D4600613729 /* CurrencyRow.swift */, 95851CE426D4DB4C004ADA79 /* Flag.swift */, 95B54F5026A4ACAC001DC0D8 /* Sidebar.swift */, @@ -708,7 +711,7 @@ 95D8C8D126A9BC6200BCC188 /* LockedCurrencyPicker.swift in Sources */, 95C517A126A5F6C000BC2B24 /* ResignKeyboard.swift in Sources */, 95CE6A3626D50B7700D9DCBD /* CurrencyList.swift in Sources */, - 957DCF3326D7ADEA00BCAB1E /* CurrencyPairModel.swift in Sources */, + 957DCF3326D7ADEA00BCAB1E /* CurrencyPair.swift in Sources */, 95AEBC9D26A04D4600613729 /* CurrencyRow.swift in Sources */, 95AEBCA326A0900E00613729 /* CurrencyQuoteModel.swift in Sources */, 9585BB1426A6B7F400E3193E /* NetworkHelper.swift in Sources */, @@ -718,6 +721,7 @@ 953B8B1726D3A970003CF530 /* CurrencyDetailsModel.swift in Sources */, 95C5179126A5DC8E00BC2B24 /* ConditionalWrapper.swift in Sources */, 95B54F5126A4ACAC001DC0D8 /* Sidebar.swift in Sources */, + 9547423526DBE56600415B3F /* ConversionTextfield.swift in Sources */, 95561E3F26AF25EF00CCB543 /* SubscriptionFeature.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0;
--- a/Simoleon/ContentView.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/ContentView.swift Sun Aug 29 19:04:34 2021 +0100 @@ -15,18 +15,17 @@ } @ViewBuilder var adjustedView: some View { - let currencyPair = CurrencyPairModel(baseSymbol: "USD", quoteSymbol: "EUR") // MARK: - iPad if UIDevice.current.userInterfaceIdiom == .pad { NavigationView { // Sidebar() - ConversionView(currencyPair: currencyPair) + ConversionView() } } else { // MARK: - iPhone TabView(selection: $tab) { - ConversionView(currencyPair: currencyPair) + ConversionView() .tabItem { Label("Convert", systemImage: "arrow.counterclockwise.circle") }
--- a/Simoleon/ConversionView.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/ConversionView.swift Sun Aug 29 19:04:34 2021 +0100 @@ -10,62 +10,31 @@ struct ConversionView: View { var showNavigationView: Bool? - @State var currencyPair: CurrencyPairModel - - // Conversion - @State private var showingConversion = false - @State private var amountIsEditing = false - @State private var amountToConvert = "" - @State private var price: Double = 0 + @StateObject var currencyPair = CurrencyPair() var body: some View { ScrollView(showsIndicators: false) { - VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 20) { HStack { CurrencySelector(currencyPair: currencyPair) FavoriteButton(currencyPair: currencyPair) } + + ConversionBox(currencyPair: currencyPair) + .padding(.top) } .padding() } - .onAppear(perform: createUrlAndRequest) .navigationTitle("Convert") - .toolbar { - ToolbarItem(placement: .navigationBarTrailing) { - if amountIsEditing { - Button(action: { - UIApplication.shared.dismissKeyboard() - amountIsEditing = false - }) { - Text("Done") - } - } - } - } .if(UIDevice.current.userInterfaceIdiom == .phone && showNavigationView ?? true) { content in NavigationView { content } } } - - private func createUrlAndRequest() { - showingConversion = false - let baseUrl = readConfigVariable(withKey: "API_URL")! - let apiKey = readConfigVariable(withKey: "API_KEY")! - let currencyPair = "\(currencyPair.baseSymbol)/\(currencyPair.quoteSymbol)" - let url = "\(baseUrl)quotes?pairs=\(currencyPair)&api_key=\(apiKey)" - - httpRequest(url: url, model: [CurrencyQuoteModel].self) { response in - if let price = response.first?.price { - self.price = price - showingConversion = true - } - } - } } struct ConversionView_Previews: PreviewProvider { static var previews: some View { - ConversionView(showNavigationView: true, currencyPair: CurrencyPairModel(baseSymbol: "USD", quoteSymbol: "EUR")) + ConversionView(showNavigationView: true) } }
--- a/Simoleon/Helpers/ErrorHandling.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/Helpers/ErrorHandling.swift Sun Aug 29 19:04:34 2021 +0100 @@ -13,4 +13,8 @@ case loadFailed(cause: String) case parseFailed(cause: String) } + + enum Networking: Error { + case invalidURL + } }
--- a/Simoleon/Helpers/FileHelper.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/Helpers/FileHelper.swift Sun Aug 29 19:04:34 2021 +0100 @@ -7,10 +7,8 @@ import Foundation -/* - Decode and read json file - */ -func read<T: Decodable>(json filename: String) throws -> T { + +func readJson<T: Decodable>(from filename: String) throws -> T { let data: Data guard let file = Bundle.main.url(forResource: filename, withExtension: nil) @@ -32,10 +30,7 @@ } } -/* - Read configuration variables from Config.xconfig - */ -func readConfigVariable(withKey: String) -> String? { +func readConfig(withKey: String) -> String? { return (Bundle.main.infoDictionary?[withKey] as? String)? .replacingOccurrences(of: "\\", with: "") }
--- a/Simoleon/Helpers/NetworkHelper.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/Helpers/NetworkHelper.swift Sun Aug 29 19:04:34 2021 +0100 @@ -7,32 +7,29 @@ import Foundation -// MARK: - HTTP Request -func httpRequest<T: Decodable>(url: String, model: T.Type, completion: @escaping (_ result: T) -> Void) { - - // We take some model data T.Type - guard let url = URL(string: url) else { - print("Invalid URL") - return +class NetworkHelper { + func httpRequest<T: Decodable>(url: String, model: T.Type, completion: @escaping (_ result: T) -> Void) throws { + // We take some model data T.Type + guard let url = URL(string: url) else { throw ErrorHandling.Networking.invalidURL } + + let request = URLRequest(url: url) + URLSession.shared.dataTask(with: request) { data, response, error in + if let data = data { + do { + // Decode response with the model passed + let decodedResponse = try JSONDecoder().decode(model, from: data) + DispatchQueue.main.async { + completion(decodedResponse) + } + return + } catch { + // Return error regarding the escaping code + print(error) + } + } + // Error with the request + print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")") + } + .resume() } - - let request = URLRequest(url: url) - URLSession.shared.dataTask(with: request) { data, response, error in - if let data = data { - do { - // Decode response with the model passed - let decodedResponse = try JSONDecoder().decode(model, from: data) - DispatchQueue.main.async { - completion(decodedResponse) - } - return - } catch { - // Return error regarding the escaping code - print(error) - } - } - // Error with the request - print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")") - } - .resume() }
--- a/Simoleon/Info.plist Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/Info.plist Sun Aug 29 19:04:34 2021 +0100 @@ -4,8 +4,6 @@ <dict> <key>API_KEY</key> <string>$(API_KEY)</string> - <key>API_URL</key> - <string>$(API_URL)</string> <key>CFBundleDevelopmentRegion</key> <string>$(DEVELOPMENT_LANGUAGE)</string> <key>CFBundleDisplayName</key>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/Models/CurrencyPair.swift Sun Aug 29 19:04:34 2021 +0100 @@ -0,0 +1,18 @@ +// +// CurrencyPair.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 26/8/21. +// + +import Foundation + +class CurrencyPair: ObservableObject { + /* + Forex pair -> XXX/YYY + Where XXX is the base currency, and YYY the quote currency + */ + + @Published var baseSymbol = "USD" + @Published var quoteSymbol = "EUR" +}
--- a/Simoleon/Models/CurrencyPairModel.swift Sat Aug 28 19:18:50 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -// -// CurrencyPairModel.swift -// Simoleon -// -// Created by Dennis Concepción Martín on 26/8/21. -// - -import Foundation - -struct CurrencyPairModel { - /* - Forex pair -> XXX/YYY - Where XXX is the base currency, and YYY the quote currency - */ - - var baseSymbol: String - var quoteSymbol: String -}
--- a/Simoleon/Models/CurrencyQuoteModel.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/Models/CurrencyQuoteModel.swift Sun Aug 29 19:04:34 2021 +0100 @@ -8,14 +8,14 @@ import Foundation struct CurrencyQuoteModel: Codable, Hashable { - var symbol: String? + var pair: String? var price: Double? var bid: Double? var ask: Double? var timeStamp: Int? private enum CodingKeys: String, CodingKey { - case symbol = "s" + case pair = "s" case price = "p" case bid = "b" case ask = "a"
--- a/Simoleon/SimoleonApp.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/SimoleonApp.swift Sun Aug 29 19:04:34 2021 +0100 @@ -14,7 +14,7 @@ let persistenceController = PersistenceController.shared init() { - let apiKey = readConfigVariable(withKey: "PURCHASES_KEY")! + let apiKey = readConfig(withKey: "PURCHASES_KEY")! Purchases.configure(withAPIKey: apiKey) }
--- a/Simoleon/UI/ConversionBox.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/UI/ConversionBox.swift Sun Aug 29 19:04:34 2021 +0100 @@ -1,83 +1,95 @@ -//// -//// ConversionBox.swift -//// Simoleon -//// -//// Created by Dennis Concepción Martín on 18/07/2021. -//// -// -//import SwiftUI // -//struct ConversionBox: View { -// var currencyDetails: CurrencyDetailsModel -// @State var currencyPair: CurrencyPairModel -// -// var body: some View { -// VStack(alignment: .leading) { -// Text("\(baseName) (\(currencyPair.baseSymbol))") -// .font(.callout) -// .fontWeight(.semibold) -// .padding(.top, 40) -// -// ZStack(alignment: .trailing) { -// TextField("Enter amount", text: $amount) { startedEditing in -// if startedEditing { -// withAnimation { -// amountIsEditing = true -// } -// } -// } -// onCommit: { -// withAnimation { -// amountIsEditing = false -// } -// } -// .keyboardType(.decimalPad) -// .font(Font.title.weight(.semibold)) -// .lineLimit(1) -// .accessibilityIdentifier("ConversionTextField") -// } -// -// Divider() +// ConversionBox.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 18/07/2021. // -// let quoteName = currencyDetails[currencyPair.quoteSymbol]!.name -// Text("\(quoteName) (\(currencyPair.quoteSymbol))") -// .font(.callout) -// .fontWeight(.semibold) -// .padding(.top, 10) -// -// if showingConversion { -// Text("\(makeConversion(), specifier: "%.2f")") -// .font(Font.title.weight(.semibold)) -// .lineLimit(1) -// .padding(.top, 5) -// } else { -// ProgressView() -// .padding(.top, 5) -// } -// } -// .onAppear(perform: request) -// } -// -// /* -// if the amount can be converted to Double: -// * Return amount -// else: -// * Return zero -// */ -// func makeConversion() -> Double { -// if let amountToConvert = Double(amount) { -// return amountToConvert * price // Conversion -// } else { -// return 0 -// } -// } -//} -// -// -//struct ConversionBox_Previews: PreviewProvider { -// static var previews: some View { -// let fileController = File() -// let currencyDetails: [String: CurrencyDetailsModel] = try! fileController.read(json: "CurrencyDetails.json") -// ConversionBox(currencyPair: CurrencyPair(), currencyDetails: currencyDetails) -// } -//} + +import SwiftUI + +struct ConversionBox: View { + @ObservedObject var currencyPair: CurrencyPair + @State private var amount = "" + @State private var isEditing = false + @State private var showingConversion = false + @State private var currencyQuote = CurrencyQuoteModel() + @State private var showingAlert = false + + let networkHelper = NetworkHelper() + let currencyDetails: [String: CurrencyModel] = try! readJson(from: "Currencies.json") + + var body: some View { + VStack(alignment: .leading) { + let baseCurrencyName = currencyDetails[currencyPair.baseSymbol]!.name + Text("\(baseCurrencyName) (\(currencyPair.baseSymbol))") + .font(.callout) + .fontWeight(.semibold) + + ConversionTextfield(amount: $amount, isEditing: $isEditing) + Divider() + + let quoteCurrencyName = currencyDetails[currencyPair.quoteSymbol]!.name + Text("\(quoteCurrencyName) (\(currencyPair.quoteSymbol))") + .font(.callout) + .fontWeight(.semibold) + + if showingConversion { + let conversion = convert() + Text("\(conversion, specifier: "%.2f")") + .font(Font.title.weight(.semibold)) + .lineLimit(1) + } else { + ProgressView() + } + } + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + if isEditing { + Button(action: { + UIApplication.shared.dismissKeyboard() + isEditing = false + }) { + Text("Done") + } + } + } + } + + .onAppear { + showingConversion = false + let pair = "\(currencyPair.baseSymbol)/\(currencyPair.quoteSymbol)" + let apiKey = readConfig(withKey: "API_KEY")! + let url = "https://api.1forge.com/quotes?pairs=\(pair)&api_key=\(apiKey)" + try? networkHelper.httpRequest(url: url, model: [CurrencyQuoteModel].self) { response in + if let currencyQuote = response.first { + self.currencyQuote = currencyQuote + } else { + showingAlert = true + } + + showingConversion = true + } + } + .alert(isPresented: $showingAlert) { + Alert( + title: Text("Currencies not supported."), + message: Text("Currently, we are unable to convert from \(currencyPair.baseSymbol) to \(currencyPair.quoteSymbol)."), + dismissButton: .default(Text("Dismiss") + ) + ) + } + } + + private func convert() -> Double { + guard let amount = Double(amount) else { return 0 } + guard let price = currencyQuote.price else { return 0 } + + return amount * price + } +} + +struct ConversionBox_Previews: PreviewProvider { + static var previews: some View { + ConversionBox(currencyPair: CurrencyPair()) + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/UI/ConversionTextfield.swift Sun Aug 29 19:04:34 2021 +0100 @@ -0,0 +1,39 @@ +// +// ConversionTextfield.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 29/8/21. +// + +import SwiftUI + +struct ConversionTextfield: View { + @Binding var amount: String + @Binding var isEditing: Bool + + var body: some View { + ZStack { + TextField("Enter amount", text: $amount) { startedEditing in + if startedEditing { + withAnimation { + isEditing = true + } + } + } + onCommit: { + withAnimation { + isEditing = false + } + } + .keyboardType(.decimalPad) + .font(Font.title.weight(.semibold)) + .lineLimit(1) + } + } +} + +struct ConversionTextfield_Previews: PreviewProvider { + static var previews: some View { + ConversionTextfield(amount: .constant("1000"), isEditing: .constant(false)) + } +}
--- a/Simoleon/UI/CurrencyButton.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/UI/CurrencyButton.swift Sun Aug 29 19:04:34 2021 +0100 @@ -9,7 +9,7 @@ struct CurrencyButton: View { var selectedCurrency: String - let currencyDetails: [String: CurrencyModel] = try! read(json: "Currencies.json") + let currencyDetails: [String: CurrencyModel] = try! readJson(from: "Currencies.json") var body: some View { let currency = currencyDetails[selectedCurrency]!
--- a/Simoleon/UI/CurrencyList.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/UI/CurrencyList.swift Sun Aug 29 19:04:34 2021 +0100 @@ -12,7 +12,7 @@ @Binding var selectedCurrency: String @State private var searchCurrency = "" @Environment(\.presentationMode) private var presentation - let currencyDetails: [String: CurrencyModel] = try! read(json: "Currencies.json") + let currencyDetails: [String: CurrencyModel] = try! readJson(from: "Currencies.json") var searchResults: [String] { if searchCurrency.isEmpty {
--- a/Simoleon/UI/CurrencySelector.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/UI/CurrencySelector.swift Sun Aug 29 19:04:34 2021 +0100 @@ -8,10 +8,10 @@ import SwiftUI struct CurrencySelector: View { - @State var currencyPair: CurrencyPairModel + @ObservedObject var currencyPair: CurrencyPair @State private var showingList = false @State private var modalSelection: ModalType = .allCurrencies - let currencyPairsSupported: [String] = try! read(json: "CurrencyPairsSupported.json") + let currencyPairsSupported: [String] = try! readJson(from: "CurrencyPairsSupported.json") private enum ModalType { case allCurrencies, compatibleCurrencies @@ -84,6 +84,6 @@ struct CurrencySelector_Previews: PreviewProvider { static var previews: some View { - CurrencySelector(currencyPair: CurrencyPairModel(baseSymbol: "USD", quoteSymbol: "EUR")) + CurrencySelector(currencyPair: CurrencyPair()) } }
--- a/Simoleon/UI/FavoriteButton.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/UI/FavoriteButton.swift Sun Aug 29 19:04:34 2021 +0100 @@ -8,7 +8,7 @@ import SwiftUI struct FavoriteButton: View { - @State var currencyPair: CurrencyPairModel + @ObservedObject var currencyPair: CurrencyPair @State private var scale: CGFloat = 1 @Environment(\.managedObjectContext) private var viewContext @FetchRequest(sortDescriptors: []) private var favoritePairs: FetchedResults<FavoritePair> @@ -91,6 +91,6 @@ struct FavoriteButton_Previews: PreviewProvider { static var previews: some View { - FavoriteButton(currencyPair: CurrencyPairModel(baseSymbol: "USD", quoteSymbol: "EUR")) + FavoriteButton(currencyPair: CurrencyPair()) } }
--- a/Simoleon/UI/Flag.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/Simoleon/UI/Flag.swift Sun Aug 29 19:04:34 2021 +0100 @@ -14,9 +14,8 @@ Image(flag) .resizable() .aspectRatio(contentMode: .fill) - .frame(width: 30, height: 30) + .frame(width: 35, height: 35) .clipShape(Circle()) - .overlay(Circle().stroke(Color(.secondaryLabel), lineWidth: 1)) } }
--- a/SimoleonTests/SimoleonTests.swift Sat Aug 28 19:18:50 2021 +0100 +++ b/SimoleonTests/SimoleonTests.swift Sun Aug 29 19:04:34 2021 +0100 @@ -24,7 +24,7 @@ let expectedResults = [1: ["USD", "EUR"], 2: ["USD"]] // Test - let currencySelector = CurrencySelector(currencyPair: CurrencyPairModel(baseSymbol: "USD", quoteSymbol: "EUR")) + let currencySelector = CurrencySelector(currencyPair: CurrencyPair()) for testCaseNumber in testCases.keys { print("Testing case: \(testCaseNumber)") let mockData = testCases[testCaseNumber]! @@ -41,7 +41,7 @@ let expectedResults = [1: ["GBP"], 2: ["GBP", "EUR"], 3: []] // Test - let currencySelector = CurrencySelector(currencyPair: CurrencyPairModel(baseSymbol: "USD", quoteSymbol: "EUR")) + let currencySelector = CurrencySelector(currencyPair: CurrencyPair()) for testCaseNumber in testCases.keys { print("Testing case: \(testCaseNumber)") let mockData = testCases[testCaseNumber]!