Mercurial > public > lazybear
changeset 121:c7532d18d6be
Fix bugs NavigationView
line wrap: on
line diff
--- a/LazyBear.xcodeproj/project.pbxproj Fri Feb 05 16:51:25 2021 +0100 +++ b/LazyBear.xcodeproj/project.pbxproj Sat Feb 06 12:33:57 2021 +0100 @@ -9,20 +9,18 @@ /* Begin PBXBuildFile section */ 95002580256D17D9008FFD28 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9500257F256D17D9008FFD28 /* StoreKit.framework */; }; 95078FD125BF4E640004FA75 /* CloudKitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95078FD025BF4E640004FA75 /* CloudKitManager.swift */; }; - 950B79F625B1CB7A00E5DB5B /* CompanyList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 950B79F525B1CB7A00E5DB5B /* CompanyList.swift */; }; 9520F0B225C712D000692610 /* LineChartShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9520F0B125C712D000692610 /* LineChartShape.swift */; }; 9520F0B525C7131300692610 /* LineChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9520F0B425C7131300692610 /* LineChart.swift */; }; 95363CDC25C8741900B74131 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95363CDB25C8741900B74131 /* Request.swift */; }; 95363CE225C87CF000B74131 /* InsiderTransactionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95363CE125C87CF000B74131 /* InsiderTransactionModel.swift */; }; - 95363CE625C87FEC00B74131 /* InsiderTransactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95363CE525C87FEC00B74131 /* InsiderTransactions.swift */; }; - 95363CEA25C8858800B74131 /* TransactionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95363CE925C8858800B74131 /* TransactionRow.swift */; }; 954D992525A2123B001F7F60 /* HistoricalPricesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954D992425A2123B001F7F60 /* HistoricalPricesModel.swift */; }; 954DDF0425C456E800848A4B /* QuoteModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954DDF0325C456E800848A4B /* QuoteModel.swift */; }; 95612C512598D48200F7698F /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95612C4F2598D48200F7698F /* SearchBar.swift */; }; 95621AD925BF2EDB00BB17FC /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95621AD825BF2EDB00BB17FC /* CloudKit.framework */; }; 95825AFC25C7255600465409 /* NormalizeData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95825AFB25C7255600465409 /* NormalizeData.swift */; }; + 9589C94525CE03B20045DFF3 /* SPAlert in Frameworks */ = {isa = PBXBuildFile; productRef = 9589C94425CE03B20045DFF3 /* SPAlert */; }; + 9589C94D25CE0B4C0045DFF3 /* AddWatchlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9589C94C25CE0B4C0045DFF3 /* AddWatchlist.swift */; }; 958B678525C42B2400BF9F89 /* ApiAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = 958B678425C42B2400BF9F89 /* ApiAccess.swift */; }; - 9597CE0125C1DC0A004DDFED /* LogoModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9597CE0025C1DC0A004DDFED /* LogoModifier.swift */; }; 9597CE0425C1DFE7004DDFED /* LogoPlaceholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9597CE0325C1DFE7004DDFED /* LogoPlaceholder.swift */; }; 959D28DC25CC99710029F689 /* NewsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 959D28DB25CC99710029F689 /* NewsModel.swift */; }; 959D28DF25CC9A1A0029F689 /* News.swift in Sources */ = {isa = PBXBuildFile; fileRef = 959D28DE25CC9A1A0029F689 /* News.swift */; }; @@ -30,26 +28,27 @@ 95AB4A7A259DCBAE0064C9C1 /* ReadJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */; }; 95AB4A7D259DCC0C0064C9C1 /* CompanyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */; }; 95AB4A90259DD66D0064C9C1 /* CompanyRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */; }; - 95AD892425C5D8A200BCE8E4 /* AddWatchlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AD892325C5D8A200BCE8E4 /* AddWatchlist.swift */; }; 95B04EB325212369000AD27F /* LazyBearApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B04EB225212369000AD27F /* LazyBearApp.swift */; }; 95B04EB525212369000AD27F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B04EB425212369000AD27F /* ContentView.swift */; }; 95B04EB72521236A000AD27F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95B04EB62521236A000AD27F /* Assets.xcassets */; }; 95B3552825CD4A5600BCDE8E /* NewsDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B3552725CD4A5600BCDE8E /* NewsDetail.swift */; }; - 95B3552C25CD5D7400BCDE8E /* TransactionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B3552B25CD5D7400BCDE8E /* TransactionDetail.swift */; }; 95B3552F25CD629F00BCDE8E /* TransactionCodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95B3552E25CD629F00BCDE8E /* TransactionCodes.swift */; }; 95B395A525BDF42E009A7EB0 /* companies.json in Resources */ = {isa = PBXBuildFile; fileRef = 95B395A425BDF42E009A7EB0 /* companies.json */; }; 95D1BF4925ADCF7700E5D063 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95D1BF4825ADCF7700E5D063 /* Persistence.swift */; }; + 95E07B6825CE92D4001718AB /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E07B6725CE92D4001718AB /* Test.swift */; }; + 95E07B6B25CE9398001718AB /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E07B6A25CE9398001718AB /* AppView.swift */; }; + 95E07B6E25CE95A1001718AB /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E07B6D25CE95A1001718AB /* Search.swift */; }; + 95E07B7225CE95D9001718AB /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E07B7125CE95D9001718AB /* Settings.swift */; }; + 95E07B9D25CEAC46001718AB /* TransactionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E07B9C25CEAC46001718AB /* TransactionDetail.swift */; }; + 95E07BA025CEAC61001718AB /* TransactionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E07B9F25CEAC61001718AB /* TransactionRow.swift */; }; + 95E07BA325CEAC7D001718AB /* Transactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E07BA225CEAC7D001718AB /* Transactions.swift */; }; 95E4118F25BEC35D00A9C23F /* SDWebImageSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 95E4118E25BEC35D00A9C23F /* SDWebImageSwiftUI */; }; - 95E4119225BEC56F00A9C23F /* SuperTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E4119125BEC56F00A9C23F /* SuperTitle.swift */; }; 95E411A725BEE03000A9C23F /* Watchlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E411A625BEE03000A9C23F /* Watchlist.swift */; }; 95E411B625BEE84E00A9C23F /* Stock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E411B525BEE84E00A9C23F /* Stock.swift */; }; 95E411BE25BEEA6C00A9C23F /* WatchlistRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E411BD25BEEA6C00A9C23F /* WatchlistRow.swift */; }; 95F6C2F025BAE2ED003CF389 /* Company.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6C2EF25BAE2ED003CF389 /* Company.swift */; }; - 95F6C30125BAEC8B003CF389 /* CompanyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6C30025BAEC8B003CF389 /* CompanyView.swift */; }; - 95F6C30525BAF599003CF389 /* CompanyHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6C30425BAF599003CF389 /* CompanyHeader.swift */; }; 95F6C30925BAF7C2003CF389 /* DateSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6C30825BAF7C2003CF389 /* DateSelection.swift */; }; 95F6F45C25C20D8D002AC66A /* Price.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6F45B25C20D8D002AC66A /* Price.swift */; }; - 95F6F46125C20E63002AC66A /* ListHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6F46025C20E63002AC66A /* ListHeader.swift */; }; 95F7CAF625ADC7B7009E0E7C /* LazyBear.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 95F7CAF425ADC7B7009E0E7C /* LazyBear.xcdatamodeld */; }; 95FE646725C2DC580052832E /* WatchlistCompany+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FE646525C2DC570052832E /* WatchlistCompany+CoreDataClass.swift */; }; 95FE646825C2DC580052832E /* WatchlistCompany+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FE646625C2DC570052832E /* WatchlistCompany+CoreDataProperties.swift */; }; @@ -60,49 +59,47 @@ 95002578256D1564008FFD28 /* Configuration.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = Configuration.storekit; sourceTree = "<group>"; }; 9500257F256D17D9008FFD28 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; 95078FD025BF4E640004FA75 /* CloudKitManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CloudKitManager.swift; path = LazyBear/CloudKitManager.swift; sourceTree = SOURCE_ROOT; }; - 950B79F525B1CB7A00E5DB5B /* CompanyList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyList.swift; sourceTree = "<group>"; }; - 9520F0B125C712D000692610 /* LineChartShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LineChartShape.swift; path = lazybear/Views/LineChartShape.swift; sourceTree = SOURCE_ROOT; }; - 9520F0B425C7131300692610 /* LineChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LineChart.swift; path = lazybear/Views/LineChart.swift; sourceTree = SOURCE_ROOT; }; + 9520F0B125C712D000692610 /* LineChartShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LineChartShape.swift; path = LazyBear/Views/LineChartShape.swift; sourceTree = SOURCE_ROOT; }; + 9520F0B425C7131300692610 /* LineChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LineChart.swift; path = LazyBear/Views/LineChart.swift; sourceTree = SOURCE_ROOT; }; 95363CDB25C8741900B74131 /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Request.swift; path = lazybear/Network/Request.swift; sourceTree = SOURCE_ROOT; }; 95363CE125C87CF000B74131 /* InsiderTransactionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = InsiderTransactionModel.swift; path = lazybear/Models/InsiderTransactionModel.swift; sourceTree = SOURCE_ROOT; }; - 95363CE525C87FEC00B74131 /* InsiderTransactions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = InsiderTransactions.swift; path = lazybear/Views/InsiderTransactions.swift; sourceTree = SOURCE_ROOT; }; - 95363CE925C8858800B74131 /* TransactionRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TransactionRow.swift; path = lazybear/Views/TransactionRow.swift; sourceTree = SOURCE_ROOT; }; 954D992425A2123B001F7F60 /* HistoricalPricesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = HistoricalPricesModel.swift; path = lazybear/Models/HistoricalPricesModel.swift; sourceTree = SOURCE_ROOT; }; 954DDF0325C456E800848A4B /* QuoteModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = QuoteModel.swift; path = lazybear/Models/QuoteModel.swift; sourceTree = SOURCE_ROOT; }; 95612C4F2598D48200F7698F /* SearchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; }; 95621AD725BF2EC500BB17FC /* LazyBear.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LazyBear.entitlements; sourceTree = "<group>"; }; 95621AD825BF2EDB00BB17FC /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; }; 95825AFB25C7255600465409 /* NormalizeData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NormalizeData.swift; path = lazybear/Jobs/NormalizeData.swift; sourceTree = SOURCE_ROOT; }; + 9589C94C25CE0B4C0045DFF3 /* AddWatchlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AddWatchlist.swift; path = LazyBear/Views/AddWatchlist.swift; sourceTree = SOURCE_ROOT; }; 958B678425C42B2400BF9F89 /* ApiAccess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ApiAccess.swift; path = lazybear/ApiAccess.swift; sourceTree = SOURCE_ROOT; }; - 9597CE0025C1DC0A004DDFED /* LogoModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoModifier.swift; sourceTree = "<group>"; }; 9597CE0325C1DFE7004DDFED /* LogoPlaceholder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoPlaceholder.swift; sourceTree = "<group>"; }; 959D28DB25CC99710029F689 /* NewsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NewsModel.swift; path = lazybear/Models/NewsModel.swift; sourceTree = SOURCE_ROOT; }; - 959D28DE25CC9A1A0029F689 /* News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = News.swift; path = lazybear/Views/News.swift; sourceTree = SOURCE_ROOT; }; - 959D28E125CC9B370029F689 /* NewsRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NewsRow.swift; path = lazybear/Views/NewsRow.swift; sourceTree = SOURCE_ROOT; }; + 959D28DE25CC9A1A0029F689 /* News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = News.swift; path = LazyBear/Views/News.swift; sourceTree = SOURCE_ROOT; }; + 959D28E125CC9B370029F689 /* NewsRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NewsRow.swift; path = LazyBear/Views/NewsRow.swift; sourceTree = SOURCE_ROOT; }; 95AB4A79259DCBAE0064C9C1 /* ReadJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReadJson.swift; path = LazyBear/Jobs/ReadJson.swift; sourceTree = SOURCE_ROOT; }; 95AB4A7C259DCC0C0064C9C1 /* CompanyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompanyModel.swift; path = lazybear/Models/CompanyModel.swift; sourceTree = SOURCE_ROOT; }; 95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyRow.swift; sourceTree = "<group>"; }; - 95AD892325C5D8A200BCE8E4 /* AddWatchlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AddWatchlist.swift; path = lazybear/Views/AddWatchlist.swift; sourceTree = SOURCE_ROOT; }; 95B04EAF25212369000AD27F /* LazyBear.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LazyBear.app; sourceTree = BUILT_PRODUCTS_DIR; }; 95B04EB225212369000AD27F /* LazyBearApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyBearApp.swift; sourceTree = "<group>"; }; 95B04EB425212369000AD27F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; 95B04EB62521236A000AD27F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 95B04EBB2521236A000AD27F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; - 95B3552725CD4A5600BCDE8E /* NewsDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NewsDetail.swift; path = lazybear/Views/NewsDetail.swift; sourceTree = SOURCE_ROOT; }; - 95B3552B25CD5D7400BCDE8E /* TransactionDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TransactionDetail.swift; path = lazybear/Views/TransactionDetail.swift; sourceTree = SOURCE_ROOT; }; + 95B3552725CD4A5600BCDE8E /* NewsDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NewsDetail.swift; path = LazyBear/Views/NewsDetail.swift; sourceTree = SOURCE_ROOT; }; 95B3552E25CD629F00BCDE8E /* TransactionCodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TransactionCodes.swift; path = lazybear/Data/TransactionCodes.swift; sourceTree = SOURCE_ROOT; }; 95B395A425BDF42E009A7EB0 /* companies.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = companies.json; path = lazybear/Data/companies.json; sourceTree = SOURCE_ROOT; }; 95D1BF4825ADCF7700E5D063 /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Persistence.swift; path = LazyBear/Persistence.swift; sourceTree = SOURCE_ROOT; }; - 95E4119125BEC56F00A9C23F /* SuperTitle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuperTitle.swift; sourceTree = "<group>"; }; + 95E07B6725CE92D4001718AB /* Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Test.swift; path = lazybear/Tests/Test.swift; sourceTree = SOURCE_ROOT; }; + 95E07B6A25CE9398001718AB /* AppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppView.swift; path = lazybear/AppView.swift; sourceTree = SOURCE_ROOT; }; + 95E07B6D25CE95A1001718AB /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Search.swift; path = LazyBear/Views/Search.swift; sourceTree = SOURCE_ROOT; }; + 95E07B7125CE95D9001718AB /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Settings.swift; path = LazyBear/Views/Settings.swift; sourceTree = SOURCE_ROOT; }; + 95E07B9C25CEAC46001718AB /* TransactionDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TransactionDetail.swift; path = lazybear/Views/TransactionDetail.swift; sourceTree = SOURCE_ROOT; }; + 95E07B9F25CEAC61001718AB /* TransactionRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TransactionRow.swift; path = lazybear/Views/TransactionRow.swift; sourceTree = SOURCE_ROOT; }; + 95E07BA225CEAC7D001718AB /* Transactions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Transactions.swift; path = lazybear/Views/Transactions.swift; sourceTree = SOURCE_ROOT; }; 95E411A625BEE03000A9C23F /* Watchlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Watchlist.swift; sourceTree = "<group>"; }; 95E411B525BEE84E00A9C23F /* Stock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stock.swift; sourceTree = "<group>"; }; 95E411BD25BEEA6C00A9C23F /* WatchlistRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchlistRow.swift; sourceTree = "<group>"; }; 95F6C2EF25BAE2ED003CF389 /* Company.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Company.swift; sourceTree = "<group>"; }; - 95F6C30025BAEC8B003CF389 /* CompanyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompanyView.swift; path = LazyBear/Views/CompanyView.swift; sourceTree = SOURCE_ROOT; }; - 95F6C30425BAF599003CF389 /* CompanyHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanyHeader.swift; sourceTree = "<group>"; }; 95F6C30825BAF7C2003CF389 /* DateSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateSelection.swift; sourceTree = "<group>"; }; 95F6F45B25C20D8D002AC66A /* Price.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Price.swift; sourceTree = "<group>"; }; - 95F6F46025C20E63002AC66A /* ListHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListHeader.swift; sourceTree = "<group>"; }; 95F7CAF525ADC7B7009E0E7C /* LazyBear.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LazyBear.xcdatamodel; sourceTree = "<group>"; }; 95FE646525C2DC570052832E /* WatchlistCompany+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WatchlistCompany+CoreDataClass.swift"; sourceTree = "<group>"; }; 95FE646625C2DC570052832E /* WatchlistCompany+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WatchlistCompany+CoreDataProperties.swift"; sourceTree = "<group>"; }; @@ -116,6 +113,7 @@ files = ( 95E4118F25BEC35D00A9C23F /* SDWebImageSwiftUI in Frameworks */, 95621AD925BF2EDB00BB17FC /* CloudKit.framework in Frameworks */, + 9589C94525CE03B20045DFF3 /* SPAlert in Frameworks */, 95002580256D17D9008FFD28 /* StoreKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -135,6 +133,7 @@ 952F791C2598B1CD00FF929F /* Tests */ = { isa = PBXGroup; children = ( + 95E07B6725CE92D4001718AB /* Test.swift */, ); path = Tests; sourceTree = "<group>"; @@ -155,30 +154,10 @@ 95945FBE25C440FC00EEA1D0 /* Views */ = { isa = PBXGroup; children = ( - 95E4119125BEC56F00A9C23F /* SuperTitle.swift */, - 95612C4F2598D48200F7698F /* SearchBar.swift */, - 95E411A625BEE03000A9C23F /* Watchlist.swift */, - 95F6F46025C20E63002AC66A /* ListHeader.swift */, - 95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */, - 95E411BD25BEEA6C00A9C23F /* WatchlistRow.swift */, - 9597CE0025C1DC0A004DDFED /* LogoModifier.swift */, - 9597CE0325C1DFE7004DDFED /* LogoPlaceholder.swift */, - 95F6F45B25C20D8D002AC66A /* Price.swift */, - 950B79F525B1CB7A00E5DB5B /* CompanyList.swift */, - 95F6C30025BAEC8B003CF389 /* CompanyView.swift */, - 95F6C2EF25BAE2ED003CF389 /* Company.swift */, - 95E411B525BEE84E00A9C23F /* Stock.swift */, - 95AD892325C5D8A200BCE8E4 /* AddWatchlist.swift */, - 95F6C30425BAF599003CF389 /* CompanyHeader.swift */, - 95F6C30825BAF7C2003CF389 /* DateSelection.swift */, - 9520F0B125C712D000692610 /* LineChartShape.swift */, - 9520F0B425C7131300692610 /* LineChart.swift */, - 95363CE525C87FEC00B74131 /* InsiderTransactions.swift */, - 95363CE925C8858800B74131 /* TransactionRow.swift */, - 959D28DE25CC9A1A0029F689 /* News.swift */, - 959D28E125CC9B370029F689 /* NewsRow.swift */, - 95B3552725CD4A5600BCDE8E /* NewsDetail.swift */, - 95B3552B25CD5D7400BCDE8E /* TransactionDetail.swift */, + 95E07B8125CEA8AB001718AB /* Search */, + 95E07B8E25CEAB30001718AB /* Watchlist */, + 95E07B8525CEA8C8001718AB /* Settings */, + 95E07B9225CEAB6D001718AB /* Company */, ); path = Views; sourceTree = "<group>"; @@ -240,6 +219,7 @@ 95078FD025BF4E640004FA75 /* CloudKitManager.swift */, 958B678425C42B2400BF9F89 /* ApiAccess.swift */, 95B04EB225212369000AD27F /* LazyBearApp.swift */, + 95E07B6A25CE9398001718AB /* AppView.swift */, 95B04EB425212369000AD27F /* ContentView.swift */, 95945FBE25C440FC00EEA1D0 /* Views */, 95945FC025C4415B00EEA1D0 /* Jobs */, @@ -251,6 +231,78 @@ path = LazyBear; sourceTree = "<group>"; }; + 95E07B8125CEA8AB001718AB /* Search */ = { + isa = PBXGroup; + children = ( + 95E07B6D25CE95A1001718AB /* Search.swift */, + 95612C4F2598D48200F7698F /* SearchBar.swift */, + 95AB4A8F259DD66D0064C9C1 /* CompanyRow.swift */, + ); + name = Search; + sourceTree = "<group>"; + }; + 95E07B8525CEA8C8001718AB /* Settings */ = { + isa = PBXGroup; + children = ( + 95E07B7125CE95D9001718AB /* Settings.swift */, + ); + name = Settings; + sourceTree = "<group>"; + }; + 95E07B8E25CEAB30001718AB /* Watchlist */ = { + isa = PBXGroup; + children = ( + 95E411A625BEE03000A9C23F /* Watchlist.swift */, + 95E411BD25BEEA6C00A9C23F /* WatchlistRow.swift */, + 95F6F45B25C20D8D002AC66A /* Price.swift */, + 9597CE0325C1DFE7004DDFED /* LogoPlaceholder.swift */, + ); + name = Watchlist; + sourceTree = "<group>"; + }; + 95E07B9225CEAB6D001718AB /* Company */ = { + isa = PBXGroup; + children = ( + 95F6C2EF25BAE2ED003CF389 /* Company.swift */, + 95E07B9725CEABD4001718AB /* Stock */, + 95E07B9525CEABC8001718AB /* News */, + 95E07B9B25CEABFC001718AB /* Insiders */, + ); + name = Company; + sourceTree = "<group>"; + }; + 95E07B9525CEABC8001718AB /* News */ = { + isa = PBXGroup; + children = ( + 959D28DE25CC9A1A0029F689 /* News.swift */, + 959D28E125CC9B370029F689 /* NewsRow.swift */, + 95B3552725CD4A5600BCDE8E /* NewsDetail.swift */, + ); + name = News; + sourceTree = "<group>"; + }; + 95E07B9725CEABD4001718AB /* Stock */ = { + isa = PBXGroup; + children = ( + 95E411B525BEE84E00A9C23F /* Stock.swift */, + 95F6C30825BAF7C2003CF389 /* DateSelection.swift */, + 9520F0B125C712D000692610 /* LineChartShape.swift */, + 9520F0B425C7131300692610 /* LineChart.swift */, + 9589C94C25CE0B4C0045DFF3 /* AddWatchlist.swift */, + ); + name = Stock; + sourceTree = "<group>"; + }; + 95E07B9B25CEABFC001718AB /* Insiders */ = { + isa = PBXGroup; + children = ( + 95E07BA225CEAC7D001718AB /* Transactions.swift */, + 95E07B9C25CEAC46001718AB /* TransactionDetail.swift */, + 95E07B9F25CEAC61001718AB /* TransactionRow.swift */, + ); + name = Insiders; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -269,6 +321,7 @@ name = LazyBear; packageProductDependencies = ( 95E4118E25BEC35D00A9C23F /* SDWebImageSwiftUI */, + 9589C94425CE03B20045DFF3 /* SPAlert */, ); productName = LazyBear; productReference = 95B04EAF25212369000AD27F /* LazyBear.app */; @@ -299,6 +352,7 @@ mainGroup = 95B04EA625212369000AD27F; packageReferences = ( 95E4118D25BEC35C00A9C23F /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */, + 9589C94325CE03B20045DFF3 /* XCRemoteSwiftPackageReference "SPAlert" */, ); productRefGroup = 95B04EB025212369000AD27F /* Products */; projectDirPath = ""; @@ -328,44 +382,42 @@ files = ( 95AB4A7A259DCBAE0064C9C1 /* ReadJson.swift in Sources */, 95F6F45C25C20D8D002AC66A /* Price.swift in Sources */, - 9597CE0125C1DC0A004DDFED /* LogoModifier.swift in Sources */, 95B3552825CD4A5600BCDE8E /* NewsDetail.swift in Sources */, + 95E07BA025CEAC61001718AB /* TransactionRow.swift in Sources */, + 9589C94D25CE0B4C0045DFF3 /* AddWatchlist.swift in Sources */, 954DDF0425C456E800848A4B /* QuoteModel.swift in Sources */, 959D28E225CC9B370029F689 /* NewsRow.swift in Sources */, 9520F0B525C7131300692610 /* LineChart.swift in Sources */, 9597CE0425C1DFE7004DDFED /* LogoPlaceholder.swift in Sources */, 959D28DF25CC9A1A0029F689 /* News.swift in Sources */, + 95E07B9D25CEAC46001718AB /* TransactionDetail.swift in Sources */, 95FE646B25C30B880052832E /* ApiModel.swift in Sources */, - 95363CE625C87FEC00B74131 /* InsiderTransactions.swift in Sources */, 95B3552F25CD629F00BCDE8E /* TransactionCodes.swift in Sources */, - 95F6C30525BAF599003CF389 /* CompanyHeader.swift in Sources */, - 95363CEA25C8858800B74131 /* TransactionRow.swift in Sources */, 95612C512598D48200F7698F /* SearchBar.swift in Sources */, 95E411BE25BEEA6C00A9C23F /* WatchlistRow.swift in Sources */, - 95AD892425C5D8A200BCE8E4 /* AddWatchlist.swift in Sources */, - 950B79F625B1CB7A00E5DB5B /* CompanyList.swift in Sources */, 95078FD125BF4E640004FA75 /* CloudKitManager.swift in Sources */, 95B04EB525212369000AD27F /* ContentView.swift in Sources */, 95AB4A90259DD66D0064C9C1 /* CompanyRow.swift in Sources */, - 95F6C30125BAEC8B003CF389 /* CompanyView.swift in Sources */, + 95E07B7225CE95D9001718AB /* Settings.swift in Sources */, 959D28DC25CC99710029F689 /* NewsModel.swift in Sources */, 95F6C30925BAF7C2003CF389 /* DateSelection.swift in Sources */, 95F6C2F025BAE2ED003CF389 /* Company.swift in Sources */, - 95F6F46125C20E63002AC66A /* ListHeader.swift in Sources */, 95D1BF4925ADCF7700E5D063 /* Persistence.swift in Sources */, + 95E07B6825CE92D4001718AB /* Test.swift in Sources */, 958B678525C42B2400BF9F89 /* ApiAccess.swift in Sources */, - 95E4119225BEC56F00A9C23F /* SuperTitle.swift in Sources */, 95B04EB325212369000AD27F /* LazyBearApp.swift in Sources */, - 95B3552C25CD5D7400BCDE8E /* TransactionDetail.swift in Sources */, + 95E07B6B25CE9398001718AB /* AppView.swift in Sources */, 95AB4A7D259DCC0C0064C9C1 /* CompanyModel.swift in Sources */, 95E411B625BEE84E00A9C23F /* Stock.swift in Sources */, 9520F0B225C712D000692610 /* LineChartShape.swift in Sources */, + 95E07BA325CEAC7D001718AB /* Transactions.swift in Sources */, 954D992525A2123B001F7F60 /* HistoricalPricesModel.swift in Sources */, 95FE646725C2DC580052832E /* WatchlistCompany+CoreDataClass.swift in Sources */, 95E411A725BEE03000A9C23F /* Watchlist.swift in Sources */, 95825AFC25C7255600465409 /* NormalizeData.swift in Sources */, 95363CDC25C8741900B74131 /* Request.swift in Sources */, 95363CE225C87CF000B74131 /* InsiderTransactionModel.swift in Sources */, + 95E07B6E25CE95A1001718AB /* Search.swift in Sources */, 95F7CAF625ADC7B7009E0E7C /* LazyBear.xcdatamodeld in Sources */, 95FE646825C2DC580052832E /* WatchlistCompany+CoreDataProperties.swift in Sources */, ); @@ -568,6 +620,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 9589C94325CE03B20045DFF3 /* XCRemoteSwiftPackageReference "SPAlert" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/varabeis/SPAlert.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.0.3; + }; + }; 95E4118D25BEC35C00A9C23F /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/SDWebImage/SDWebImageSwiftUI.git"; @@ -579,6 +639,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 9589C94425CE03B20045DFF3 /* SPAlert */ = { + isa = XCSwiftPackageProductDependency; + package = 9589C94325CE03B20045DFF3 /* XCRemoteSwiftPackageReference "SPAlert" */; + productName = SPAlert; + }; 95E4118E25BEC35D00A9C23F /* SDWebImageSwiftUI */ = { isa = XCSwiftPackageProductDependency; package = 95E4118D25BEC35C00A9C23F /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */;
--- a/LazyBear.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Fri Feb 05 16:51:25 2021 +0100 +++ b/LazyBear.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved Sat Feb 06 12:33:57 2021 +0100 @@ -18,6 +18,15 @@ "revision": "4c7f169e39bc35d6b80d42b8eb8301bee9cd0907", "version": "1.5.0" } + }, + { + "package": "SPAlert", + "repositoryURL": "https://github.com/varabeis/SPAlert.git", + "state": { + "branch": null, + "revision": "0c28dc4aa42c4f2c1cef7ad892d5d6ecbb30ebd2", + "version": "3.0.3" + } } ] },
Binary file LazyBear.xcodeproj/project.xcworkspace/xcuserdata/dennis.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/AppView.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,53 @@ +// +// AppView.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 6/2/21. +// + +import SwiftUI +import CloudKit + +struct AppView: View { + let persistenceController = PersistenceController.shared // Core Data + + // <--------- CloudKit ---------> + let cloud = CloudKitManager() + @EnvironmentObject var apiAccess: ApiAccess // Env apis info + @State var cloudFetch = [CKRecord]() { didSet { cloudValues() }} // Fetch arrives here + // <--------- CloudKit ---------> + + var body: some View { + VStack { + if apiAccess.showingView { + ContentView() + .environment(\.managedObjectContext, persistenceController.container.viewContext) + .environmentObject(apiAccess) // Api info (url and token) + } + }.onAppear { cloud.query(recordType: "API") { cloudFetch = $0 } } // Request CloudKit + } + + // Assign CloudKit fetch to model + private func cloudValues() { + var results = [ApiModel]() + cloudFetch.forEach({ (result) in + let key = result.object(forKey: "key") as? String + let name = result.object(forKey: "name") as? String + let url = result.object(forKey: "url") as? String + + let value = ApiModel(key: key, name: name, url: url) + results.append(value) + }) + // Main thread + DispatchQueue.main.async { + apiAccess.results = results + apiAccess.showingView = true + } + } +} + +struct AppView_Previews: PreviewProvider { + static var previews: some View { + AppView() + } +}
--- a/lazybear/ContentView.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/ContentView.swift Sat Feb 06 12:33:57 2021 +0100 @@ -6,57 +6,36 @@ // import SwiftUI -import CoreData -import CloudKit struct ContentView: View { - @State var searchedCompany = String() - @State public var showingSearch: Bool = false - @State var cloudFetch = [CKRecord]() { didSet { cloudValues() }} // CloudKit fetch arrives here - - let persistenceController = PersistenceController.shared // Core data - let cloud = CloudKitManager() // CloudKit fetch function - @EnvironmentObject var apiAccess: ApiAccess // Env apis info + let persistenceController = PersistenceController.shared // Core Data var body: some View { - VStack(alignment: .leading) { - if apiAccess.showingView { - if !showingSearch { - SuperTitle(name: "Home") - } + TabView { + // First view + Search() + .environment(\.managedObjectContext, persistenceController.container.viewContext) + .environmentObject(apiAccess) // Api info (url and token) - SearchBar(searchedText: $searchedCompany, showingSearch: $showingSearch) - - if showingSearch { - if searchedCompany.count > 2 { - CompanyList(searchedCompany: $searchedCompany) - } - Spacer() - } else { - Watchlist() - .transition(.opacity) - } + .tabItem { + Image(systemName: "magnifyingglass") + Text("Search") } - } - .onAppear { cloud.query(recordType: "API") { cloudFetch = $0 } } // Request CloudKit - } - - // Assign CloudKit fetch to model - private func cloudValues() { - var results = [ApiModel]() - cloudFetch.forEach({ (result) in - let key = result.object(forKey: "key") as? String - let name = result.object(forKey: "name") as? String - let url = result.object(forKey: "url") as? String - - let value = ApiModel(key: key, name: name, url: url) - results.append(value) - }) - // Main thread - DispatchQueue.main.async { - apiAccess.results = results - apiAccess.showingView = true + + // Second view + //Watchlist() + //.tabItem { + //Image(systemName: "list.bullet") + //Text("Watchlist") + //} + + // Third view + //Settings() + //.tabItem { + //Image(systemName: "gear") + //Text("Settings") + //} } } } @@ -65,6 +44,5 @@ struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() - .environmentObject(ApiAccess()) } }
--- a/lazybear/LazyBearApp.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/LazyBearApp.swift Sat Feb 06 12:33:57 2021 +0100 @@ -9,12 +9,12 @@ @main struct LazyBearApp: App { - let persistenceController = PersistenceController.shared - var apiAccess = ApiAccess() + let persistenceController = PersistenceController.shared // Core Data + var apiAccess = ApiAccess() // Environment data var body: some Scene { WindowGroup { - ContentView() + AppView() .environment(\.managedObjectContext, persistenceController.container.viewContext) .environmentObject(apiAccess) // Api info (url and token) }
--- a/lazybear/Network/Request.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Network/Request.swift Sat Feb 06 12:33:57 2021 +0100 @@ -21,7 +21,7 @@ // Decode response with the model passed let decodedResponse = try JSONDecoder().decode(model, from: data) DispatchQueue.main.async { - print(decodedResponse) + //print(decodedResponse) completion(decodedResponse) } return
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Tests/Test.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,43 @@ +// +// Test.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 6/2/21. +// + +import SwiftUI + +struct Test: View { + @State private var users = ["Paul", "Taylor", "Adele"] + + var body: some View { + TabView { + // First view + NavigationView { + Text("Hello") + } + .tabItem { + Image(systemName: "magnifyingglass") + Text("Search") + } + + // Second view + Text("Hello") + .tabItem { + Image(systemName: "list.bullet") + Text("Watchlist") + } + + // Third view + Text("Hello") + .tabItem { + Image(systemName: "gear") + Text("Settings") + } + } + } + + func delete(at offsets: IndexSet) { + users.remove(atOffsets: offsets) + } +}
--- a/lazybear/Views/AddWatchlist.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/AddWatchlist.swift Sat Feb 06 12:33:57 2021 +0100 @@ -2,20 +2,33 @@ // AddWatchlist.swift // LazyBear // -// Created by Dennis Concepción Martín on 30/1/21. +// Created by Dennis Concepción Martín on 6/2/21. // import SwiftUI +import SPAlert struct AddWatchlist: View { + var symbol: String var name: String - var symbol: String + // <--------- Core Data ---------> @Environment(\.managedObjectContext) private var viewContext + @FetchRequest(entity: WatchlistCompany.entity(), sortDescriptors: []) + var companies: FetchedResults<WatchlistCompany> + // <--------- Core Data ---------> var body: some View { - Button(action: { addWatchlist(name: name, symbol: symbol) }) { - Text("Add to watchlist") + let watchSymbols = companies.map { $0.symbol } + let alertView = SPAlertView(title: "Company added", preset: .done) + + if !watchSymbols.contains(symbol) { + Button(action: { + addWatchlist(name: name, symbol: symbol) + alertView.present(haptic: .success) + }) { + Text("Add") + } } } @@ -34,6 +47,6 @@ struct AddWatchlist_Previews: PreviewProvider { static var previews: some View { - AddWatchlist(name: "apple inc", symbol: "aapl") + AddWatchlist(symbol: "aapl", name: "apple") } }
--- a/lazybear/Views/Company.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/Company.swift Sat Feb 06 12:33:57 2021 +0100 @@ -11,41 +11,37 @@ var name: String var symbol: String - let persistenceController = PersistenceController.shared - @EnvironmentObject var apiAccess: ApiAccess + @Environment(\.presentationMode) var presentationMode var body: some View { - VStack { - CompanyHeader(name: self.name, symbol: self.symbol) + NavigationView { TabView { - // First view GeometryReader { geo in ScrollView { VStack(alignment: .leading) { Stock(name: name, symbol: symbol, lineChartHeight: geo.size.height*0.2) .padding(.bottom) - .environmentObject(self.apiAccess) News(symbol: symbol) - .environmentObject(self.apiAccess) } - .environment(\.managedObjectContext, persistenceController.container.viewContext) } } - .tabItem { - Image(systemName: "chart.bar.fill") - Text("Stock") - }.tag(0) - - // Second view - InsiderTransactions(symbol: symbol) - .environmentObject(self.apiAccess) - .tabItem { - Image(systemName: "chart.pie.fill") - Text("Insiders") - }.tag(1) + .tabItem { + Image(systemName: "magnifyingglass") + Text("Stock") } } + .navigationBarTitle(symbol, displayMode: .inline) + .navigationBarItems( + leading: + Button(action: { self.presentationMode.wrappedValue.dismiss() }) { + Image(systemName: "multiply") + } + , + trailing: + AddWatchlist(symbol: symbol, name: name) + ) + } } }
--- a/lazybear/Views/CompanyHeader.swift Fri Feb 05 16:51:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -// -// CompanyHeader.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 22/1/21. -// - -import SwiftUI - -struct CompanyHeader: View { - @Environment(\.presentationMode) var presentationMode - var name: String - var symbol: String - - var body: some View { - VStack(alignment: .leading) { - Group { - HStack { - Text(self.symbol.uppercased()) - .font(.title) - .fontWeight(.semibold) - - Spacer() - Button(action: { self.presentationMode.wrappedValue.dismiss() }) { - Image(systemName: "multiply.circle.fill") - } - - } - - Text(self.name.capitalized) - } - .padding([.leading, .trailing]) - Divider() - } - } -} - -struct CompanyHeader_Previews: PreviewProvider { - static var previews: some View { - CompanyHeader(name: "Apple Inc", symbol: "AAPL") - } -}
--- a/lazybear/Views/CompanyList.swift Fri Feb 05 16:51:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -// -// CompanyList.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 15/1/21. -// - -import SwiftUI - -struct CompanyList: View { - @Binding var searchedCompany: String - - var body: some View { - List { - ForEach(companiesData.filter({ searchedCompany.isEmpty ? true : $0.name.localizedStandardContains(searchedCompany) }) - , id: \.symbol) { company in - CompanyRow(company: company) - } - } - .edgesIgnoringSafeArea(.bottom) - .cornerRadius(20) - .id(UUID()) // Increase speed in search the list - } -} - -struct CompanyList_Previews: PreviewProvider { - static var previews: some View { - CompanyList(searchedCompany: .constant("Apple")) - } -}
--- a/lazybear/Views/CompanyRow.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/CompanyRow.swift Sat Feb 06 12:33:57 2021 +0100 @@ -8,22 +8,26 @@ import SwiftUI struct CompanyRow: View { - @ObservedObject var companyView = CompanyView() var company: CompanyModel + @State var showingCompany = false + + @EnvironmentObject var apiAccess: ApiAccess // Env apis info + let persistenceController = PersistenceController.shared // Core Data var body: some View { - Button(action: { companyView.isShowing.toggle() }) { + Button(action: { self.showingCompany.toggle() }) { VStack(alignment: .leading) { Text(company.symbol.uppercased()) .fontWeight(.semibold) Text(company.name.capitalized) - .font(.caption) - + .font(.subheadline) } } - .fullScreenCover(isPresented: $companyView.isShowing) { + .fullScreenCover(isPresented: $showingCompany) { Company(name: company.name, symbol: company.symbol) + .environment(\.managedObjectContext, persistenceController.container.viewContext) + .environmentObject(apiAccess) // Api info (url and token) } } }
--- a/lazybear/Views/CompanyView.swift Fri Feb 05 16:51:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -// -// ShowingCompany.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 22/1/21. -// - -import SwiftUI - -class CompanyView: ObservableObject { - @Published var isShowing: Bool = false { - didSet { - print("Company is showing -> " + String(isShowing)) - } - } -}
--- a/lazybear/Views/InsiderTransactions.swift Fri Feb 05 16:51:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -// -// Insiders.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 1/2/21. -// - -import SwiftUI - -struct InsiderTransactions: View { - var symbol: String - @EnvironmentObject var apiAccess: ApiAccess - - // <--------- API Job ---------> - @State private var url = String() { - didSet { request(url: url, model: [InsiderTransactionModel].self) { self.data = $0 } }} - - @State private var data = [InsiderTransactionModel]() - // <--------- API Job ---------> - - var body: some View { - VStack { - HStack { - Text("Insider transactions") - .font(.title) - .fontWeight(.semibold) - .padding([.leading, .bottom]) - Spacer() - } - .onAppear { getUrl() } - - List { - ForEach(data, id: \.self) { data in - TransactionRow(data: data) - } - } - } - } - - private func getUrl() { - // 1 -> Sandbox / 2 -> Production - let baseUrl = apiAccess.results[2].url ?? "" - let token = apiAccess.results[2].key ?? "" - let path = "/stable/stock/\(symbol)/insider-transactions?token=" - - self.url = baseUrl + path + token - } -} - -struct InsiderTransactions_Previews: PreviewProvider { - static var previews: some View { - InsiderTransactions(symbol: "aapl") - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Views/Insiders/InsiderTransactions.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,54 @@ +// +// Insiders.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 1/2/21. +// + +import SwiftUI + +struct InsiderTransactions: View { + var symbol: String + @EnvironmentObject var apiAccess: ApiAccess + + // <--------- API Job ---------> + @State private var url = String() { + didSet { request(url: url, model: [InsiderTransactionModel].self) { self.data = $0 } }} + + @State private var data = [InsiderTransactionModel]() + // <--------- API Job ---------> + + var body: some View { + VStack { + HStack { + Text("Insider transactions") + .font(.title) + .fontWeight(.semibold) + .padding([.leading, .bottom]) + Spacer() + } + .onAppear { getUrl() } + + List { + ForEach(data, id: \.self) { data in + TransactionRow(data: data) + } + } + } + } + + private func getUrl() { + // 1 -> Sandbox / 2 -> Production + let baseUrl = apiAccess.results[1].url ?? "" + let token = apiAccess.results[1].key ?? "" + let path = "/stable/stock/\(symbol)/insider-transactions?token=" + + self.url = baseUrl + path + token + } +} + +struct InsiderTransactions_Previews: PreviewProvider { + static var previews: some View { + InsiderTransactions(symbol: "aapl") + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Views/Insiders/TransactionDetail.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,83 @@ +// +// TransactionDetail.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 5/2/21. +// + +import SwiftUI + +struct TransactionDetail: View { + @State var data: InsiderTransactionModel + @Environment(\.presentationMode) var transactionDetailPresentation + + var body: some View { + Form { + Section(header: Text("Filling date")) { + HStack { + Image(systemName: "calendar") + Text(data.filingDate ?? "-") + } + } + + Section(header: Text("Owner")) { + HStack { + Image(systemName: "person.fill") + Text(data.fullName ?? "-") + } + let title = data.reportedTitle ?? "" + if !title.isEmpty { + Text(data.reportedTitle ?? "") + } + } + + let postShares = data.postShares ?? 0 + if postShares != 0 { + Section(header: Text("Shares owned after the transaction")) { + HStack { + Image(systemName: "number") + Text(String(postShares)) + } + } + } + + Section(header: Text("Transaction type")) { + let transactionCode = data.transactionCode ?? "" + Text(transactionCodes[transactionCode] ?? "-") + } + + Section(header: Text("Transaction data")) { + let shares = Int(data.transactionShares ?? 0) + if shares != 0 { + Text("Number of shares: \(shares)") + } + let price = data.transactionPrice ?? 0 + if price != 0 { + Text("Price per share: $\(price, specifier: "%.2f")") + } + let value = data.transactionValue ?? 0 + if value != 0 { + Text("Transaction value: $\(value, specifier: "%.2f")") + } + } + } + .navigationBarTitle("Transaction detail") + } +} + +struct TransactionDetail_Previews: PreviewProvider { + static var previews: some View { + TransactionDetail(data: InsiderTransactionModel( + conversionOrExercisePrice: 100, + directIndirect: "D", + filingDate: "2020-10-09", + fullName: "Tim", + postShares: 100, + reportedTitle: "Some reported title", + transactionCode: "I", + transactionDate: "2020-10-09", + transactionPrice: 50, + transactionShares: 1000, + transactionValue: 50000)) + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Views/Insiders/TransactionRow.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,66 @@ +// +// TransactionRow.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 1/2/21. +// + +import SwiftUI + +struct TransactionRow: View { + @State var data: InsiderTransactionModel + @State private var showingDetail = false + + var body: some View { + Button(action: { self.showingDetail.toggle() }) { + HStack { + VStack(alignment: .leading) { + Text(data.fullName?.capitalized ?? "-") + .fontWeight(.semibold) + + Text(data.transactionDate ?? "-") + .font(.subheadline) + } + Spacer() + VStack(alignment: .trailing) { + Text("\(data.transactionShares ?? 0)") + .fontWeight(.semibold) + .foregroundColor(color()) + + Text("Shares") + .font(.subheadline) + } + } + } + .sheet(isPresented: $showingDetail) { + TransactionDetail(data: self.data) + } + } + + private func color() -> Color { + var color: Color = .red + if data.transactionShares ?? 0 >= 0 { + color = .green + } + + return color + } +} + +struct TransactionRow_Previews: PreviewProvider { + static var previews: some View { + TransactionRow(data: InsiderTransactionModel( + conversionOrExercisePrice: 100, + directIndirect: "D", + filingDate: "2020-10-09", + fullName: "Tim", + postShares: 100, + reportedTitle: "Some reported title", + transactionCode: "B", + transactionDate: "2020-10-09", + transactionPrice: 50, + transactionShares: 1000, + transactionValue: 50000) + ) + } +}
--- a/lazybear/Views/ListHeader.swift Fri Feb 05 16:51:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -// -// Header.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 27/1/21. -// - -import SwiftUI - -struct ListHeader: View { - var header: String - - var body: some View { - HStack { - Text(header) - .font(.title) - .fontWeight(.semibold) - - Spacer() - EditButton() - } - .padding([.leading, .trailing]) - } -} - -struct ListHeader_Previews: PreviewProvider { - static var previews: some View { - ListHeader(header: "Header") - } -}
--- a/lazybear/Views/LogoModifier.swift Fri Feb 05 16:51:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -// -// LogoModifier.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 27/1/21. -// - -import SwiftUI - -struct LogoModifier: ViewModifier { - func body(content: Content) -> some View { - content - .aspectRatio(contentMode: .fit) - .frame(maxWidth: 40, maxHeight: 40) - .clipShape(RoundedRectangle(cornerRadius: 3)) - } -}
--- a/lazybear/Views/News.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/News.swift Sat Feb 06 12:33:57 2021 +0100 @@ -37,8 +37,8 @@ private func getUrl() { // 1 -> Sandbox / 2 -> Production - let baseUrl = apiAccess.results[2].url ?? "" - let token = apiAccess.results[2].key ?? "" + let baseUrl = apiAccess.results[1].url ?? "" + let token = apiAccess.results[1].key ?? "" let path = "/stable/stock/\(symbol)/news/last/10?token=" self.url = baseUrl + path + token @@ -48,5 +48,6 @@ struct News_Previews: PreviewProvider { static var previews: some View { News(symbol: "aapl") + .environmentObject(ApiAccess()) } }
--- a/lazybear/Views/Price.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/Price.swift Sat Feb 06 12:33:57 2021 +0100 @@ -10,7 +10,7 @@ struct Price: View { @State var symbol: String - @State var showVertical: Bool + @State var showHorizontal: Bool @EnvironmentObject var apiAccess: ApiAccess // <--------- API Job ---------> @@ -31,13 +31,10 @@ let percent = (data[0].changePercent ?? 0) * 100 Text("\(percent, specifier: "%.2f")%") - .padding(1) .font(.subheadline) - .foregroundColor(.white) - .background(percentageColor().cornerRadius(3)) - + .foregroundColor(percentageColor()) } - .if(showVertical) { content in + .if(showHorizontal) { content in HStack { content } } } @@ -49,8 +46,8 @@ private func getUrl() { // 1 -> Sandbox / 2 -> Production - let baseUrl = apiAccess.results[2].url ?? "" - let token = apiAccess.results[2].key ?? "" + let baseUrl = apiAccess.results[1].url ?? "" + let token = apiAccess.results[1].key ?? "" let path = "/stable/stock/\(symbol)/quote?token=" self.url = baseUrl + path + token @@ -87,6 +84,7 @@ struct Price_Previews: PreviewProvider { static var previews: some View { - Price(symbol: "AAPL", showVertical: false) + Price(symbol: "AAPL", showHorizontal: false) + .environmentObject(ApiAccess()) } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Views/Search.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,39 @@ +// +// Search.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 6/2/21. +// + +import SwiftUI + +struct Search: View { + @State var searchedCompany = String() + @EnvironmentObject var apiAccess: ApiAccess // Env apis info + let persistenceController = PersistenceController.shared // Core Data + + var body: some View { + NavigationView { + VStack { + SearchBar(searchedText: $searchedCompany) + List { + if searchedCompany.count > 2 { + ForEach(companiesData.filter({ searchedCompany.isEmpty ? true : $0.name.localizedStandardContains(searchedCompany) }), id: \.symbol) { company in + CompanyRow(company: company) + .environment(\.managedObjectContext, persistenceController.container.viewContext) + .environmentObject(apiAccess) // Api info (url and token) + } + } + } + .id(UUID()) // Increase speed in search the list + .navigationBarTitle("Search", displayMode: .inline) + } + } .navigationViewStyle(StackNavigationViewStyle()) + } +} + +struct Search_Previews: PreviewProvider { + static var previews: some View { + Search() + } +}
--- a/lazybear/Views/SearchBar.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/SearchBar.swift Sat Feb 06 12:33:57 2021 +0100 @@ -10,7 +10,6 @@ struct SearchBar: View { @Binding var searchedText: String @State var searchBarIsEditing = false - @Binding var showingSearch: Bool // Show search view in ContentView var body: some View { HStack { @@ -40,7 +39,6 @@ .onTapGesture { withAnimation { self.searchBarIsEditing = true - self.showingSearch = true // Content View } } @@ -49,7 +47,6 @@ withAnimation { self.searchedText = "" self.searchBarIsEditing = false - self.showingSearch = false // Content View // Force hide keyboard UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) @@ -66,6 +63,6 @@ struct SearchBar_Previews: PreviewProvider { static var previews: some View { - SearchBar(searchedText: .constant(""), showingSearch: .constant(true)) + SearchBar(searchedText: .constant("")) } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Views/Settings.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,20 @@ +// +// Settings.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 6/2/21. +// + +import SwiftUI + +struct Settings: View { + var body: some View { + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + } +} + +struct Settings_Previews: PreviewProvider { + static var previews: some View { + Settings() + } +}
--- a/lazybear/Views/Stock.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/Stock.swift Sat Feb 06 12:33:57 2021 +0100 @@ -26,21 +26,12 @@ @State private var showingLineChart = false // <--------- API Job ---------> - // <--------- Core Data ---------> - @Environment(\.managedObjectContext) private var viewContext - @FetchRequest(entity: WatchlistCompany.entity(), sortDescriptors: []) - var companies: FetchedResults<WatchlistCompany> - // <--------- Core Data ---------> - var body: some View { VStack { + Divider() HStack { - Price(symbol: symbol, showVertical: true) + Price(symbol: symbol, showHorizontal: true) Spacer() - let watchSymbols = companies.map { $0.symbol } - if !watchSymbols.contains(symbol) { - AddWatchlist(name: name, symbol: symbol) - } } Divider() @@ -64,8 +55,8 @@ var range = range // 1 -> Sandbox / 2 -> Production - let baseUrl = apiAccess.results[2].url ?? "" - let token = apiAccess.results[2].key ?? "" + let baseUrl = apiAccess.results[1].url ?? "" + let token = apiAccess.results[1].key ?? "" if period[selectedPeriod] == "1W" { range = "5dm" } if period[selectedPeriod] == "1M" { range = "1mm" } let path = "/stable/stock/\(symbol)/chart/\(range)?chartCloseOnly=true&includeToday=false&token="
--- a/lazybear/Views/SuperTitle.swift Fri Feb 05 16:51:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -// -// Header.swift -// LazyBear -// -// Created by Dennis Concepción Martín on 25/1/21. -// - -import SwiftUI - -struct SuperTitle: View { - @State var name: String - - var body: some View { - Text(name) - .font(.largeTitle) - .fontWeight(.bold) - .padding() - } -} - -struct SuperTitle_Previews: PreviewProvider { - static var previews: some View { - SuperTitle(name: "Home") - } -}
--- a/lazybear/Views/TransactionDetail.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/TransactionDetail.swift Sat Feb 06 12:33:57 2021 +0100 @@ -2,7 +2,7 @@ // TransactionDetail.swift // LazyBear // -// Created by Dennis Concepción Martín on 5/2/21. +// Created by Dennis Concepción Martín on 6/2/21. // import SwiftUI
--- a/lazybear/Views/TransactionRow.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/TransactionRow.swift Sat Feb 06 12:33:57 2021 +0100 @@ -2,7 +2,7 @@ // TransactionRow.swift // LazyBear // -// Created by Dennis Concepción Martín on 1/2/21. +// Created by Dennis Concepción Martín on 6/2/21. // import SwiftUI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lazybear/Views/Transactions.swift Sat Feb 06 12:33:57 2021 +0100 @@ -0,0 +1,54 @@ +// +// Transactions.swift +// LazyBear +// +// Created by Dennis Concepción Martín on 6/2/21. +// + +import SwiftUI + +struct Transactions: View { + var symbol: String + @EnvironmentObject var apiAccess: ApiAccess + + // <--------- API Job ---------> + @State private var url = String() { + didSet { request(url: url, model: [InsiderTransactionModel].self) { self.data = $0 } }} + + @State private var data = [InsiderTransactionModel]() + // <--------- API Job ---------> + + var body: some View { + VStack { + HStack { + Text("Insider transactions") + .font(.title) + .fontWeight(.semibold) + .padding([.leading, .bottom]) + Spacer() + } + .onAppear { getUrl() } + + List { + ForEach(data, id: \.self) { data in + TransactionRow(data: data) + } + } + } + } + + private func getUrl() { + // 1 -> Sandbox / 2 -> Production + let baseUrl = apiAccess.results[2].url ?? "" + let token = apiAccess.results[2].key ?? "" + let path = "/stable/stock/\(symbol)/insider-transactions?token=" + + self.url = baseUrl + path + token + } +} + +struct Transactions_Previews: PreviewProvider { + static var previews: some View { + Transactions(symbol: "aapl") + } +}
--- a/lazybear/Views/Watchlist.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/Watchlist.swift Sat Feb 06 12:33:57 2021 +0100 @@ -14,12 +14,18 @@ var companies: FetchedResults<WatchlistCompany> // Fetch core data var body: some View { - ListHeader(header: "Watchlist") - List { - ForEach(companies) { company in - WatchlistRow(company: company) + NavigationView { + List { + Section(header: Text("Watchlist")) { + ForEach(companies) { company in + WatchlistRow(company: company) + } + .onDelete { indexSet in deleteWatchlist(indexSet: indexSet) } // Delete from persistent storage + } } - .onDelete { indexSet in deleteWatchlist(indexSet: indexSet) } // Delete from persistent storage + .navigationBarTitle("Watchlist", displayMode: .inline) + .toolbar { EditButton() } + } }
--- a/lazybear/Views/WatchlistRow.swift Fri Feb 05 16:51:25 2021 +0100 +++ b/lazybear/Views/WatchlistRow.swift Sat Feb 06 12:33:57 2021 +0100 @@ -10,41 +10,47 @@ import SDWebImageSwiftUI struct WatchlistRow: View { + var company: WatchlistCompany + @EnvironmentObject var apiAccess: ApiAccess - @ObservedObject var companyView = CompanyView() @Environment(\.editMode) var editMode // EditButton list - var company: WatchlistCompany + let persistenceController = PersistenceController.shared var body: some View { - Button(action: { companyView.isShowing.toggle() }) { - HStack { - let url = apiAccess.results[0].url - let path = "/iex/api/logos/\(company.symbol ?? "").png" - let endpoint = url! + path - WebImage(url: URL(string: endpoint)) - .resizable() - .placeholder { LogoPlaceholder() } // If there is no logo - .indicator(.activity) - .modifier(LogoModifier()) + HStack { + let url = apiAccess.results[0].url + let path = "/iex/api/logos/\(company.symbol ?? "").png" + let endpoint = url! + path + + WebImage(url: URL(string: endpoint)) + .resizable() + .placeholder { LogoPlaceholder() } // If there is no logo + .indicator(.activity) + .modifier(LogoModifier()) + + VStack(alignment: .leading) { + Text(company.symbol ?? "".uppercased()) + .fontWeight(.semibold) - VStack(alignment: .leading) { - Text(company.symbol ?? "".uppercased()) - .fontWeight(.semibold) - - Text(company.name ?? "".capitalized) - .font(.subheadline) - .padding(1) - } - - Spacer() - if self.editMode?.wrappedValue.isEditing ?? true { } else { // If EditButton() is not clicked -> show prices - Price(symbol: company.symbol ?? "", showVertical: false) - } + Text(company.name ?? "".capitalized) + .font(.subheadline) + } + + Spacer() + if self.editMode?.wrappedValue.isEditing ?? true { } else { // If EditButton() is not clicked -> show prices + Price(symbol: company.symbol ?? "", showHorizontal: false) } } - .fullScreenCover(isPresented: $companyView.isShowing) { - Company(name: company.name ?? "", symbol: company.symbol ?? "") - } + .padding([.top, .bottom], 6) + } +} + +struct LogoModifier: ViewModifier { + func body(content: Content) -> some View { + content + .aspectRatio(contentMode: .fit) + .frame(maxWidth: 40, maxHeight: 40) + .clipShape(RoundedRectangle(cornerRadius: 3)) } }