Mercurial > public > simoleon
changeset 19:94fd7ac93060
Redesign
author | Dennis Concepción Martín <dennisconcepcionmartin@gmail.com> |
---|---|
date | Sun, 18 Jul 2021 20:00:05 +0100 |
parents | a3512b689bbe |
children | f8aabe5b7251 |
files | Simoleon.xcodeproj/project.pbxproj Simoleon.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Simoleon.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate Simoleon/Assets.xcassets/PlainButton.colorset/Contents.json Simoleon/ContentView.swift Simoleon/ContentViewPad.swift Simoleon/Conversion.swift Simoleon/Helpers/ConversionBox.swift Simoleon/Helpers/CurrencyButton.swift Simoleon/Helpers/CurrencyConversion.swift Simoleon/Helpers/CurrencyRow.swift Simoleon/Helpers/CurrencySelector.swift Simoleon/Helpers/SearchBar.swift Simoleon/Helpers/Sidebar.swift Simoleon/Preview Content/CurrencyQuoteData.json Simoleon/Resources/PopularCurrencyPairs.json Simoleon/SimoleonApp.swift |
diffstat | 17 files changed, 408 insertions(+), 292 deletions(-) [+] |
line wrap: on
line diff
--- a/Simoleon.xcodeproj/project.pbxproj Sun Jul 18 16:43:06 2021 +0100 +++ b/Simoleon.xcodeproj/project.pbxproj Sun Jul 18 20:00:05 2021 +0100 @@ -7,16 +7,19 @@ objects = { /* Begin PBXBuildFile section */ - 95559337269B0A7B000FD726 /* CurrencyQuoteData.json in Resources */ = {isa = PBXBuildFile; fileRef = 95559336269B0A7B000FD726 /* CurrencyQuoteData.json */; }; 9555933A269B0AB8000FD726 /* ParseJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95559339269B0AB8000FD726 /* ParseJson.swift */; }; 9555933D269B0E0A000FD726 /* CurrencyMetadata.json in Resources */ = {isa = PBXBuildFile; fileRef = 9555933C269B0E0A000FD726 /* CurrencyMetadata.json */; }; 95AEBC9526A03ECB00613729 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AEBC9426A03ECB00613729 /* ContentView.swift */; }; - 95AEBC9726A043C100613729 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AEBC9626A043C100613729 /* SearchBar.swift */; }; 95AEBC9B26A04A4200613729 /* CurrencyMetadataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AEBC9A26A04A4200613729 /* CurrencyMetadataModel.swift */; }; 95AEBC9D26A04D4600613729 /* CurrencyRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AEBC9C26A04D4600613729 /* CurrencyRow.swift */; }; - 95AEBC9F26A08A1C00613729 /* CurrencyConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AEBC9E26A08A1C00613729 /* CurrencyConversion.swift */; }; 95AEBCA326A0900E00613729 /* CurrencyQuoteModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AEBCA226A0900E00613729 /* CurrencyQuoteModel.swift */; }; - 95AEBCA826A0AE2400613729 /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AEBCA726A0AE2400613729 /* Sidebar.swift */; }; + 95B54F4426A4842C001DC0D8 /* Conversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B54F4326A4842C001DC0D8 /* Conversion.swift */; }; + 95B54F4626A48852001DC0D8 /* CurrencySelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B54F4526A48852001DC0D8 /* CurrencySelector.swift */; }; + 95B54F4826A4954B001DC0D8 /* CurrencyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B54F4726A4954B001DC0D8 /* CurrencyButton.swift */; }; + 95B54F4A26A4A450001DC0D8 /* ConversionBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B54F4926A4A450001DC0D8 /* ConversionBox.swift */; }; + 95B54F4D26A4A64F001DC0D8 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 95B54F4C26A4A64F001DC0D8 /* Introspect */; }; + 95B54F4F26A4AC52001DC0D8 /* ContentViewPad.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B54F4E26A4AC52001DC0D8 /* ContentViewPad.swift */; }; + 95B54F5126A4ACAC001DC0D8 /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B54F5026A4ACAC001DC0D8 /* Sidebar.swift */; }; 95C02C8B269B61680061DD6D /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 95C02C8A269B61680061DD6D /* Alamofire */; }; 95C5B2282697752600941585 /* SimoleonApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C5B2272697752600941585 /* SimoleonApp.swift */; }; 95C5B22C2697752700941585 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95C5B22B2697752700941585 /* Assets.xcassets */; }; @@ -26,7 +29,6 @@ 95C5B23F2697752700941585 /* SimoleonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C5B23E2697752700941585 /* SimoleonTests.swift */; }; 95C5B24A2697752700941585 /* SimoleonUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C5B2492697752700941585 /* SimoleonUITests.swift */; }; 95DD4ABB269B33810027CA1F /* CurrencyPairs.json in Resources */ = {isa = PBXBuildFile; fileRef = 95DD4ABA269B33810027CA1F /* CurrencyPairs.json */; }; - 95E76432269DF531008E9F31 /* PopularCurrencyPairs.json in Resources */ = {isa = PBXBuildFile; fileRef = 95E76431269DF531008E9F31 /* PopularCurrencyPairs.json */; }; 95E76436269DFC1A008E9F31 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 95E76435269DFC1A008E9F31 /* LaunchScreen.storyboard */; }; 95E7643A269E0037008E9F31 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95E76439269E0037008E9F31 /* CloudKit.framework */; }; /* End PBXBuildFile section */ @@ -49,16 +51,18 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 95559336269B0A7B000FD726 /* CurrencyQuoteData.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = CurrencyQuoteData.json; sourceTree = "<group>"; }; 95559339269B0AB8000FD726 /* ParseJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseJson.swift; sourceTree = "<group>"; }; 9555933C269B0E0A000FD726 /* CurrencyMetadata.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = CurrencyMetadata.json; sourceTree = "<group>"; }; 95AEBC9426A03ECB00613729 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; - 95AEBC9626A043C100613729 /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; }; 95AEBC9A26A04A4200613729 /* CurrencyMetadataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyMetadataModel.swift; sourceTree = "<group>"; }; 95AEBC9C26A04D4600613729 /* CurrencyRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyRow.swift; sourceTree = "<group>"; }; - 95AEBC9E26A08A1C00613729 /* CurrencyConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyConversion.swift; sourceTree = "<group>"; }; 95AEBCA226A0900E00613729 /* CurrencyQuoteModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyQuoteModel.swift; sourceTree = "<group>"; }; - 95AEBCA726A0AE2400613729 /* Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sidebar.swift; sourceTree = "<group>"; }; + 95B54F4326A4842C001DC0D8 /* Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Conversion.swift; sourceTree = "<group>"; }; + 95B54F4526A48852001DC0D8 /* CurrencySelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencySelector.swift; sourceTree = "<group>"; }; + 95B54F4726A4954B001DC0D8 /* CurrencyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyButton.swift; sourceTree = "<group>"; }; + 95B54F4926A4A450001DC0D8 /* ConversionBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversionBox.swift; sourceTree = "<group>"; }; + 95B54F4E26A4AC52001DC0D8 /* ContentViewPad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewPad.swift; sourceTree = "<group>"; }; + 95B54F5026A4ACAC001DC0D8 /* Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sidebar.swift; sourceTree = "<group>"; }; 95C5B2242697752600941585 /* Simoleon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Simoleon.app; sourceTree = BUILT_PRODUCTS_DIR; }; 95C5B2272697752600941585 /* SimoleonApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimoleonApp.swift; sourceTree = "<group>"; }; 95C5B22B2697752700941585 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; @@ -73,7 +77,6 @@ 95C5B2492697752700941585 /* SimoleonUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimoleonUITests.swift; sourceTree = "<group>"; }; 95C5B24B2697752700941585 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 95DD4ABA269B33810027CA1F /* CurrencyPairs.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = CurrencyPairs.json; sourceTree = "<group>"; }; - 95E76431269DF531008E9F31 /* PopularCurrencyPairs.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = PopularCurrencyPairs.json; sourceTree = "<group>"; }; 95E76435269DFC1A008E9F31 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; }; 95E76437269E0033008E9F31 /* Simoleon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Simoleon.entitlements; sourceTree = "<group>"; }; 95E76439269E0037008E9F31 /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; }; @@ -85,6 +88,7 @@ buildActionMask = 2147483647; files = ( 95C02C8B269B61680061DD6D /* Alamofire in Frameworks */, + 95B54F4D26A4A64F001DC0D8 /* Introspect in Frameworks */, 95E7643A269E0037008E9F31 /* CloudKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -128,7 +132,6 @@ children = ( 9555933C269B0E0A000FD726 /* CurrencyMetadata.json */, 95DD4ABA269B33810027CA1F /* CurrencyPairs.json */, - 95E76431269DF531008E9F31 /* PopularCurrencyPairs.json */, ); path = Resources; sourceTree = "<group>"; @@ -160,6 +163,8 @@ 95E76437269E0033008E9F31 /* Simoleon.entitlements */, 95C5B2272697752600941585 /* SimoleonApp.swift */, 95AEBC9426A03ECB00613729 /* ContentView.swift */, + 95B54F4E26A4AC52001DC0D8 /* ContentViewPad.swift */, + 95B54F4326A4842C001DC0D8 /* Conversion.swift */, 95C5B22B2697752700941585 /* Assets.xcassets */, 95C5B2302697752700941585 /* Persistence.swift */, 95C5B2352697752700941585 /* Info.plist */, @@ -178,7 +183,6 @@ isa = PBXGroup; children = ( 95C5B22E2697752700941585 /* Preview Assets.xcassets */, - 95559336269B0A7B000FD726 /* CurrencyQuoteData.json */, ); path = "Preview Content"; sourceTree = "<group>"; @@ -212,10 +216,11 @@ 95FE659A269AFB44008745DE /* Helpers */ = { isa = PBXGroup; children = ( - 95AEBC9626A043C100613729 /* SearchBar.swift */, + 95B54F4726A4954B001DC0D8 /* CurrencyButton.swift */, + 95B54F4526A48852001DC0D8 /* CurrencySelector.swift */, 95AEBC9C26A04D4600613729 /* CurrencyRow.swift */, - 95AEBC9E26A08A1C00613729 /* CurrencyConversion.swift */, - 95AEBCA726A0AE2400613729 /* Sidebar.swift */, + 95B54F4926A4A450001DC0D8 /* ConversionBox.swift */, + 95B54F5026A4ACAC001DC0D8 /* Sidebar.swift */, ); path = Helpers; sourceTree = "<group>"; @@ -238,6 +243,7 @@ name = Simoleon; packageProductDependencies = ( 95C02C8A269B61680061DD6D /* Alamofire */, + 95B54F4C26A4A64F001DC0D8 /* Introspect */, ); productName = Simoleon; productReference = 95C5B2242697752600941585 /* Simoleon.app */; @@ -312,6 +318,7 @@ mainGroup = 95C5B21B2697752600941585; packageReferences = ( 95C02C89269B61680061DD6D /* XCRemoteSwiftPackageReference "Alamofire" */, + 95B54F4B26A4A64F001DC0D8 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, ); productRefGroup = 95C5B2252697752600941585 /* Products */; projectDirPath = ""; @@ -329,9 +336,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 95559337269B0A7B000FD726 /* CurrencyQuoteData.json in Resources */, 95DD4ABB269B33810027CA1F /* CurrencyPairs.json in Resources */, - 95E76432269DF531008E9F31 /* PopularCurrencyPairs.json in Resources */, 95C5B22F2697752700941585 /* Preview Assets.xcassets in Resources */, 95E76436269DFC1A008E9F31 /* LaunchScreen.storyboard in Resources */, 9555933D269B0E0A000FD726 /* CurrencyMetadata.json in Resources */, @@ -361,16 +366,19 @@ buildActionMask = 2147483647; files = ( 95C5B2312697752700941585 /* Persistence.swift in Sources */, - 95AEBC9F26A08A1C00613729 /* CurrencyConversion.swift in Sources */, 95AEBC9526A03ECB00613729 /* ContentView.swift in Sources */, 95AEBC9B26A04A4200613729 /* CurrencyMetadataModel.swift in Sources */, 9555933A269B0AB8000FD726 /* ParseJson.swift in Sources */, 95C5B2282697752600941585 /* SimoleonApp.swift in Sources */, + 95B54F4A26A4A450001DC0D8 /* ConversionBox.swift in Sources */, 95AEBC9D26A04D4600613729 /* CurrencyRow.swift in Sources */, 95AEBCA326A0900E00613729 /* CurrencyQuoteModel.swift in Sources */, - 95AEBCA826A0AE2400613729 /* Sidebar.swift in Sources */, + 95B54F4826A4954B001DC0D8 /* CurrencyButton.swift in Sources */, + 95B54F4F26A4AC52001DC0D8 /* ContentViewPad.swift in Sources */, + 95B54F4426A4842C001DC0D8 /* Conversion.swift in Sources */, 95C5B2342697752700941585 /* Simoleon.xcdatamodeld in Sources */, - 95AEBC9726A043C100613729 /* SearchBar.swift in Sources */, + 95B54F5126A4ACAC001DC0D8 /* Sidebar.swift in Sources */, + 95B54F4626A48852001DC0D8 /* CurrencySelector.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -696,6 +704,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 95B54F4B26A4A64F001DC0D8 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/siteline/SwiftUI-Introspect.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.1.3; + }; + }; 95C02C89269B61680061DD6D /* XCRemoteSwiftPackageReference "Alamofire" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/Alamofire.git"; @@ -707,6 +723,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 95B54F4C26A4A64F001DC0D8 /* Introspect */ = { + isa = XCSwiftPackageProductDependency; + package = 95B54F4B26A4A64F001DC0D8 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */; + productName = Introspect; + }; 95C02C8A269B61680061DD6D /* Alamofire */ = { isa = XCSwiftPackageProductDependency; package = 95C02C89269B61680061DD6D /* XCRemoteSwiftPackageReference "Alamofire" */;
--- a/Simoleon.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Sun Jul 18 16:43:06 2021 +0100 +++ b/Simoleon.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Sun Jul 18 20:00:05 2021 +0100 @@ -9,6 +9,15 @@ "revision": "f96b619bcb2383b43d898402283924b80e2c4bae", "version": "5.4.3" } + }, + { + "package": "Introspect", + "repositoryURL": "https://github.com/siteline/SwiftUI-Introspect.git", + "state": { + "branch": null, + "revision": "2e09be8af614401bc9f87d40093ec19ce56ccaf2", + "version": "0.1.3" + } } ] },
Binary file Simoleon.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/Assets.xcassets/PlainButton.colorset/Contents.json Sun Jul 18 20:00:05 2021 +0100 @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +}
--- a/Simoleon/ContentView.swift Sun Jul 18 16:43:06 2021 +0100 +++ b/Simoleon/ContentView.swift Sun Jul 18 20:00:05 2021 +0100 @@ -8,53 +8,12 @@ import SwiftUI struct ContentView: View { - @State var searchText = "" - @State var searching = false - @State private var refreshView = 0 - let currencyPairs: [String] = parseJson("CurrencyPairs.json") - var body: some View { - VStack { - SearchBar(searchText: $searchText, searching: $searching) - List(filterCurrencies(), id: \.self) { currency in - NavigationLink(destination: CurrencyConversion(currency: currency)) { - CurrencyRow(currency: currency) - } - } - .id(UUID()) - .listStyle(InsetListStyle()) - .gesture(DragGesture() - .onChanged({ _ in - UIApplication.shared.dismissKeyboard() - }) - ) - } - .navigationTitle(searching ? "Search" : "Popular currencies") - .toolbar { - if searching { - Button("Cancel") { searchText = "" - withAnimation { - searching = false - UIApplication.shared.dismissKeyboard() - } - } - } - } - } - - private func filterCurrencies() -> [String] { - if searchText.isEmpty { - return currencyPairs - } else { - return currencyPairs.filter { $0.contains(searchText.uppercased()) } + NavigationView { + Conversion() } } } -extension UIApplication { - func dismissKeyboard() { - sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) - } - } struct ContentView_Previews: PreviewProvider { static var previews: some View {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/ContentViewPad.swift Sun Jul 18 20:00:05 2021 +0100 @@ -0,0 +1,23 @@ +// +// ContentViewPad.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 18/07/2021. +// + +import SwiftUI + +struct ContentViewPad: View { + var body: some View { + NavigationView { + Sidebar() + Conversion() + } + } +} + +struct ContentViewPad_Previews: PreviewProvider { + static var previews: some View { + ContentViewPad() + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/Conversion.swift Sun Jul 18 20:00:05 2021 +0100 @@ -0,0 +1,93 @@ +// +// Conversion.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 18/07/2021. +// + +import SwiftUI +import Alamofire + +struct Conversion: View { + @State private var mainCurrency = "USD" + @State private var secondaryCurrency = "GBP" + @State private var amountToConvert = "1000" + @State private var price: Double = 1.00 + @State private var showingConversion = false + @State private var showingCurrencySelector = false + @State private var selectingMainCurrency = false + @State private var currencyPairNotFound = false + + let currencyMetadata: [String: CurrencyMetadataModel] = parseJson("CurrencyMetadata.json") + + var body: some View { + ScrollView(showsIndicators: false) { + VStack(alignment: .leading) { + HStack { + Button(action: { selectingMainCurrency = true; showingCurrencySelector = true }) { + CurrencyButton(currency: $mainCurrency) + } + + Button(action: { selectingMainCurrency = false; showingCurrencySelector = true }) { + CurrencyButton(currency: $secondaryCurrency) + } + } + + ConversionBox( + mainCurrency: $mainCurrency, + secondaryCurrency: $secondaryCurrency, + amountToConvert: $amountToConvert, + price: $price, + showingConversion: $showingConversion, + showingCurrencySelector: $showingCurrencySelector, + currencyPairNotFound: $currencyPairNotFound + ) + } + .padding() + .onAppear { requestApi(mainCurrency, secondaryCurrency) } + .onChange(of: showingCurrencySelector, perform: { showingCurrencySelector in + if !showingCurrencySelector { + requestApi(mainCurrency, secondaryCurrency) + } + }) + .sheet(isPresented: $showingCurrencySelector) { + CurrencySelector( + mainCurrencySelected: $mainCurrency, + secondaryCurrencySelected: $secondaryCurrency, + showingCurrencySelector: $showingCurrencySelector, + selectingMainCurrency: $selectingMainCurrency + ) + } + } + .navigationBarHidden(true) + } + + private func requestApi(_ mainCurrency: String, _ secondaryCurrency: String) { + let url = "https://api.1forge.com/quotes?pairs=\(mainCurrency)/\(secondaryCurrency)&api_key=BFWeJQ3jJtqqpDv5ArNis59pAlFcQ4KF" + + AF.request(url).responseDecodable(of: [CurrencyQuoteModel].self) { response in + self.showingConversion = false + self.currencyPairNotFound = false + + if let currencyQuotes = response.value { + if let price = currencyQuotes.first?.price { + self.price = price + self.showingConversion = true + } else { + self.currencyPairNotFound = true + } + } else { +// Handle error + } + } + } +} + + +struct Conversion_Previews: PreviewProvider { + static var previews: some View { + NavigationView { + Conversion() + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/Helpers/ConversionBox.swift Sun Jul 18 20:00:05 2021 +0100 @@ -0,0 +1,85 @@ +// +// ConversionBox.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 18/07/2021. +// + +import SwiftUI +import Introspect + +struct ConversionBox: View { + @Binding var mainCurrency: String + @Binding var secondaryCurrency: String + @Binding var amountToConvert: String + @Binding var price: Double + @Binding var showingConversion: Bool + @Binding var showingCurrencySelector: Bool + @Binding var currencyPairNotFound: Bool + + @State private var showingCancelationButton = false + + let currencyMetadata: [String: CurrencyMetadataModel] = parseJson("CurrencyMetadata.json") + + var body: some View { + VStack(alignment: .leading) { + Text("\(currencyMetadata[mainCurrency]!.name) (\(mainCurrency))") + .font(.callout) + .fontWeight(.semibold) + .padding(.top, 40) + + ZStack(alignment: .trailing) { + TextField("Enter amount", text: $amountToConvert) + .keyboardType(.decimalPad) + .font(Font.title.weight(.semibold)) + .lineLimit(1) + .padding(.bottom, 10) + .introspectTextField { textField in + if !showingCurrencySelector { + textField.becomeFirstResponder() + } + } + } + + Divider() + + Text("\(currencyMetadata[secondaryCurrency]!.name) (\(secondaryCurrency))") + .font(.callout) + .fontWeight(.semibold) + .padding(.top, 10) + + if showingConversion { + Text("\(makeConversion(), specifier: "%.2f")") + .font(Font.title.weight(.semibold)) + .lineLimit(1) + .padding(.top, 5) + } else { + if currencyPairNotFound { + Text("The currency pair selected is not supported yet 😢") + .padding(.top, 5) + } else { + ProgressView() + .padding(.top, 5) + } + } + } + } + + + private func makeConversion() -> Double { + if amountToConvert.isEmpty { /// Avoid nil error when string is empty + return 0 + } else { + let conversion = Double(amountToConvert)! * price + + return conversion + } + } +} + + +struct ConversionBox_Previews: PreviewProvider { + static var previews: some View { + ConversionBox(mainCurrency: .constant("USD"), secondaryCurrency: .constant("GBP"), amountToConvert: .constant("1000"), price: .constant(1), showingConversion: .constant(true), showingCurrencySelector: .constant(false), currencyPairNotFound: .constant(false)) + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/Helpers/CurrencyButton.swift Sun Jul 18 20:00:05 2021 +0100 @@ -0,0 +1,39 @@ +// +// CurrencyButton.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 18/07/2021. +// + +import SwiftUI + +struct CurrencyButton: View { + @Binding var currency: String + let currencyMetadata: [String: CurrencyMetadataModel] = parseJson("CurrencyMetadata.json") + + var body: some View { + RoundedRectangle(cornerRadius: 25) + .foregroundColor(Color(.secondarySystemBackground)) + .frame(height: 75) + .overlay( + HStack { + Image(currencyMetadata[currency]!.flag) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 30, height: 30) + .clipShape(Circle()) + .overlay(Circle().stroke(Color(.systemGray), lineWidth: 1)) + + Text("\(currency)") + .fontWeight(.semibold) + .foregroundColor(Color("PlainButton")) + } + ) + } +} + +struct CurrencyButton_Previews: PreviewProvider { + static var previews: some View { + CurrencyButton(currency: .constant("USD")) + } +}
--- a/Simoleon/Helpers/CurrencyConversion.swift Sun Jul 18 16:43:06 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -// -// CurrencyConversion.swift -// Simoleon -// -// Created by Dennis Concepción Martín on 15/07/2021. -// - -import SwiftUI -import Alamofire - -struct CurrencyConversion: View { - var currency: String - @State private var price: Double = 1.00 - @State private var amountToConvert = "100" - @State private var isEditing = false - @State private var showConversion = false - let currencyMetadata: [String: CurrencyMetadataModel] = parseJson("CurrencyMetadata.json") - - var body: some View { - let currencies = currency.components(separatedBy: "/") - let mainCurrency = String(currencies[0]) - let secondaryCurrency = String(currencies[1]) - - ScrollView(showsIndicators: false) { - VStack(spacing: 20) { - ZStack { - Rectangle() - .foregroundColor(Color(.secondarySystemBackground)) - - HStack { - Image(currencyMetadata[mainCurrency]!.flag) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 30, height: 30) - .clipShape(Circle()) - .overlay(Circle().stroke(Color(.systemGray), lineWidth: 1)) - - TextField("Amount", text: $amountToConvert) { startedEditing in - if startedEditing { - withAnimation { - isEditing = true - } - } - } - onCommit: { - withAnimation { - isEditing = false - } - } - .keyboardType(.decimalPad) - .lineLimit(1) - .padding(.horizontal) - - Text("\(mainCurrency)") - .fontWeight(.semibold) - } - .padding(.horizontal) - } - .frame(height: 50) - .cornerRadius(13) - - ZStack { - Rectangle() - .foregroundColor(Color(.secondarySystemBackground)) - - HStack { - Image(currencyMetadata[secondaryCurrency]!.flag) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 30, height: 30) - .clipShape(Circle()) - .overlay(Circle().stroke(Color(.systemGray), lineWidth: 1)) - - if showConversion { - Text("\(makeConversion(), specifier: "%.4f")") - .lineLimit(1) - .padding(.horizontal) - } else { - ProgressView() - .padding(.horizontal) - } - - Spacer() - Text("\(secondaryCurrency)") - .fontWeight(.semibold) - } - .padding(.horizontal) - } - .frame(height: 50) - .cornerRadius(13) - - if showConversion { - Text("From \(currencyMetadata[mainCurrency]!.name) to \(currencyMetadata[secondaryCurrency]!.name) at \(price, specifier: "%.4f") exchange rate.") - .multilineTextAlignment(.center) - } - - } - .padding() - } - .onAppear { requestApi(mainCurrency, secondaryCurrency) } - .navigationTitle("Conversion") - } - - private func makeConversion() -> Double { - if amountToConvert.isEmpty { /// Avoid nil error when string is empty - return 0 - } else { - let conversion = Double(amountToConvert)! * price - - return conversion - } - } - - private func requestApi(_ mainCurrency: String, _ secondaryCurrency: String) { - let url = "https://api.simoleon.app/quotes=\(mainCurrency)-\(secondaryCurrency)" - AF.request(url).responseDecodable(of: [CurrencyQuoteModel].self) { response in - if let currencyQuotes = response.value { - if let price = currencyQuotes[0].price { - self.price = price - } - self.showConversion = true - } else { -// Handle error - } - } - } -} - -struct CurrencyConversion_Previews: PreviewProvider { - static var previews: some View { - NavigationView { - CurrencyConversion(currency: "USD/GBP") - } - } -}
--- a/Simoleon/Helpers/CurrencyRow.swift Sun Jul 18 16:43:06 2021 +0100 +++ b/Simoleon/Helpers/CurrencyRow.swift Sun Jul 18 20:00:05 2021 +0100 @@ -8,48 +8,37 @@ import SwiftUI struct CurrencyRow: View { + var currency: String let currencyMetadata: [String: CurrencyMetadataModel] = parseJson("CurrencyMetadata.json") - var currency: String var body: some View { - let currencies = currency.components(separatedBy: "/") - let mainCurrency = String(currencies[0]) - let secondaryCurrency = String(currencies[1]) HStack { - Image(currencyMetadata[mainCurrency]!.flag) + Image(currencyMetadata[currency]!.flag) .resizable() .aspectRatio(contentMode: .fill) .frame(width: 30, height: 30) .clipShape(Circle()) .overlay(Circle().stroke(Color(.systemGray), lineWidth: 1)) - Image(currencyMetadata[secondaryCurrency]!.flag) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 30, height: 30) - .clipShape(Circle()) - .overlay(Circle().stroke(Color(.systemGray), lineWidth: 1)) - .offset(x: -20) - .padding(.trailing, -20) - VStack(alignment: .leading) { Text("\(currency)") .fontWeight(.semibold) + .foregroundColor(Color("PlainButton")) - Text("\(currencyMetadata[mainCurrency]!.name)/\(currencyMetadata[secondaryCurrency]!.name)") + Text("\(currencyMetadata[currency]!.name)") .font(.footnote) .fontWeight(.semibold) + .foregroundColor(Color("PlainButton")) .opacity(0.5) .lineLimit(1) } .padding(.horizontal) } - .padding(.vertical, 7) } } struct CurrencyRow_Previews: PreviewProvider { static var previews: some View { - CurrencyRow(currency: "USD/GBP") + CurrencyRow(currency: "USD") } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Simoleon/Helpers/CurrencySelector.swift Sun Jul 18 20:00:05 2021 +0100 @@ -0,0 +1,65 @@ +// +// CurrencySelector.swift +// Simoleon +// +// Created by Dennis Concepción Martín on 18/07/2021. +// + +import SwiftUI + +struct CurrencySelector: View { + @Binding var mainCurrencySelected: String + @Binding var secondaryCurrencySelected: String + @Binding var showingCurrencySelector: Bool + @Binding var selectingMainCurrency: Bool + + var body: some View { + NavigationView { + Form { + ForEach(generateCurrencyList(), id: \.self) { currency in + Button(action: { select(currency) }) { + CurrencyRow(currency: currency) + } + } + } + .navigationTitle("Currencies") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button("OK", action: { showingCurrencySelector = false }) + } + } + } + } + + private func generateCurrencyList() -> [String] { + let currencyPairs: [String] = parseJson("CurrencyPairs.json") + var currencies: [String] = [] + + for currencyPair in currencyPairs { + let splittedCurrencies = currencyPair.split(separator: "/") + let mainCurrency = String(splittedCurrencies[0]) + if !currencies.contains(mainCurrency) { + currencies.append(mainCurrency) + } + } + + return currencies + } + + private func select(_ currency: String) { + if selectingMainCurrency { + self.mainCurrencySelected = currency + } else { + self.secondaryCurrencySelected = currency + } + + showingCurrencySelector = false + } +} + +struct CurrencySelector_Previews: PreviewProvider { + static var previews: some View { + CurrencySelector(mainCurrencySelected: .constant(""), secondaryCurrencySelected: .constant(""), showingCurrencySelector: .constant(false), selectingMainCurrency: .constant(true)) + } +}
--- a/Simoleon/Helpers/SearchBar.swift Sun Jul 18 16:43:06 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -// -// SearchBar.swift -// Simoleon -// -// Created by Dennis Concepción Martín on 15/07/2021. -// - -import SwiftUI - -struct SearchBar: View { - @Binding var searchText: String - @Binding var searching: Bool - - var body: some View { - ZStack { - Rectangle() - .foregroundColor(Color(.secondarySystemBackground)) - - HStack { - Image(systemName: "magnifyingglass") - TextField("Search ..", text: $searchText) { startedEditing in - if startedEditing { - withAnimation { - searching = true - } - } - } - onCommit: { - withAnimation { - searching = false - } - } - } - .padding(.leading, 13) - - } - .frame(height: 40) - .cornerRadius(13) - .padding() - } -} - -struct SearchBar_Previews: PreviewProvider { - static var previews: some View { - SearchBar(searchText: .constant(""), searching: .constant(false)) - } -}
--- a/Simoleon/Helpers/Sidebar.swift Sun Jul 18 16:43:06 2021 +0100 +++ b/Simoleon/Helpers/Sidebar.swift Sun Jul 18 20:00:05 2021 +0100 @@ -2,7 +2,7 @@ // Sidebar.swift // Simoleon // -// Created by Dennis Concepción Martín on 15/07/2021. +// Created by Dennis Concepción Martín on 18/07/2021. // import SwiftUI @@ -10,12 +10,11 @@ struct Sidebar: View { var body: some View { List { - NavigationLink(destination: ContentView()) { - Text("Popular currencies") + NavigationLink(destination: Conversion()) { + Label("Convert", systemImage: "glass") } } .listStyle(SidebarListStyle()) - .navigationBarTitle("Categories") } }
--- a/Simoleon/Preview Content/CurrencyQuoteData.json Sun Jul 18 16:43:06 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -{ - "p": 1.39011, - "a": 1.39016, - "b": 1.39006, - "s": "GBP/USD", - "t": 1625864399283 -} -
--- a/Simoleon/Resources/PopularCurrencyPairs.json Sun Jul 18 16:43:06 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -[ - "EUR/USD", - "USD/JPY", - "USD/GBP", - "USD/CHF", - "USD/CAD", - "AUD/USD", - "NZD/USD" -]
--- a/Simoleon/SimoleonApp.swift Sun Jul 18 16:43:06 2021 +0100 +++ b/Simoleon/SimoleonApp.swift Sun Jul 18 20:00:05 2021 +0100 @@ -14,16 +14,11 @@ var body: some Scene { WindowGroup { if UIDevice.current.userInterfaceIdiom == .pad { - NavigationView { - Sidebar() - ContentView() - CurrencyConversion(currency: "EUR/USD") - } + ContentViewPad() + .environment(\.managedObjectContext, persistenceController.container.viewContext) } else { - NavigationView { - ContentView() - .environment(\.managedObjectContext, persistenceController.container.viewContext) - } + ContentView() + .environment(\.managedObjectContext, persistenceController.container.viewContext) } } }