# HG changeset patch # User Dennis C. M. # Date 1666522119 -3600 # Node ID e281791e04946b1de5c3159c0c3d3f8132dbb2ed # Parent f140bb277c96b46341da9abf06be9e0bbca7b15d finish implementation diff -r f140bb277c96 -r e281791e0494 GeoQuiz.xcodeproj/project.pbxproj --- a/GeoQuiz.xcodeproj/project.pbxproj Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz.xcodeproj/project.pbxproj Sun Oct 23 11:48:39 2022 +0100 @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 95030CEA28D1BA4D001AA3A1 /* AnswerButtonHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95030CE928D1BA4D001AA3A1 /* AnswerButtonHelper.swift */; }; + 95030CEA28D1BA4D001AA3A1 /* AnswerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95030CE928D1BA4D001AA3A1 /* AnswerButton.swift */; }; 9509A8DE28E5A19A00CFCDBA /* countries.json in Resources */ = {isa = PBXBuildFile; fileRef = 9509A8DD28E5A19A00CFCDBA /* countries.json */; }; 9509A8E228E5A3D700CFCDBA /* GuessThePopulationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9509A8E128E5A3D700CFCDBA /* GuessThePopulationView.swift */; }; 950C535328F2FA3300179C78 /* BuyPremiumModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 950C535228F2FA3300179C78 /* BuyPremiumModalView.swift */; }; @@ -27,32 +27,34 @@ 9539829328C51EDE00B70973 /* GeoQuizApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9539829228C51EDE00B70973 /* GeoQuizApp.swift */; }; 9539829728C51EDF00B70973 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9539829628C51EDF00B70973 /* Assets.xcassets */; }; 9539829A28C51EDF00B70973 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9539829928C51EDF00B70973 /* Preview Assets.xcassets */; }; + 954AF4682905397A00180065 /* PlayedGamesList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954AF4672905397A00180065 /* PlayedGamesList.swift */; }; + 954AF46A29053D4E00180065 /* LatestGamesPlaceholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954AF46929053D4E00180065 /* LatestGamesPlaceholder.swift */; }; 955950BB28F15FF2001BDEE8 /* FormatterExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955950BA28F15FF2001BDEE8 /* FormatterExtension.swift */; }; - 955A658128D703EB00CEEC6D /* GameToolbarHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955A658028D703EB00CEEC6D /* GameToolbarHelper.swift */; }; + 955A658128D703EB00CEEC6D /* GameToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955A658028D703EB00CEEC6D /* GameToolbar.swift */; }; 955A658328D733E400CEEC6D /* GameProtocol+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955A658228D733E400CEEC6D /* GameProtocol+Extension.swift */; }; 955A65A928D7815E00CEEC6D /* HapticsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955A65A828D7815E00CEEC6D /* HapticsController.swift */; }; - 956273EA28CB2E98008DC094 /* FlagImageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956273E928CB2E98008DC094 /* FlagImageHelper.swift */; }; + 956273EA28CB2E98008DC094 /* FlagImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956273E928CB2E98008DC094 /* FlagImage.swift */; }; 9590359528E098FF00B24560 /* ProfileModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9590359428E098FF00B24560 /* ProfileModalView.swift */; }; 95919DB628F076BF00F21F8F /* UserController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95919DB528F076BF00F21F8F /* UserController.swift */; }; - 95919DBC28F08D0600F21F8F /* LinkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95919DBB28F08D0600F21F8F /* LinkHelper.swift */; }; + 95919DBC28F08D0600F21F8F /* FormLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95919DBB28F08D0600F21F8F /* FormLink.swift */; }; 95A4F42929040E350018DFAC /* CoreDataController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A4F42829040E350018DFAC /* CoreDataController.swift */; }; - 95A4F42B29043DC00018DFAC /* UserImageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A4F42A29043DC00018DFAC /* UserImageHelper.swift */; }; + 95A4F42B29043DC00018DFAC /* UserImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A4F42A29043DC00018DFAC /* UserImage.swift */; }; 95AE8D5728C8750E0067F219 /* FileController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AE8D5628C8750E0067F219 /* FileController.swift */; }; 95AF322A28DF293900023ACC /* GuessTheCountryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AF322928DF293900023ACC /* GuessTheCountryView.swift */; }; - 95BC392D28EC42570049AB49 /* CityMapHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BC392C28EC42570049AB49 /* CityMapHelper.swift */; }; + 95BC392D28EC42570049AB49 /* CityMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BC392C28EC42570049AB49 /* CityMap.swift */; }; 95C430F928D0A8E500480D23 /* GradientExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C430F828D0A8E500480D23 /* GradientExtension.swift */; }; 95C4315628C64A8C00212131 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C4315528C64A8C00212131 /* ContentView.swift */; }; - 95C4315928C6500000212131 /* GameButtonHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C4315828C6500000212131 /* GameButtonHelper.swift */; }; + 95C4315928C6500000212131 /* GameButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C4315828C6500000212131 /* GameButton.swift */; }; 95C6456C28FE87E4000CD570 /* UserDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6456B28FE87E4000CD570 /* UserDataModel.swift */; }; - 95C6456E28FE8C04000CD570 /* UserProfileHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6456D28FE8C04000CD570 /* UserProfileHelper.swift */; }; + 95C6456E28FE8C04000CD570 /* UserProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6456D28FE8C04000CD570 /* UserProfile.swift */; }; 95C6457228FFC4DC000CD570 /* ProfileEditModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6457128FFC4DC000CD570 /* ProfileEditModalView.swift */; }; 95C6457428FFC8E0000CD570 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6457328FFC8E0000CD570 /* PersistenceController.swift */; }; 95C6457728FFC934000CD570 /* GeoQuiz.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 95C6457528FFC934000CD570 /* GeoQuiz.xcdatamodeld */; }; 95C6459A28FFE5A3000CD570 /* PlayedGame+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6459828FFE5A3000CD570 /* PlayedGame+CoreDataClass.swift */; }; 95C6459B28FFE5A3000CD570 /* PlayedGame+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6459928FFE5A3000CD570 /* PlayedGame+CoreDataProperties.swift */; }; - 95C6459D290003E1000CD570 /* RecentGameHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6459C290003E1000CD570 /* RecentGameHelper.swift */; }; + 95C6459D290003E1000CD570 /* RecentGame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C6459C290003E1000CD570 /* RecentGame.swift */; }; 95C645C229014442000CD570 /* GameInfoProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95C645C129014442000CD570 /* GameInfoProtocol.swift */; }; - 95CA295028F6BB4500CE0B7A /* ActivityAlertHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95CA294F28F6BB4500CE0B7A /* ActivityAlertHelper.swift */; }; + 95CA295028F6BB4500CE0B7A /* ActivityAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95CA294F28F6BB4500CE0B7A /* ActivityAlert.swift */; }; 95DB7C01290492FC007D01D8 /* GameInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95DB7C00290492FC007D01D8 /* GameInfoController.swift */; }; 95DB7C032904A968007D01D8 /* MapController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95DB7C022904A968007D01D8 /* MapController.swift */; }; 95FA409A28D9876B00129B60 /* GuessTheFlagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FA409928D9876B00129B60 /* GuessTheFlagView.swift */; }; @@ -60,7 +62,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 95030CE928D1BA4D001AA3A1 /* AnswerButtonHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnswerButtonHelper.swift; sourceTree = ""; }; + 95030CE928D1BA4D001AA3A1 /* AnswerButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnswerButton.swift; sourceTree = ""; }; 9509A8DD28E5A19A00CFCDBA /* countries.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = countries.json; sourceTree = ""; }; 9509A8E128E5A3D700CFCDBA /* GuessThePopulationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuessThePopulationView.swift; sourceTree = ""; }; 950C535228F2FA3300179C78 /* BuyPremiumModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyPremiumModalView.swift; sourceTree = ""; }; @@ -80,32 +82,35 @@ 9539829228C51EDE00B70973 /* GeoQuizApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoQuizApp.swift; sourceTree = ""; }; 9539829628C51EDF00B70973 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 9539829928C51EDF00B70973 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 954AF4672905397A00180065 /* PlayedGamesList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayedGamesList.swift; sourceTree = ""; }; + 954AF46929053D4E00180065 /* LatestGamesPlaceholder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestGamesPlaceholder.swift; sourceTree = ""; }; + 954AF46B2905433300180065 /* GeoQuiz.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GeoQuiz.entitlements; sourceTree = ""; }; 955950BA28F15FF2001BDEE8 /* FormatterExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormatterExtension.swift; sourceTree = ""; }; - 955A658028D703EB00CEEC6D /* GameToolbarHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameToolbarHelper.swift; sourceTree = ""; }; + 955A658028D703EB00CEEC6D /* GameToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameToolbar.swift; sourceTree = ""; }; 955A658228D733E400CEEC6D /* GameProtocol+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GameProtocol+Extension.swift"; sourceTree = ""; }; 955A65A828D7815E00CEEC6D /* HapticsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticsController.swift; sourceTree = ""; }; - 956273E928CB2E98008DC094 /* FlagImageHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagImageHelper.swift; sourceTree = ""; }; + 956273E928CB2E98008DC094 /* FlagImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagImage.swift; sourceTree = ""; }; 9590359428E098FF00B24560 /* ProfileModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModalView.swift; sourceTree = ""; }; 95919DB528F076BF00F21F8F /* UserController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserController.swift; sourceTree = ""; }; - 95919DBB28F08D0600F21F8F /* LinkHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkHelper.swift; sourceTree = ""; }; + 95919DBB28F08D0600F21F8F /* FormLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLink.swift; sourceTree = ""; }; 95A4F42829040E350018DFAC /* CoreDataController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataController.swift; sourceTree = ""; }; - 95A4F42A29043DC00018DFAC /* UserImageHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserImageHelper.swift; sourceTree = ""; }; + 95A4F42A29043DC00018DFAC /* UserImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserImage.swift; sourceTree = ""; }; 95AE8D5628C8750E0067F219 /* FileController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileController.swift; sourceTree = ""; }; 95AF322928DF293900023ACC /* GuessTheCountryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuessTheCountryView.swift; sourceTree = ""; }; - 95BC392C28EC42570049AB49 /* CityMapHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityMapHelper.swift; sourceTree = ""; }; + 95BC392C28EC42570049AB49 /* CityMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityMap.swift; sourceTree = ""; }; 95C430F828D0A8E500480D23 /* GradientExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientExtension.swift; sourceTree = ""; }; 95C4315528C64A8C00212131 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - 95C4315828C6500000212131 /* GameButtonHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameButtonHelper.swift; sourceTree = ""; }; + 95C4315828C6500000212131 /* GameButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameButton.swift; sourceTree = ""; }; 95C6456B28FE87E4000CD570 /* UserDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDataModel.swift; sourceTree = ""; }; - 95C6456D28FE8C04000CD570 /* UserProfileHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileHelper.swift; sourceTree = ""; }; + 95C6456D28FE8C04000CD570 /* UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfile.swift; sourceTree = ""; }; 95C6457128FFC4DC000CD570 /* ProfileEditModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileEditModalView.swift; sourceTree = ""; }; 95C6457328FFC8E0000CD570 /* PersistenceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = ""; }; 95C6457628FFC934000CD570 /* GeoQuiz.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = GeoQuiz.xcdatamodel; sourceTree = ""; }; 95C6459828FFE5A3000CD570 /* PlayedGame+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PlayedGame+CoreDataClass.swift"; sourceTree = ""; }; 95C6459928FFE5A3000CD570 /* PlayedGame+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PlayedGame+CoreDataProperties.swift"; sourceTree = ""; }; - 95C6459C290003E1000CD570 /* RecentGameHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentGameHelper.swift; sourceTree = ""; }; + 95C6459C290003E1000CD570 /* RecentGame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentGame.swift; sourceTree = ""; }; 95C645C129014442000CD570 /* GameInfoProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameInfoProtocol.swift; sourceTree = ""; }; - 95CA294F28F6BB4500CE0B7A /* ActivityAlertHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityAlertHelper.swift; sourceTree = ""; }; + 95CA294F28F6BB4500CE0B7A /* ActivityAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityAlert.swift; sourceTree = ""; }; 95DB7C00290492FC007D01D8 /* GameInfoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameInfoController.swift; sourceTree = ""; }; 95DB7C022904A968007D01D8 /* MapController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapController.swift; sourceTree = ""; }; 95E6188428DDDB5C003359ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; @@ -189,6 +194,7 @@ 9539829128C51EDE00B70973 /* GeoQuiz */ = { isa = PBXGroup; children = ( + 954AF46B2905433300180065 /* GeoQuiz.entitlements */, 95E6188428DDDB5C003359ED /* Info.plist */, 9539829628C51EDF00B70973 /* Assets.xcassets */, 95C6457528FFC934000CD570 /* GeoQuiz.xcdatamodeld */, @@ -221,17 +227,19 @@ 959D414728C87EA600BAAC14 /* Components */ = { isa = PBXGroup; children = ( - 95C4315828C6500000212131 /* GameButtonHelper.swift */, - 956273E928CB2E98008DC094 /* FlagImageHelper.swift */, - 95030CE928D1BA4D001AA3A1 /* AnswerButtonHelper.swift */, - 955A658028D703EB00CEEC6D /* GameToolbarHelper.swift */, - 95BC392C28EC42570049AB49 /* CityMapHelper.swift */, - 95919DBB28F08D0600F21F8F /* LinkHelper.swift */, - 95CA294F28F6BB4500CE0B7A /* ActivityAlertHelper.swift */, - 95C6456D28FE8C04000CD570 /* UserProfileHelper.swift */, - 95A4F42A29043DC00018DFAC /* UserImageHelper.swift */, - 95C6459C290003E1000CD570 /* RecentGameHelper.swift */, + 95C4315828C6500000212131 /* GameButton.swift */, + 956273E928CB2E98008DC094 /* FlagImage.swift */, + 95030CE928D1BA4D001AA3A1 /* AnswerButton.swift */, + 955A658028D703EB00CEEC6D /* GameToolbar.swift */, + 95BC392C28EC42570049AB49 /* CityMap.swift */, + 95919DBB28F08D0600F21F8F /* FormLink.swift */, + 95CA294F28F6BB4500CE0B7A /* ActivityAlert.swift */, + 95C6456D28FE8C04000CD570 /* UserProfile.swift */, + 95A4F42A29043DC00018DFAC /* UserImage.swift */, + 95C6459C290003E1000CD570 /* RecentGame.swift */, + 954AF4672905397A00180065 /* PlayedGamesList.swift */, 952E41E828DC521200198643 /* GameAlertsModifier.swift */, + 954AF46929053D4E00180065 /* LatestGamesPlaceholder.swift */, 95C430F828D0A8E500480D23 /* GradientExtension.swift */, 951D197228D485E000671FAD /* ColorExtension.swift */, 955950BA28F15FF2001BDEE8 /* FormatterExtension.swift */, @@ -320,9 +328,9 @@ buildActionMask = 2147483647; files = ( 955A65A928D7815E00CEEC6D /* HapticsController.swift in Sources */, - 95BC392D28EC42570049AB49 /* CityMapHelper.swift in Sources */, + 95BC392D28EC42570049AB49 /* CityMap.swift in Sources */, 95C6459A28FFE5A3000CD570 /* PlayedGame+CoreDataClass.swift in Sources */, - 95A4F42B29043DC00018DFAC /* UserImageHelper.swift in Sources */, + 95A4F42B29043DC00018DFAC /* UserImage.swift in Sources */, 952E41E928DC521200198643 /* GameAlertsModifier.swift in Sources */, 95197EFD28F339AE00FE67E9 /* StoreKitController.swift in Sources */, 9509A8E228E5A3D700CFCDBA /* GuessThePopulationView.swift in Sources */, @@ -330,24 +338,26 @@ 95A4F42929040E350018DFAC /* CoreDataController.swift in Sources */, 95C6457428FFC8E0000CD570 /* PersistenceController.swift in Sources */, 95919DB628F076BF00F21F8F /* UserController.swift in Sources */, - 95C6459D290003E1000CD570 /* RecentGameHelper.swift in Sources */, - 95C6456E28FE8C04000CD570 /* UserProfileHelper.swift in Sources */, + 95C6459D290003E1000CD570 /* RecentGame.swift in Sources */, + 95C6456E28FE8C04000CD570 /* UserProfile.swift in Sources */, 95C4315628C64A8C00212131 /* ContentView.swift in Sources */, 95C645C229014442000CD570 /* GameInfoProtocol.swift in Sources */, - 95C4315928C6500000212131 /* GameButtonHelper.swift in Sources */, - 956273EA28CB2E98008DC094 /* FlagImageHelper.swift in Sources */, + 954AF4682905397A00180065 /* PlayedGamesList.swift in Sources */, + 95C4315928C6500000212131 /* GameButton.swift in Sources */, + 956273EA28CB2E98008DC094 /* FlagImage.swift in Sources */, 951AFAED28E5657500A4A4BD /* CityModel.swift in Sources */, 950C535328F2FA3300179C78 /* BuyPremiumModalView.swift in Sources */, + 954AF46A29053D4E00180065 /* LatestGamesPlaceholder.swift in Sources */, 951B630228D1A87C004F9877 /* GuessTheCapitalView.swift in Sources */, 9539829328C51EDE00B70973 /* GeoQuizApp.swift in Sources */, 95AF322A28DF293900023ACC /* GuessTheCountryView.swift in Sources */, 95DB7C032904A968007D01D8 /* MapController.swift in Sources */, - 95919DBC28F08D0600F21F8F /* LinkHelper.swift in Sources */, + 95919DBC28F08D0600F21F8F /* FormLink.swift in Sources */, 951AFAEF28E565FE00A4A4BD /* CountryModel.swift in Sources */, - 95030CEA28D1BA4D001AA3A1 /* AnswerButtonHelper.swift in Sources */, + 95030CEA28D1BA4D001AA3A1 /* AnswerButton.swift in Sources */, 95FA409C28D9881100129B60 /* CountryGameController.swift in Sources */, - 95CA295028F6BB4500CE0B7A /* ActivityAlertHelper.swift in Sources */, - 955A658128D703EB00CEEC6D /* GameToolbarHelper.swift in Sources */, + 95CA295028F6BB4500CE0B7A /* ActivityAlert.swift in Sources */, + 955A658128D703EB00CEEC6D /* GameToolbar.swift in Sources */, 95AE8D5728C8750E0067F219 /* FileController.swift in Sources */, 95C6457728FFC934000CD570 /* GeoQuiz.xcdatamodeld in Sources */, 9590359528E098FF00B24560 /* ProfileModalView.swift in Sources */, @@ -486,6 +496,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = GeoQuiz/GeoQuiz.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"GeoQuiz/Preview Content\""; @@ -520,6 +531,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = GeoQuiz/GeoQuiz.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"GeoQuiz/Preview Content\""; diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/ActivityAlert.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/ActivityAlert.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,26 @@ +// +// ActivityAlert.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 12/10/22. +// + +import SwiftUI + +struct ActivityAlert: View { + var body: some View { + VStack(spacing: 10) { + ProgressView() + Text("Loading") + } + .padding() + .background(.regularMaterial) + .cornerRadius(10) + } +} + +struct ActivityAlert_Previews: PreviewProvider { + static var previews: some View { + ActivityAlert() + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/ActivityAlertHelper.swift --- a/GeoQuiz/Components/ActivityAlertHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -// -// ActivityAlertHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 12/10/22. -// - -import SwiftUI - -struct ActivityAlert: View { - var body: some View { - VStack(spacing: 10) { - ProgressView() - Text("Loading") - } - .padding() - .background(.regularMaterial) - .cornerRadius(10) - } -} - -struct ActivityAlert_Previews: PreviewProvider { - static var previews: some View { - ActivityAlert() - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/AnswerButton.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/AnswerButton.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,39 @@ +// +// AnswerButton.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 14/9/22. +// + +import SwiftUI + +struct AnswerButton: View { + let name: String + let color: Color + + var body: some View { + RoundedRectangle(cornerRadius: 15) + .foregroundColor(.white) + .overlay( + Text(name) + .font(.title2.bold()) + .foregroundColor(color) + ) + } +} + +struct AnswerButton_Previews: PreviewProvider { + static var previews: some View { + ZStack { + LinearGradient(gradient: .main, startPoint: .top, endPoint: .bottom) + .ignoresSafeArea() + + VStack { + Spacer() + AnswerButton(name: "Madrid", color: .royalLightBlue) + .frame(height: 70) + } + .padding() + } + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/AnswerButtonHelper.swift --- a/GeoQuiz/Components/AnswerButtonHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -// -// AnswerButtonHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 14/9/22. -// - -import SwiftUI - -struct AnswerButton: View { - let name: String - let color: Color - - var body: some View { - RoundedRectangle(cornerRadius: 15) - .foregroundColor(.white) - .overlay( - Text(name) - .font(.title2.bold()) - .foregroundColor(color) - ) - } -} - -struct AnswerButton_Previews: PreviewProvider { - static var previews: some View { - ZStack { - LinearGradient(gradient: .main, startPoint: .top, endPoint: .bottom) - .ignoresSafeArea() - - VStack { - Spacer() - AnswerButton(name: "Madrid", color: .royalLightBlue) - .frame(height: 70) - } - .padding() - } - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/CityMap.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/CityMap.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,51 @@ +// +// CityMap.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 4/10/22. +// + +import SwiftUI +import MapKit + +struct CityMap: View { + @ObservedObject var game: CityGameController + + @StateObject var mapController: MapController + + init(game: CityGameController) { + self.game = game + self._mapController = StateObject(wrappedValue: MapController()) + } + + var body: some View { + VStack { + if let mapImage = mapController.image { + Image(uiImage: mapImage) + .resizable() + .scaledToFit() + .clipShape(Circle()) + .overlay { + Circle() + .strokeBorder(.white, lineWidth: 4) + } + .shadow(radius: 10) + } else { + ProgressView() + } + } + .onChange(of: game.correctAnswer.value) { _ in + mapController.getMapImage(lat: game.correctAnswer.value.lat, lon: game.correctAnswer.value.lon) + } + + .onAppear { + mapController.getMapImage(lat: game.correctAnswer.value.lat, lon: game.correctAnswer.value.lon) + } + } +} + +struct CityMap_Previews: PreviewProvider { + static var previews: some View { + CityMap(game: CityGameController()) + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/CityMapHelper.swift --- a/GeoQuiz/Components/CityMapHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -// -// CityMapHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 4/10/22. -// - -import SwiftUI -import MapKit - -struct CityMap: View { - @ObservedObject var game: CityGameController - - @StateObject var mapController: MapController - - init(game: CityGameController) { - self.game = game - self._mapController = StateObject(wrappedValue: MapController()) - } - - var body: some View { - VStack { - if let mapImage = mapController.image { - Image(uiImage: mapImage) - .resizable() - .scaledToFit() - .clipShape(Circle()) - .overlay { - Circle() - .strokeBorder(.white, lineWidth: 4) - } - .shadow(radius: 10) - } else { - ProgressView() - } - } - .onChange(of: game.correctAnswer.value) { _ in - mapController.getMapImage(lat: game.correctAnswer.value.lat, lon: game.correctAnswer.value.lon) - } - - .onAppear { - mapController.getMapImage(lat: game.correctAnswer.value.lat, lon: game.correctAnswer.value.lon) - } - } -} - -struct CityMap_Previews: PreviewProvider { - static var previews: some View { - CityMap(game: CityGameController()) - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/FlagImage.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/FlagImage.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,28 @@ +// +// FlagImage.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 9/9/22. +// + +import SwiftUI + +struct FlagImage: View { + var flagSymbol: String + + @Environment(\.colorScheme) var colorScheme + + var body: some View { + Image(flagSymbol) + .renderingMode(.original) + .resizable() + .scaledToFill() + } +} + +struct FlagImage_Previews: PreviewProvider { + static var previews: some View { + FlagImage(flagSymbol: "es") + .frame(height: 130) + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/FlagImageHelper.swift --- a/GeoQuiz/Components/FlagImageHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -// -// FlagImageHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 9/9/22. -// - -import SwiftUI - -struct FlagImage: View { - var flagSymbol: String - var cornerRadius: Double - - @Environment(\.colorScheme) var colorScheme - - var body: some View { - Image(flagSymbol) - .renderingMode(.original) - .resizable() - .scaledToFit() - } -} - -struct FlagImage_Previews: PreviewProvider { - static var previews: some View { - FlagImage(flagSymbol: "es", cornerRadius: 20) - .frame(height: 130) - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/FormLink.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/FormLink.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,41 @@ +// +// FormLink.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 7/10/22. +// + +import SwiftUI + +struct FormLink: View { + var color: Color + var symbol: String + var text: String + var url: URL + + @Environment(\.openURL) var openURL + + var body: some View { + Link(destination: url) { + HStack(alignment: .center, spacing: 20) { + Image(systemName: symbol) + .imageScale(.large) + .foregroundColor(color) + + Text(text) + .foregroundColor(.primary) + } + } + } +} + +struct FormLink_Previews: PreviewProvider { + static var previews: some View { + FormLink( + color: .mayaBlue, + symbol: "info.circle.fill", + text: "About", + url: URL(string: "https://dennistech.io")! + ) + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/GameButton.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/GameButton.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,64 @@ +// +// GameButton.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 5/9/22. +// + +import SwiftUI + +struct GameButton: View { + let gameInfo: GameInfo + let isActive: Bool + + init(gameType: GameType, isActive: Bool) { + self.gameInfo = GameInfoController.getInfo(for: gameType) + self.isActive = isActive + } + + var body: some View { + RoundedRectangle(cornerRadius: 20) + .fill( + LinearGradient( + gradient: gameInfo.gradient, + startPoint: .trailing, endPoint: .leading + ) + ) + .frame(height: 180) + .frame(maxWidth: 700) + .overlay { + ZStack(alignment: .trailing) { + VStack(alignment: .leading) { + HStack { + Image(systemName: isActive ? gameInfo.symbol : "lock.fill") + .font(.headline) + .padding(5) + .background( + RoundedRectangle(cornerRadius: 5) + .stroke(lineWidth: 1.5) + ) + + Spacer() + } + .padding(.bottom) + + VStack(alignment: .leading, spacing: 5) { + Text(gameInfo.level) + .font(.callout) + + Text(gameInfo.name) + .font(.title.bold()) + } + } + .foregroundColor(.white) + .padding() + } + } + } +} + +struct GameButton_Previews: PreviewProvider { + static var previews: some View { + GameButton(gameType: .guessTheFlag, isActive: false) + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/GameButtonHelper.swift --- a/GeoQuiz/Components/GameButtonHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -// -// GameButtonHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 5/9/22. -// - -import SwiftUI - -struct GameButton: View { - let gameInfo: GameInfo - let isActive: Bool - - init(gameType: GameType, isActive: Bool) { - self.gameInfo = GameInfoController.getInfo(for: gameType) - self.isActive = isActive - } - - var body: some View { - RoundedRectangle(cornerRadius: 20) - .fill( - LinearGradient( - gradient: gameInfo.gradient, - startPoint: .trailing, endPoint: .leading - ) - ) - .frame(height: 180) - .frame(maxWidth: 700) - .overlay { - ZStack(alignment: .trailing) { - VStack(alignment: .leading) { - HStack { - Image(systemName: isActive ? gameInfo.symbol : "lock.fill") - .font(.headline) - .padding(5) - .background( - RoundedRectangle(cornerRadius: 5) - .stroke(lineWidth: 1.5) - ) - - Spacer() - } - .padding(.bottom) - - VStack(alignment: .leading, spacing: 5) { - Text(gameInfo.level) - .font(.callout) - - Text(gameInfo.name) - .font(.title.bold()) - } - } - .foregroundColor(.white) - .padding() - } - } - } -} - -struct GameButton_Previews: PreviewProvider { - static var previews: some View { - GameButton(gameType: .guessTheFlag, isActive: false) - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/GameToolbar.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/GameToolbar.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,90 @@ +// +// GameToolbar.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 18/9/22. +// + +import SwiftUI + +struct GameToolbar: View { + @ObservedObject var game: T + + var color: Color + + var body: some View { + HStack(spacing: 0) { + Group { + Button { + game.showingExitGameAlert = true + } label: { + Image(systemName: "multiply") + .font(.headline) + .foregroundColor(color) + .padding(10) + .background( + Circle() + .foregroundColor(.white) + ) + } + } + .font(.headline) + .frame(maxWidth: .infinity, alignment: .leading) + + Group { + Text("\(game.userScore)") + .font(.title.bold()) + .foregroundColor(color) + .padding() + .background( + Group { + if game.userScore < 1000 { + Circle() + } else { + Capsule() + } + } + .foregroundColor(.white) + ) + } + .font(.title2) + .scaleEffect(game.scoreScaleAmount) + .frame(maxWidth: .infinity, alignment: .center) + + Group { + HStack { + Image(systemName: "heart.fill") + Text("\(game.userLives)") + } + .font(.headline) + .foregroundColor(color) + .padding(10) + .background( + Capsule() + .foregroundColor(.white) + ) + .scaleEffect(game.livesScaleAmount) + } + .font(.headline) + .frame(maxWidth: .infinity, alignment: .trailing) + } + } +} + +struct GameToolbar_Previews: PreviewProvider { + static var previews: some View { + ZStack { + LinearGradient(gradient: .main, startPoint: .top, endPoint: .bottom) + .ignoresSafeArea() + + GeometryReader { geo in + VStack { + GameToolbar(game: CountryGameController(), color: .mayaBlue) + + Spacer() + } + .padding() + } + } + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/GameToolbarHelper.swift --- a/GeoQuiz/Components/GameToolbarHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -// -// GameToolbarHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 18/9/22. -// - -import SwiftUI - -struct GameToolbar: View { - @ObservedObject var game: T - - var color: Color - - var body: some View { - HStack(spacing: 0) { - Group { - Button { - game.showingExitGameAlert = true - } label: { - Image(systemName: "multiply") - .font(.headline) - .foregroundColor(color) - .padding(10) - .background( - Circle() - .foregroundColor(.white) - ) - } - } - .font(.headline) - .frame(maxWidth: .infinity, alignment: .leading) - - Group { - Text("\(game.userScore)") - .font(.title.bold()) - .foregroundColor(color) - .padding() - .background( - Group { - if game.userScore < 1000 { - Circle() - } else { - Capsule() - } - } - .foregroundColor(.white) - ) - } - .font(.title2) - .scaleEffect(game.scoreScaleAmount) - .frame(maxWidth: .infinity, alignment: .center) - - Group { - HStack { - Image(systemName: "heart.fill") - Text("\(game.userLives)") - } - .font(.headline) - .foregroundColor(color) - .padding(10) - .background( - Capsule() - .foregroundColor(.white) - ) - .scaleEffect(game.livesScaleAmount) - } - .font(.headline) - .frame(maxWidth: .infinity, alignment: .trailing) - } - } -} - -struct GameToolbar_Previews: PreviewProvider { - static var previews: some View { - ZStack { - LinearGradient(gradient: .main, startPoint: .top, endPoint: .bottom) - .ignoresSafeArea() - - GeometryReader { geo in - VStack { - GameToolbar(game: CountryGameController(), color: .mayaBlue) - - Spacer() - } - .padding() - } - } - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/LatestGamesPlaceholder.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/LatestGamesPlaceholder.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,24 @@ +// +// LatestGamesPlaceholder.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 23/10/22. +// + +import SwiftUI + +struct LatestGamesPlaceholder: View { + var body: some View { + VStack(spacing: 20) { + Image(systemName: "gamecontroller.fill") + Text("No recently played games") + } + .foregroundColor(.secondary) + } +} + +struct LatestGamesPlaceholder_Previews: PreviewProvider { + static var previews: some View { + LatestGamesPlaceholder() + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/LinkHelper.swift --- a/GeoQuiz/Components/LinkHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -// -// LinkHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 7/10/22. -// - -import SwiftUI - -struct LinkComponent: View { - var color: Color - var symbol: String - var text: String - var url: URL - - @Environment(\.openURL) var openURL - - var body: some View { - Link(destination: url) { - HStack(alignment: .center, spacing: 20) { - Image(systemName: symbol) - .imageScale(.large) - .foregroundColor(color) - - Text(text) - .foregroundColor(.primary) - } - } - } -} - -struct LinkComponent_Previews: PreviewProvider { - static var previews: some View { - LinkComponent( - color: .mayaBlue, - symbol: "info.circle.fill", - text: "About", - url: URL(string: "https://dennistech.io")! - ) - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/PlayedGamesList.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/PlayedGamesList.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,30 @@ +// +// PlayedGamesList.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 23/10/22. +// + +import SwiftUI + +struct PlayedGamesList: View { + var playedGames: FetchedResults + + @Environment(\.managedObjectContext) var moc + + var body: some View { + List { + ForEach(playedGames, id: \.id) { game in + RecentGame(game: game) + } + .onDelete { indexSet in + CoreDataController.deleteGame(at: indexSet, from: playedGames, with: moc) + } + } + .navigationTitle("Played games") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + EditButton() + } + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/RecentGame.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/RecentGame.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,52 @@ +// +// RecentGame.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 19/10/22. +// + +import SwiftUI + +struct RecentGame: View { + let game: PlayedGame + let gameInfo: GameInfo + + init(game: PlayedGame) { + self.game = game + self.gameInfo = GameInfoController.getInfo(for: game.type) + } + + var body: some View { + HStack(alignment: .center, spacing: 15) { + RoundedRectangle(cornerRadius: 5) + .fill( + LinearGradient( + gradient: gameInfo.gradient, + startPoint: .top, endPoint: .bottom + ) + ) + .frame(width: 35, height: 35) + .overlay( + Image(systemName: gameInfo.symbol) + .font(.headline) + .foregroundColor(.white) + .padding(5) + ) + + VStack(alignment: .leading) { + Text(gameInfo.name) + .font(.headline) + + Text("\(game.date ?? Date(), format: .dateTime)") + .font(.callout) + .foregroundColor(.secondary) + } + + Spacer() + + Text("\(game.score, format: .number) ⭐️") + .font(.headline) + + } + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/RecentGameHelper.swift --- a/GeoQuiz/Components/RecentGameHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -// -// RecentGameHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 19/10/22. -// - -import SwiftUI - -struct RecentGame: View { - let game: PlayedGame - let gameInfo: GameInfo - - init(game: PlayedGame) { - self.game = game - self.gameInfo = GameInfoController.getInfo(for: game.type) - } - - var body: some View { - HStack(alignment: .center, spacing: 15) { - RoundedRectangle(cornerRadius: 5) - .fill( - LinearGradient( - gradient: gameInfo.gradient, - startPoint: .top, endPoint: .bottom - ) - ) - .frame(width: 35, height: 35) - .overlay( - Image(systemName: gameInfo.symbol) - .font(.headline) - .foregroundColor(.white) - .padding(5) - ) - - VStack(alignment: .leading) { - Text(gameInfo.name) - .font(.headline) - - Text("\(game.date, format: .dateTime)") - .font(.callout) - .foregroundColor(.secondary) - } - - Spacer() - - Text("\(game.score, format: .number) ⭐️") - .font(.headline) - - } - .padding() - .background(Color(.secondarySystemGroupedBackground)) - .cornerRadius(20) - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/UserImage.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/UserImage.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,39 @@ +// +// UserImage.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 22/10/22. +// + +import SwiftUI + +struct UserImage: View { + @ObservedObject var userController: UserController + + var body: some View { + if let uiImage = userController.data.uiImage { + Circle() + .overlay( + Image(uiImage: uiImage) + .resizable() + .scaledToFill() + .clipShape(Circle()) + ) + } else { + Circle() + .foregroundColor(.secondary.opacity(0.3)) + .overlay( + Image(systemName: "camera.fill") + .foregroundColor(.white) + .font(.title) + .shadow(radius: 5) + ) + } + } +} + +struct UserImage_Previews: PreviewProvider { + static var previews: some View { + UserImage(userController: UserController()) + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/UserImageHelper.swift --- a/GeoQuiz/Components/UserImageHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -// -// UserImageHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 22/10/22. -// - -import SwiftUI - -struct UserImage: View { - @ObservedObject var userController: UserController - - var body: some View { - if let uiImage = userController.data.uiImage { - Circle() - .overlay( - Image(uiImage: uiImage) - .resizable() - .scaledToFill() - .clipShape(Circle()) - ) - } else { - Circle() - .foregroundColor(.secondary.opacity(0.3)) - .overlay( - Image(systemName: "person") - .font(.largeTitle) - ) - } - } -} - -struct UserImage_Previews: PreviewProvider { - static var previews: some View { - UserImage(userController: UserController()) - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/UserProfile.swift --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/Components/UserProfile.swift Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,44 @@ +// +// UserProfile.swift +// GeoQuiz +// +// Created by Dennis Concepción Martín on 18/10/22. +// + +import SwiftUI + +struct UserProfile: View { + @ObservedObject var userController: UserController + @ObservedObject var storeKitController: StoreKitController + + @Binding var isShowing: Bool + + var body: some View { + VStack(spacing: 20) { + UserImage(userController: userController) + .frame(height: 150) + .shadow(radius: 10) + + VStack(spacing: 10) { + Text(userController.data.username) + .font(.title.bold()) + + if storeKitController.premiumIsActive { + Text("Premium user ⭐️") + .foregroundColor(.secondary) + } + } + + Button("Edit") { + isShowing = true + } + .buttonStyle(.borderedProminent) + } + } +} + +struct UserProfile_Previews: PreviewProvider { + static var previews: some View { + UserProfile(userController: UserController(), storeKitController: StoreKitController(), isShowing: .constant(true)) + } +} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Components/UserProfileHelper.swift --- a/GeoQuiz/Components/UserProfileHelper.swift Sun Oct 23 00:11:38 2022 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -// -// UserProfileHelper.swift -// GeoQuiz -// -// Created by Dennis Concepción Martín on 18/10/22. -// - -import SwiftUI - -struct UserProfile: View { - @ObservedObject var userController: UserController - @ObservedObject var storeKitController: StoreKitController - - @Binding var isShowing: Bool - - var body: some View { - VStack(spacing: 20) { - UserImage(userController: userController) - .frame(height: 150) - .shadow(radius: 10) - - VStack(spacing: 10) { - Text(userController.data.username) - .font(.title.bold()) - - if storeKitController.premiumIsActive { - Text("Premium user ⭐️") - .foregroundColor(.secondary) - } - } - - Button("Edit") { - isShowing = true - } - .buttonStyle(.borderedProminent) - } - } -} - -struct UserProfile_Previews: PreviewProvider { - static var previews: some View { - UserProfile(userController: UserController(), storeKitController: StoreKitController(), isShowing: .constant(true)) - } -} diff -r f140bb277c96 -r e281791e0494 GeoQuiz/GeoQuiz.entitlements --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuiz/GeoQuiz.entitlements Sun Oct 23 11:48:39 2022 +0100 @@ -0,0 +1,16 @@ + + + + + aps-environment + development + com.apple.developer.icloud-container-identifiers + + iCloud.io.dennistech.geoquiz + + com.apple.developer.icloud-services + + CloudKit + + + diff -r f140bb277c96 -r e281791e0494 GeoQuiz/GeoQuiz.xcdatamodeld/GeoQuiz.xcdatamodel/contents --- a/GeoQuiz/GeoQuiz.xcdatamodeld/GeoQuiz.xcdatamodel/contents Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/GeoQuiz.xcdatamodeld/GeoQuiz.xcdatamodel/contents Sun Oct 23 11:48:39 2022 +0100 @@ -2,15 +2,9 @@ - - + - - - - - \ No newline at end of file diff -r f140bb277c96 -r e281791e0494 GeoQuiz/GeoQuizApp.swift --- a/GeoQuiz/GeoQuizApp.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/GeoQuizApp.swift Sun Oct 23 11:48:39 2022 +0100 @@ -10,7 +10,7 @@ @main struct GeoQuizApp: App { - @StateObject private var persistenceController = PersistenceController() + let persistenceController = PersistenceController.shared init() { Purchases.configure(withAPIKey: "appl_BymTxroeoaWiXAraaFjcPlHlqbf") diff -r f140bb277c96 -r e281791e0494 GeoQuiz/GuessTheCapitalView.swift --- a/GeoQuiz/GuessTheCapitalView.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/GuessTheCapitalView.swift Sun Oct 23 11:48:39 2022 +0100 @@ -23,7 +23,7 @@ Spacer() - FlagImage(flagSymbol: game.correctAnswer.value.flag, cornerRadius: 20) + FlagImage(flagSymbol: game.correctAnswer.value.flag) .clipShape(RoundedRectangle(cornerRadius: 20)) .shadow(radius: 10) .frame(height: geo.size.height * 0.15) diff -r f140bb277c96 -r e281791e0494 GeoQuiz/GuessTheFlagView.swift --- a/GeoQuiz/GuessTheFlagView.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/GuessTheFlagView.swift Sun Oct 23 11:48:39 2022 +0100 @@ -46,14 +46,14 @@ game.selector() } } label: { - FlagImage(flagSymbol: game.data[countryName]!.flag, cornerRadius: 20) - .clipShape(Circle()) - .overlay { - Circle() - .strokeBorder(.white, lineWidth: 4) - } + Circle() + .stroke(.white, lineWidth: 6) + .frame(height: geo.size.height * 0.15) .shadow(radius: 10) - .frame(height: geo.size.height * 0.15) + .overlay( + FlagImage(flagSymbol: game.data[countryName]!.flag) + .clipShape(Circle()) + ) } } } diff -r f140bb277c96 -r e281791e0494 GeoQuiz/GuessThePopulationView.swift --- a/GeoQuiz/GuessThePopulationView.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/GuessThePopulationView.swift Sun Oct 23 11:48:39 2022 +0100 @@ -23,7 +23,7 @@ Spacer() - FlagImage(flagSymbol: game.correctAnswer.value.flag, cornerRadius: 20) + FlagImage(flagSymbol: game.correctAnswer.value.flag) .clipShape(RoundedRectangle(cornerRadius: 20)) .shadow(radius: 10) .frame(height: geo.size.height * 0.15) diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Info.plist --- a/GeoQuiz/Info.plist Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/Info.plist Sun Oct 23 11:48:39 2022 +0100 @@ -5,6 +5,7 @@ UIBackgroundModes audio + remote-notification diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Logic/GameProtocol+Extension.swift --- a/GeoQuiz/Logic/GameProtocol+Extension.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/Logic/GameProtocol+Extension.swift Sun Oct 23 11:48:39 2022 +0100 @@ -110,7 +110,6 @@ func save(_ gameType: GameType, with moc: NSManagedObjectContext) { let playedGame = PlayedGame(context: moc) - playedGame.id = UUID() playedGame.type = gameType playedGame.date = Date() playedGame.score = Int32(userScore) diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Logic/PersistenceController.swift --- a/GeoQuiz/Logic/PersistenceController.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/Logic/PersistenceController.swift Sun Oct 23 11:48:39 2022 +0100 @@ -7,24 +7,8 @@ import CoreData -class PersistenceController: ObservableObject { - let container: NSPersistentContainer - - init(inMemory: Bool = false) { - container = NSPersistentContainer(name: "GeoQuiz") - - if inMemory { - container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") - } - - container.loadPersistentStores(completionHandler: { (storeDescription, error) in - if let error = error { - fatalError("Unresolved error \(error.localizedDescription)") - } - }) - - container.viewContext.automaticallyMergesChangesFromParent = true - } +class PersistenceController { + static let shared = PersistenceController() // Create mock data for previews static var preview: PersistenceController = { @@ -33,7 +17,6 @@ for _ in 0..<10 { let playedGame = PlayedGame(context: viewContext) - playedGame.id = UUID() playedGame.type = GameType(rawValue: Int16.random(in: 0...3))! playedGame.score = Int32.random(in: 0...50) playedGame.date = Date() @@ -55,4 +38,22 @@ return result }() + + let container: NSPersistentCloudKitContainer + + init(inMemory: Bool = false) { + container = NSPersistentCloudKitContainer(name: "GeoQuiz") + + if inMemory { + container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") + } + + container.loadPersistentStores(completionHandler: { (storeDescription, error) in + if let error = error as NSError? { + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + + container.viewContext.automaticallyMergesChangesFromParent = true + } } diff -r f140bb277c96 -r e281791e0494 GeoQuiz/Logic/PlayedGame+CoreDataProperties.swift --- a/GeoQuiz/Logic/PlayedGame+CoreDataProperties.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/Logic/PlayedGame+CoreDataProperties.swift Sun Oct 23 11:48:39 2022 +0100 @@ -16,10 +16,9 @@ return NSFetchRequest(entityName: "PlayedGame") } - @NSManaged public var id: UUID @NSManaged public var type: GameType @NSManaged public var score: Int32 - @NSManaged public var date: Date + @NSManaged public var date: Date? @NSManaged public var correctAnswers: [String]? @NSManaged public var wrongAnswers: [String]? diff -r f140bb277c96 -r e281791e0494 GeoQuiz/ProfileModalView.swift --- a/GeoQuiz/ProfileModalView.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/ProfileModalView.swift Sun Oct 23 11:48:39 2022 +0100 @@ -11,7 +11,7 @@ @ObservedObject var userController: UserController @ObservedObject var storeKitController: StoreKitController - @State var showingEditModalView = false + @State private var showingEditModalView = false @FetchRequest(sortDescriptors: [ SortDescriptor(\.date, order: .reverse), @@ -31,13 +31,36 @@ ) VStack(spacing: 20) { - ForEach(playedGames.prefix(8)) { playedGame in - RecentGame(game: playedGame) + HStack { + Text("Latest games") + .foregroundColor(.secondary) + + Spacer() + + NavigationLink { + PlayedGamesList(playedGames: playedGames) + } label: { + Text("Show all") + } + .disabled(playedGames.isEmpty) + } + + if playedGames.isEmpty { + Spacer() + LatestGamesPlaceholder() + } else { + ForEach(playedGames.prefix(8)) { playedGame in + RecentGame(game: playedGame) + .padding() + .background(Color(.secondarySystemGroupedBackground)) + .cornerRadius(20) + } } } } .padding() } + .frame(maxWidth: .infinity) .navigationTitle("Profile") .navigationBarTitleDisplayMode(.inline) .background(Color(.systemGroupedBackground)) diff -r f140bb277c96 -r e281791e0494 GeoQuiz/SettingsModalView.swift --- a/GeoQuiz/SettingsModalView.swift Sun Oct 23 00:11:38 2022 +0100 +++ b/GeoQuiz/SettingsModalView.swift Sun Oct 23 11:48:39 2022 +0100 @@ -45,21 +45,21 @@ } Section { - LinkComponent( + FormLink( color: .mayaBlue, symbol: "info.circle.fill", text: "About", url: URL(string: "https://dennistech.io")! ) - LinkComponent( + FormLink( color: .atomicTangerine, symbol: "ant.circle.fill", text: "Report bugs", url: URL(string: "mailto:dmartin@dennistech.io")! ) - LinkComponent( + FormLink( color: .blueBell, symbol: "message.circle.fill", text: "Twitter",