# HG changeset patch # User Dennis Concepción Martín <66180929+denniscm190@users.noreply.github.com> # Date 1611515617 -3600 # Node ID 096dbea11d438b5d2edffe2bf53b8a9a85d41e13 # Parent 7fef171d4820bb7cbb4608d3d0fe4eda08ce765e Implement SDWebImageSwiftUI to load remote image from google api diff -r 7fef171d4820 -r 096dbea11d43 LazyBear.xcodeproj/project.pbxproj --- a/LazyBear.xcodeproj/project.pbxproj Sun Jan 24 19:44:15 2021 +0100 +++ b/LazyBear.xcodeproj/project.pbxproj Sun Jan 24 20:13:37 2021 +0100 @@ -11,13 +11,16 @@ 950B79F625B1CB7A00E5DB5B /* CompanyList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 950B79F525B1CB7A00E5DB5B /* CompanyList.swift */; }; 952498B325BB381300B00E22 /* CurrentPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952498B225BB381300B00E22 /* CurrentPrice.swift */; }; 952498B625BB47A700B00E22 /* LatestPriceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952498B525BB47A700B00E22 /* LatestPriceModel.swift */; }; + 9537923625BDF85D0001F82B /* GoogleApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9537923525BDF85D0001F82B /* GoogleApi.swift */; }; + 9537924A25BDFCD70001F82B /* LoadImageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9537924925BDFCD70001F82B /* LoadImageTest.swift */; }; + 9537924F25BDFD940001F82B /* SDWebImageSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 9537924E25BDFD940001F82B /* SDWebImageSwiftUI */; }; 954D992525A2123B001F7F60 /* HistoricalPricesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954D992425A2123B001F7F60 /* HistoricalPricesModel.swift */; }; 954D996D25A2461B001F7F60 /* SwiftUICharts in Frameworks */ = {isa = PBXBuildFile; productRef = 954D996C25A2461B001F7F60 /* SwiftUICharts */; }; 954D997125A253A9001F7F60 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954D997025A253A9001F7F60 /* Config.swift */; }; 95612C512598D48200F7698F /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95612C4F2598D48200F7698F /* SearchBar.swift */; }; 956FAF7B25AF421E0002B2C1 /* FavCompany+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956FAF7925AF421E0002B2C1 /* FavCompany+CoreDataClass.swift */; }; 956FAF7C25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956FAF7A25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift */; }; - 95700BC625BD9D12009CEEFE /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95700BC525BD9D12009CEEFE /* API.swift */; }; + 95700BC625BD9D12009CEEFE /* IexApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95700BC525BD9D12009CEEFE /* IexApi.swift */; }; 958E472B25B1CA8B0048E770 /* FavCompanyList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 958E472A25B1CA8B0048E770 /* FavCompanyList.swift */; }; 95AB4A7A259DCBAE0064C9C1 /* ReadJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */; }; 95AB4A7D259DCC0C0064C9C1 /* CompanyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */; }; @@ -48,12 +51,14 @@ 950B79F525B1CB7A00E5DB5B /* CompanyList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyList.swift; sourceTree = ""; }; 952498B225BB381300B00E22 /* CurrentPrice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentPrice.swift; sourceTree = ""; }; 952498B525BB47A700B00E22 /* LatestPriceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LatestPriceModel.swift; path = lazybear/Models/LatestPriceModel.swift; sourceTree = SOURCE_ROOT; }; + 9537923525BDF85D0001F82B /* GoogleApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GoogleApi.swift; path = lazybear/GoogleApi.swift; sourceTree = SOURCE_ROOT; }; + 9537924925BDFCD70001F82B /* LoadImageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LoadImageTest.swift; path = lazybear/Tests/LoadImageTest.swift; sourceTree = SOURCE_ROOT; }; 954D992425A2123B001F7F60 /* HistoricalPricesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = HistoricalPricesModel.swift; path = lazybear/Models/HistoricalPricesModel.swift; sourceTree = SOURCE_ROOT; }; 954D997025A253A9001F7F60 /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Config.swift; path = lazybear/Config.swift; sourceTree = SOURCE_ROOT; }; 95612C4F2598D48200F7698F /* SearchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = ""; }; 956FAF7925AF421E0002B2C1 /* FavCompany+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FavCompany+CoreDataClass.swift"; sourceTree = ""; }; 956FAF7A25AF421E0002B2C1 /* FavCompany+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FavCompany+CoreDataProperties.swift"; sourceTree = ""; }; - 95700BC525BD9D12009CEEFE /* API.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = API.swift; path = lazybear/API.swift; sourceTree = SOURCE_ROOT; }; + 95700BC525BD9D12009CEEFE /* IexApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = IexApi.swift; path = lazybear/IexApi.swift; sourceTree = SOURCE_ROOT; }; 958E472A25B1CA8B0048E770 /* FavCompanyList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FavCompanyList.swift; path = "lazybear/Supply views/FavCompanyList.swift"; sourceTree = SOURCE_ROOT; }; 95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReadJson.swift; path = lazybear/Functions/ReadJson.swift; sourceTree = SOURCE_ROOT; }; 95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompanyModel.swift; path = lazybear/Models/CompanyModel.swift; sourceTree = SOURCE_ROOT; }; @@ -85,6 +90,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9537924F25BDFD940001F82B /* SDWebImageSwiftUI in Frameworks */, 95002580256D17D9008FFD28 /* StoreKit.framework in Frameworks */, 954D996D25A2461B001F7F60 /* SwiftUICharts in Frameworks */, ); @@ -104,6 +110,7 @@ 952F791C2598B1CD00FF929F /* Tests */ = { isa = PBXGroup; children = ( + 9537924925BDFCD70001F82B /* LoadImageTest.swift */, ); path = Tests; sourceTree = ""; @@ -187,7 +194,8 @@ 95002578256D1564008FFD28 /* Configuration.storekit */, 95F7CAF425ADC7B7009E0E7C /* LazyBear.xcdatamodeld */, 954D997025A253A9001F7F60 /* Config.swift */, - 95700BC525BD9D12009CEEFE /* API.swift */, + 95700BC525BD9D12009CEEFE /* IexApi.swift */, + 9537923525BDF85D0001F82B /* GoogleApi.swift */, 95B04EB225212369000AD27F /* LazyBearApp.swift */, 95B04EB425212369000AD27F /* ContentView.swift */, 95612C4D2598D48200F7698F /* Supply views */, @@ -225,6 +233,7 @@ name = LazyBear; packageProductDependencies = ( 954D996C25A2461B001F7F60 /* SwiftUICharts */, + 9537924E25BDFD940001F82B /* SDWebImageSwiftUI */, ); productName = LazyBear; productReference = 95B04EAF25212369000AD27F /* LazyBear.app */; @@ -255,6 +264,7 @@ mainGroup = 95B04EA625212369000AD27F; packageReferences = ( 954D996B25A2461B001F7F60 /* XCRemoteSwiftPackageReference "ChartView" */, + 9537924D25BDFD940001F82B /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */, ); productRefGroup = 95B04EB025212369000AD27F /* Products */; projectDirPath = ""; @@ -304,9 +314,11 @@ 95F6C2F325BAE3D1003CF389 /* Stock.swift in Sources */, 95AB4A7D259DCC0C0064C9C1 /* CompanyModel.swift in Sources */, 95F6C2DD25BAD394003CF389 /* FavCompanyRow.swift in Sources */, - 95700BC625BD9D12009CEEFE /* API.swift in Sources */, + 95700BC625BD9D12009CEEFE /* IexApi.swift in Sources */, + 9537923625BDF85D0001F82B /* GoogleApi.swift in Sources */, 95F6C2E425BAD529003CF389 /* RandomColor.swift in Sources */, 95C28AB625BC45CF0033D16A /* ChartStyle.swift in Sources */, + 9537924A25BDFCD70001F82B /* LoadImageTest.swift in Sources */, 954D997125A253A9001F7F60 /* Config.swift in Sources */, 95C28AB925BC46250033D16A /* ScalateChart.swift in Sources */, 954D992525A2123B001F7F60 /* HistoricalPricesModel.swift in Sources */, @@ -511,6 +523,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 9537924D25BDFD940001F82B /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SDWebImage/SDWebImageSwiftUI.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.5.0; + }; + }; 954D996B25A2461B001F7F60 /* XCRemoteSwiftPackageReference "ChartView" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/AppPear/ChartView.git"; @@ -522,6 +542,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 9537924E25BDFD940001F82B /* SDWebImageSwiftUI */ = { + isa = XCSwiftPackageProductDependency; + package = 9537924D25BDFD940001F82B /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */; + productName = SDWebImageSwiftUI; + }; 954D996C25A2461B001F7F60 /* SwiftUICharts */ = { isa = XCSwiftPackageProductDependency; package = 954D996B25A2461B001F7F60 /* XCRemoteSwiftPackageReference "ChartView" */; diff -r 7fef171d4820 -r 096dbea11d43 LazyBear.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved --- a/LazyBear.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Sun Jan 24 19:44:15 2021 +0100 +++ b/LazyBear.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Sun Jan 24 20:13:37 2021 +0100 @@ -9,6 +9,24 @@ "revision": "4699847a9ac0c694666cea3acef133498952566e", "version": "1.5.4" } + }, + { + "package": "SDWebImage", + "repositoryURL": "https://github.com/SDWebImage/SDWebImage.git", + "state": { + "branch": null, + "revision": "4aaca57fb2f6dc5554a2228cf1d94289bd0a6c7d", + "version": "5.10.3" + } + }, + { + "package": "SDWebImageSwiftUI", + "repositoryURL": "https://github.com/SDWebImage/SDWebImageSwiftUI.git", + "state": { + "branch": null, + "revision": "4c7f169e39bc35d6b80d42b8eb8301bee9cd0907", + "version": "1.5.0" + } } ] }, diff -r 7fef171d4820 -r 096dbea11d43 LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed diff -r 7fef171d4820 -r 096dbea11d43 lazybear/API.swift --- a/lazybear/API.swift Sun Jan 24 19:44:15 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -// -// API.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 24/1/21. -// - -import SwiftUI - -struct API { - enum BaseURL { - case sandbox - case production - - var path: (String, String) { - let token = Token() - switch self { - case .sandbox: - return ("https://sandbox.iexapis.com", token.sandbox) - case .production: - return ("https://cloud.iexapis.com", token.production) - } - } - } - - enum Version { - case stable - - var path: String { - switch self { - case .stable: - return "/stable" - } - } - } - - enum Stock { - case symbol(company: String) - var path: String { - switch self { - case let .symbol(company): - return "/stock/\(company)" - } - } - } - - enum Endpoint { - case historicalPrices - var path: String { - switch self { - case .historicalPrices: - return "/chart" - } - } - } - - enum Range { - case period(range: String) - var path: String { - switch self { - case let .period(range): - return "/\(range)?" - } - } - } - - enum Parameters { - case chartCloseOnly - var path: String { - switch self { - case .chartCloseOnly: - return "chartCloseOnly=true" - } - } - } - - - // Create URL - func getURL(baseURL: BaseURL, version: Version, stock: Stock, endpoint: Endpoint, range: Range, parameters: Parameters) -> String { - let (baseURL, token) = baseURL.path - let version = version.path - let stock = stock.path - let endpoint = endpoint.path - let range = range.path - let parameters = parameters.path - - let url = "\(baseURL)\(version)\(stock)\(endpoint)\(range)\(parameters)&token=\(token)" - - return url - - } - - // Request API - func request(url: String, model: T.Type, completion: @escaping (T) -> Void) { - // We take some model data T.Type - guard let url = URL(string: url) else { - print("Invalid URL") - return - } - 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 { - print(decodedResponse) - completion(decodedResponse) - } - return - } catch { - print(error) - } - } - print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")") - } - .resume() - } -} diff -r 7fef171d4820 -r 096dbea11d43 lazybear/ContentView.swift --- a/lazybear/ContentView.swift Sun Jan 24 19:44:15 2021 +0100 +++ b/lazybear/ContentView.swift Sun Jan 24 20:13:37 2021 +0100 @@ -9,7 +9,7 @@ import CoreData struct ContentView: View { - @State var searchedCompany: String = "" + @State var searchedCompany = String() @State public var showingSearch: Bool = false let persistenceController = PersistenceController.shared diff -r 7fef171d4820 -r 096dbea11d43 lazybear/GoogleApi.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/GoogleApi.swift Sun Jan 24 20:13:37 2021 +0100 @@ -0,0 +1,12 @@ +// +// GoogleApi.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 24/1/21. +// + +import SwiftUI + +struct GoogleApi { + +} diff -r 7fef171d4820 -r 096dbea11d43 lazybear/IexApi.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/IexApi.swift Sun Jan 24 20:13:37 2021 +0100 @@ -0,0 +1,119 @@ +// +// API.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 24/1/21. +// + +import SwiftUI + +struct IexApi { + enum BaseURL { + case sandbox + case production + + var path: (String, String) { + let token = Token() + switch self { + case .sandbox: + return ("https://sandbox.iexapis.com", token.sandbox) + case .production: + return ("https://cloud.iexapis.com", token.production) + } + } + } + + enum Version { + case stable + + var path: String { + switch self { + case .stable: + return "/stable" + } + } + } + + enum Stock { + case symbol(company: String) + var path: String { + switch self { + case let .symbol(company): + return "/stock/\(company)" + } + } + } + + enum Endpoint { + case historicalPrices + var path: String { + switch self { + case .historicalPrices: + return "/chart" + } + } + } + + enum Range { + case period(range: String) + var path: String { + switch self { + case let .period(range): + return "/\(range)?" + } + } + } + + enum Parameters { + case chartCloseOnly + var path: String { + switch self { + case .chartCloseOnly: + return "chartCloseOnly=true" + } + } + } + + + // Create URL + func getURL(baseURL: BaseURL, version: Version, stock: Stock, endpoint: Endpoint, range: Range, parameters: Parameters) -> String { + let (baseURL, token) = baseURL.path + let version = version.path + let stock = stock.path + let endpoint = endpoint.path + let range = range.path + let parameters = parameters.path + + let url = "\(baseURL)\(version)\(stock)\(endpoint)\(range)\(parameters)&token=\(token)" + + return url + + } + + // Request API + func request(url: String, model: T.Type, completion: @escaping (T) -> Void) { + // We take some model data T.Type + guard let url = URL(string: url) else { + print("Invalid URL") + return + } + 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 { + print(decodedResponse) + completion(decodedResponse) + } + return + } catch { + print(error) + } + } + print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")") + } + .resume() + } +} diff -r 7fef171d4820 -r 096dbea11d43 lazybear/LazyBearApp.swift --- a/lazybear/LazyBearApp.swift Sun Jan 24 19:44:15 2021 +0100 +++ b/lazybear/LazyBearApp.swift Sun Jan 24 20:13:37 2021 +0100 @@ -13,7 +13,7 @@ var body: some Scene { WindowGroup { - ContentView() + LoadImageTest() .environment(\.managedObjectContext, persistenceController.container.viewContext) } } diff -r 7fef171d4820 -r 096dbea11d43 lazybear/Tests/LoadImageTest.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Tests/LoadImageTest.swift Sun Jan 24 20:13:37 2021 +0100 @@ -0,0 +1,31 @@ +// +// LoadImageTest.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 24/1/21. +// + +import SwiftUI +import SDWebImageSwiftUI + +struct LoadImageTest: View { + var body: some View { + WebImage(url: URL(string: "https://storage.googleapis.com/iex/api/logos/AAPL.png")) + // Supports options and context, like `.delayPlaceholder` to show placeholder only when error + .onSuccess { image, data, cacheType in + // Success + // Note: Data exist only when queried from disk cache or network. Use `.queryMemoryData` if you really need data + } + .resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size + .placeholder(Image(systemName: "photo")) // Placeholder Image + // Supports ViewBuilder as well + .placeholder { + Rectangle().foregroundColor(.gray) + } + .indicator(.activity) // Activity Indicator + .transition(.fade(duration: 0.5)) // Fade Transition with duration + .scaledToFit() + .frame(width: 300, height: 300, alignment: .center) + } +} +