diff --git a/Project SF.xcodeproj/project.pbxproj b/Project SF.xcodeproj/project.pbxproj index 99c6e36..9c4f438 100644 --- a/Project SF.xcodeproj/project.pbxproj +++ b/Project SF.xcodeproj/project.pbxproj @@ -7,14 +7,9 @@ objects = { /* Begin PBXBuildFile section */ - 3019CD9924BC9792002564AD /* PlaceBadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3019CD9824BC9792002564AD /* PlaceBadgeView.swift */; }; - 30251C1924BFC1A50058D6D2 /* CompetitorDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30251C1824BFC1A50058D6D2 /* CompetitorDetail.swift */; }; - 30251C1B24BFC1B10058D6D2 /* CompetitorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30251C1A24BFC1B10058D6D2 /* CompetitorCell.swift */; }; - 30251C1E24BFE1D50058D6D2 /* PointsGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30251C1D24BFE1D50058D6D2 /* PointsGraph.swift */; }; - 30278E9324BC553A00E87E80 /* CompetitionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30278E9224BC553A00E87E80 /* CompetitionDetail.swift */; }; 302CF88A24BA199E00FF79D7 /* RingType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302CF88924BA199E00FF79D7 /* RingType.swift */; }; 302CF88C24BA1A4000FF79D7 /* ActivityResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302CF88B24BA1A4000FF79D7 /* ActivityResult.swift */; }; - 3050123624C0887D00E39019 /* Int+ConvertFromRangeToRange copy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3050123524C0887D00E39019 /* Int+ConvertFromRangeToRange copy.swift */; }; + 3050123624C0887D00E39019 /* Int+ConvertFromRangeToRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3050123524C0887D00E39019 /* Int+ConvertFromRangeToRange.swift */; }; 3067712F24BDE0080085F152 /* FriendsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3067712E24BDE0080085F152 /* FriendsCell.swift */; }; 3067713124BDE3950085F152 /* FriendDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3067713024BDE3950085F152 /* FriendDetailView.swift */; }; 307648C924BC7DC5005D8531 /* GrantDataAccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307648C824BC7DC4005D8531 /* GrantDataAccessView.swift */; }; @@ -24,6 +19,18 @@ 308FAD9124B987F000126F3F /* SignUpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 308FAD9024B987F000126F3F /* SignUpView.swift */; }; 308FAD9E24B9A0DC00126F3F /* NavigationBarLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 308FAD9D24B9A0DC00126F3F /* NavigationBarLabel.swift */; }; 3090918224B9480F000E3B11 /* RoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3090918124B9480F000E3B11 /* RoundedButton.swift */; }; + 30B2818824BFF2F600647B83 /* UIImage+PixelData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2818724BFF2F600647B83 /* UIImage+PixelData.swift */; }; + 30B2818A24C001A000647B83 /* Pixel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2818924C001A000647B83 /* Pixel.swift */; }; + 30B2818C24C07F4700647B83 /* ProfileImageCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2818B24C07F4700647B83 /* ProfileImageCreator.swift */; }; + 30B2819924C1A41300647B83 /* PointsGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819024C1A41200647B83 /* PointsGraph.swift */; }; + 30B2819A24C1A41300647B83 /* CompetitorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819124C1A41200647B83 /* CompetitorCell.swift */; }; + 30B2819B24C1A41300647B83 /* CompetitionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819224C1A41200647B83 /* CompetitionDetail.swift */; }; + 30B2819C24C1A41300647B83 /* CompetitorDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819324C1A41200647B83 /* CompetitorDetail.swift */; }; + 30B2819D24C1A41300647B83 /* CompetitionDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819424C1A41200647B83 /* CompetitionDetailView.swift */; }; + 30B2819E24C1A41300647B83 /* CompetitionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819524C1A41200647B83 /* CompetitionsView.swift */; }; + 30B2819F24C1A41300647B83 /* CreateCompetition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819624C1A41200647B83 /* CreateCompetition.swift */; }; + 30B281A024C1A41300647B83 /* CompetitionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819724C1A41300647B83 /* CompetitionCell.swift */; }; + 30B281A124C1A41300647B83 /* PlaceBadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2819824C1A41300647B83 /* PlaceBadgeView.swift */; }; 30BFC8CE24B75E6C00DAC6D9 /* ProjectSFApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30BFC8CD24B75E6C00DAC6D9 /* ProjectSFApp.swift */; }; 30BFC8D024B75E6C00DAC6D9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30BFC8CF24B75E6C00DAC6D9 /* ContentView.swift */; }; 30BFC8D224B75E6F00DAC6D9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 30BFC8D124B75E6F00DAC6D9 /* Assets.xcassets */; }; @@ -35,9 +42,6 @@ 30CCF30724BED9EA00103C1E /* ActivityOverview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCF30624BED9EA00103C1E /* ActivityOverview.swift */; }; 30D3217824BB430E009CD9D0 /* RoundedTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3217724BB430E009CD9D0 /* RoundedTextField.swift */; }; 30D3217D24BB4EDE009CD9D0 /* ActivityRings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D3217C24BB4EDE009CD9D0 /* ActivityRings.swift */; }; - 30D321B524BB65D5009CD9D0 /* CompetitionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321A724BB65D5009CD9D0 /* CompetitionsView.swift */; }; - 30D321B624BB65D5009CD9D0 /* CompetitionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321A824BB65D5009CD9D0 /* CompetitionCell.swift */; }; - 30D321B724BB65D5009CD9D0 /* CreateCompetition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321A924BB65D5009CD9D0 /* CreateCompetition.swift */; }; 30D321B824BB65D5009CD9D0 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321AC24BB65D5009CD9D0 /* SettingsView.swift */; }; 30D321B924BB65D5009CD9D0 /* ImageSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321AD24BB65D5009CD9D0 /* ImageSelectionView.swift */; }; 30D321BA24BB65D5009CD9D0 /* NotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321AE24BB65D5009CD9D0 /* NotificationSettings.swift */; }; @@ -47,6 +51,7 @@ 30D321BE24BB65D5009CD9D0 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321B224BB65D5009CD9D0 /* ProfileView.swift */; }; 30D321BF24BB65D5009CD9D0 /* FriendsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321B424BB65D5009CD9D0 /* FriendsView.swift */; }; 30D321C124BC1886009CD9D0 /* NavScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D321C024BC1886009CD9D0 /* NavScrollView.swift */; }; + 30EAB9FB24C2A234005326C8 /* ImageStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EAB9FA24C2A234005326C8 /* ImageStore.swift */; }; 30F1EA3B24B951CA00FF89FC /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F1EA3A24B951CA00FF89FC /* OnboardingView.swift */; }; 30FCC84C24BB2EC800862C01 /* ResignKeyboardOnDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FCC84B24BB2EC800862C01 /* ResignKeyboardOnDragGesture.swift */; }; 30FCC84E24BB318000862C01 /* KeyboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FCC84D24BB318000862C01 /* KeyboardManager.swift */; }; @@ -84,14 +89,9 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 3019CD9824BC9792002564AD /* PlaceBadgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceBadgeView.swift; sourceTree = ""; }; - 30251C1824BFC1A50058D6D2 /* CompetitorDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompetitorDetail.swift; sourceTree = ""; }; - 30251C1A24BFC1B10058D6D2 /* CompetitorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompetitorCell.swift; sourceTree = ""; }; - 30251C1D24BFE1D50058D6D2 /* PointsGraph.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointsGraph.swift; sourceTree = ""; }; - 30278E9224BC553A00E87E80 /* CompetitionDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompetitionDetail.swift; sourceTree = ""; }; 302CF88924BA199E00FF79D7 /* RingType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RingType.swift; sourceTree = ""; }; 302CF88B24BA1A4000FF79D7 /* ActivityResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityResult.swift; sourceTree = ""; }; - 3050123524C0887D00E39019 /* Int+ConvertFromRangeToRange copy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+ConvertFromRangeToRange copy.swift"; sourceTree = ""; }; + 3050123524C0887D00E39019 /* Int+ConvertFromRangeToRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+ConvertFromRangeToRange.swift"; sourceTree = ""; }; 3067712E24BDE0080085F152 /* FriendsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsCell.swift; sourceTree = ""; }; 3067713024BDE3950085F152 /* FriendDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendDetailView.swift; sourceTree = ""; }; 307648C824BC7DC4005D8531 /* GrantDataAccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GrantDataAccessView.swift; sourceTree = ""; }; @@ -101,6 +101,18 @@ 308FAD9024B987F000126F3F /* SignUpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpView.swift; sourceTree = ""; }; 308FAD9D24B9A0DC00126F3F /* NavigationBarLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarLabel.swift; sourceTree = ""; }; 3090918124B9480F000E3B11 /* RoundedButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedButton.swift; sourceTree = ""; }; + 30B2818724BFF2F600647B83 /* UIImage+PixelData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+PixelData.swift"; sourceTree = ""; }; + 30B2818924C001A000647B83 /* Pixel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pixel.swift; sourceTree = ""; }; + 30B2818B24C07F4700647B83 /* ProfileImageCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileImageCreator.swift; sourceTree = ""; }; + 30B2819024C1A41200647B83 /* PointsGraph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PointsGraph.swift; sourceTree = ""; }; + 30B2819124C1A41200647B83 /* CompetitorCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitorCell.swift; sourceTree = ""; }; + 30B2819224C1A41200647B83 /* CompetitionDetail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitionDetail.swift; sourceTree = ""; }; + 30B2819324C1A41200647B83 /* CompetitorDetail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitorDetail.swift; sourceTree = ""; }; + 30B2819424C1A41200647B83 /* CompetitionDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitionDetailView.swift; sourceTree = ""; }; + 30B2819524C1A41200647B83 /* CompetitionsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitionsView.swift; sourceTree = ""; }; + 30B2819624C1A41200647B83 /* CreateCompetition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateCompetition.swift; sourceTree = ""; }; + 30B2819724C1A41300647B83 /* CompetitionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitionCell.swift; sourceTree = ""; }; + 30B2819824C1A41300647B83 /* PlaceBadgeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlaceBadgeView.swift; sourceTree = ""; }; 30BFC8CA24B75E6C00DAC6D9 /* Project SF.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Project SF.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 30BFC8CD24B75E6C00DAC6D9 /* ProjectSFApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectSFApp.swift; sourceTree = ""; }; 30BFC8CF24B75E6C00DAC6D9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -115,9 +127,6 @@ 30CCF30624BED9EA00103C1E /* ActivityOverview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityOverview.swift; sourceTree = ""; }; 30D3217724BB430E009CD9D0 /* RoundedTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedTextField.swift; sourceTree = ""; }; 30D3217C24BB4EDE009CD9D0 /* ActivityRings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityRings.swift; sourceTree = ""; }; - 30D321A724BB65D5009CD9D0 /* CompetitionsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitionsView.swift; sourceTree = ""; }; - 30D321A824BB65D5009CD9D0 /* CompetitionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompetitionCell.swift; sourceTree = ""; }; - 30D321A924BB65D5009CD9D0 /* CreateCompetition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateCompetition.swift; sourceTree = ""; }; 30D321AC24BB65D5009CD9D0 /* SettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; 30D321AD24BB65D5009CD9D0 /* ImageSelectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageSelectionView.swift; sourceTree = ""; }; 30D321AE24BB65D5009CD9D0 /* NotificationSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationSettings.swift; sourceTree = ""; }; @@ -127,6 +136,7 @@ 30D321B224BB65D5009CD9D0 /* ProfileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; 30D321B424BB65D5009CD9D0 /* FriendsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FriendsView.swift; sourceTree = ""; }; 30D321C024BC1886009CD9D0 /* NavScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavScrollView.swift; sourceTree = ""; }; + 30EAB9FA24C2A234005326C8 /* ImageStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageStore.swift; sourceTree = ""; }; 30F1EA3A24B951CA00FF89FC /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = ""; }; 30FABF2B24BB5423004B8B62 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; 30FCC84B24BB2EC800862C01 /* ResignKeyboardOnDragGesture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResignKeyboardOnDragGesture.swift; sourceTree = ""; }; @@ -178,17 +188,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 30251C1C24BFC1B80058D6D2 /* CompetitionDetail */ = { - isa = PBXGroup; - children = ( - 30278E9224BC553A00E87E80 /* CompetitionDetail.swift */, - 30251C1824BFC1A50058D6D2 /* CompetitorDetail.swift */, - 30251C1A24BFC1B10058D6D2 /* CompetitorCell.swift */, - 30251C1D24BFE1D50058D6D2 /* PointsGraph.swift */, - ); - path = CompetitionDetail; - sourceTree = ""; - }; 3029AF5024B8869E003F0324 /* Views */ = { isa = PBXGroup; children = ( @@ -210,9 +209,10 @@ isa = PBXGroup; children = ( 9C7B4D0724B89AF100FC4456 /* Double+ConvertFromRangeToRange.swift */, - 3050123524C0887D00E39019 /* Int+ConvertFromRangeToRange copy.swift */, + 3050123524C0887D00E39019 /* Int+ConvertFromRangeToRange.swift */, 9C7B4D0524B89AC700FC4456 /* View+ForegroundModifier.swift */, 9CCFDD2324B9745E00162B0F /* UIApplication+IsTesting.swift */, + 30B2818724BFF2F600647B83 /* UIImage+PixelData.swift */, ); path = Extensions; sourceTree = ""; @@ -239,6 +239,17 @@ path = Onboarding; sourceTree = ""; }; + 30B2818F24C1A41200647B83 /* CompetitionDetail */ = { + isa = PBXGroup; + children = ( + 30B2819024C1A41200647B83 /* PointsGraph.swift */, + 30B2819124C1A41200647B83 /* CompetitorCell.swift */, + 30B2819224C1A41200647B83 /* CompetitionDetail.swift */, + 30B2819324C1A41200647B83 /* CompetitorDetail.swift */, + ); + path = CompetitionDetail; + sourceTree = ""; + }; 30BFC8C124B75E6C00DAC6D9 = { isa = PBXGroup; children = ( @@ -322,11 +333,12 @@ 30D321A624BB65D5009CD9D0 /* Competitions */ = { isa = PBXGroup; children = ( - 30251C1C24BFC1B80058D6D2 /* CompetitionDetail */, - 30D321A724BB65D5009CD9D0 /* CompetitionsView.swift */, - 30D321A824BB65D5009CD9D0 /* CompetitionCell.swift */, - 30D321A924BB65D5009CD9D0 /* CreateCompetition.swift */, - 3019CD9824BC9792002564AD /* PlaceBadgeView.swift */, + 30B2819724C1A41300647B83 /* CompetitionCell.swift */, + 30B2818F24C1A41200647B83 /* CompetitionDetail */, + 30B2819424C1A41200647B83 /* CompetitionDetailView.swift */, + 30B2819524C1A41200647B83 /* CompetitionsView.swift */, + 30B2819624C1A41200647B83 /* CreateCompetition.swift */, + 30B2819824C1A41300647B83 /* PlaceBadgeView.swift */, ); path = Competitions; sourceTree = ""; @@ -349,6 +361,7 @@ 30D321AF24BB65D5009CD9D0 /* PermissionSettings.swift */, 30D321B024BB65D5009CD9D0 /* PrivacyAbout.swift */, 30D321B124BB65D5009CD9D0 /* ProfileSettings.swift */, + 30B2818B24C07F4700647B83 /* ProfileImageCreator.swift */, ); path = Settings; sourceTree = ""; @@ -404,6 +417,8 @@ 302CF88924BA199E00FF79D7 /* RingType.swift */, 302CF88B24BA1A4000FF79D7 /* ActivityResult.swift */, 30D3217C24BB4EDE009CD9D0 /* ActivityRings.swift */, + 30B2818924C001A000647B83 /* Pixel.swift */, + 30EAB9FA24C2A234005326C8 /* ImageStore.swift */, ); path = Models; sourceTree = ""; @@ -575,7 +590,6 @@ buildActionMask = 2147483647; files = ( 308FAD9E24B9A0DC00126F3F /* NavigationBarLabel.swift in Sources */, - 30D321B524BB65D5009CD9D0 /* CompetitionsView.swift in Sources */, 9C7B4D0824B89AF100FC4456 /* Double+ConvertFromRangeToRange.swift in Sources */, 30BFC8D024B75E6C00DAC6D9 /* ContentView.swift in Sources */, 30FCC84C24BB2EC800862C01 /* ResignKeyboardOnDragGesture.swift in Sources */, @@ -584,15 +598,18 @@ 9CCFDD1F24B971D600162B0F /* NetworkManager.swift in Sources */, 9CCFDD2624B9753F00162B0F /* Main.swift in Sources */, 30D321C124BC1886009CD9D0 /* NavScrollView.swift in Sources */, - 30251C1924BFC1A50058D6D2 /* CompetitorDetail.swift in Sources */, + 30B2818824BFF2F600647B83 /* UIImage+PixelData.swift in Sources */, + 30B281A124C1A41300647B83 /* PlaceBadgeView.swift in Sources */, 30BFC8E924B804CC00DAC6D9 /* ActivityRingView.swift in Sources */, 3067712F24BDE0080085F152 /* FriendsCell.swift in Sources */, + 30B281A024C1A41300647B83 /* CompetitionCell.swift in Sources */, 30D321BD24BB65D5009CD9D0 /* ProfileSettings.swift in Sources */, 30BFC8DF24B7637F00DAC6D9 /* VisualEffectView.swift in Sources */, 9CCFDD1D24B971D600162B0F /* User.swift in Sources */, - 30D321B624BB65D5009CD9D0 /* CompetitionCell.swift in Sources */, 30D321BC24BB65D5009CD9D0 /* PrivacyAbout.swift in Sources */, - 30D321B724BB65D5009CD9D0 /* CreateCompetition.swift in Sources */, + 30B2819C24C1A41300647B83 /* CompetitorDetail.swift in Sources */, + 30EAB9FB24C2A234005326C8 /* ImageStore.swift in Sources */, + 30B2819B24C1A41300647B83 /* CompetitionDetail.swift in Sources */, 308FAD8D24B97E8A00126F3F /* PrivacyView.swift in Sources */, 30D321BE24BB65D5009CD9D0 /* ProfileView.swift in Sources */, 308FAD8B24B97E7E00126F3F /* OnboardingInfoCell.swift in Sources */, @@ -601,28 +618,31 @@ 30F1EA3B24B951CA00FF89FC /* OnboardingView.swift in Sources */, 30D3217824BB430E009CD9D0 /* RoundedTextField.swift in Sources */, 9CCFDD2024B971D600162B0F /* HealthKitController.swift in Sources */, + 30B2818A24C001A000647B83 /* Pixel.swift in Sources */, 9C8FAD4624B9E39E00571947 /* Record.swift in Sources */, 30D321B924BB65D5009CD9D0 /* ImageSelectionView.swift in Sources */, + 30B2819F24C1A41300647B83 /* CreateCompetition.swift in Sources */, + 30B2819924C1A41300647B83 /* PointsGraph.swift in Sources */, 30D3217D24BB4EDE009CD9D0 /* ActivityRings.swift in Sources */, 307648C924BC7DC5005D8531 /* GrantDataAccessView.swift in Sources */, 30D321BF24BB65D5009CD9D0 /* FriendsView.swift in Sources */, 302CF88A24BA199E00FF79D7 /* RingType.swift in Sources */, 9C7B4D0624B89AC700FC4456 /* View+ForegroundModifier.swift in Sources */, - 30251C1B24BFC1B10058D6D2 /* CompetitorCell.swift in Sources */, + 30B2819A24C1A41300647B83 /* CompetitorCell.swift in Sources */, 30CCF30724BED9EA00103C1E /* ActivityOverview.swift in Sources */, 30D321BA24BB65D5009CD9D0 /* NotificationSettings.swift in Sources */, - 30251C1E24BFE1D50058D6D2 /* PointsGraph.swift in Sources */, 30BFC8E724B8041C00DAC6D9 /* ActivityRingsView.swift in Sources */, 3090918224B9480F000E3B11 /* RoundedButton.swift in Sources */, 9CCFDD2424B9745E00162B0F /* UIApplication+IsTesting.swift in Sources */, - 3019CD9924BC9792002564AD /* PlaceBadgeView.swift in Sources */, + 30B2818C24C07F4700647B83 /* ProfileImageCreator.swift in Sources */, + 30B2819D24C1A41300647B83 /* CompetitionDetailView.swift in Sources */, 9CCFDD2824B9758A00162B0F /* TestApp.swift in Sources */, + 30B2819E24C1A41300647B83 /* CompetitionsView.swift in Sources */, 302CF88C24BA1A4000FF79D7 /* ActivityResult.swift in Sources */, 3067713124BDE3950085F152 /* FriendDetailView.swift in Sources */, 9C6C74AC24BADD1800C657B0 /* RoundedNavigationButton.swift in Sources */, 30D321BB24BB65D5009CD9D0 /* PermissionSettings.swift in Sources */, - 3050123624C0887D00E39019 /* Int+ConvertFromRangeToRange copy.swift in Sources */, - 30278E9324BC553A00E87E80 /* CompetitionDetail.swift in Sources */, + 3050123624C0887D00E39019 /* Int+ConvertFromRangeToRange.swift in Sources */, 30D321B824BB65D5009CD9D0 /* SettingsView.swift in Sources */, 307648CB24BC81C8005D8531 /* iCloudErrorView.swift in Sources */, ); diff --git a/Project SF/Models/ImageStore.swift b/Project SF/Models/ImageStore.swift new file mode 100644 index 0000000..6612b5a --- /dev/null +++ b/Project SF/Models/ImageStore.swift @@ -0,0 +1,28 @@ +// +// ImageStore.swift +// Project SF +// +// Created by Roman Esin on 18.07.2020. +// + +import UIKit + +// TODO: Finish this thing... +@propertyWrapper +struct ImageStore { + var key: String + var storage = UserDefaults.standard + + var wrappedValue: UIImage? { + get { + guard let data = storage.value(forKey: key) as? Data else { return nil } + return UIImage(data: data) + } + set { storage.setValue(newValue?.pngData(), forKey: key) } + } + + init(_ key: String, wrappedValue: UIImage) { + self.key = key + self.wrappedValue = wrappedValue + } +} diff --git a/Project SF/Models/Pixel.swift b/Project SF/Models/Pixel.swift new file mode 100644 index 0000000..547529a --- /dev/null +++ b/Project SF/Models/Pixel.swift @@ -0,0 +1,81 @@ +// +// Pixel.swift +// Project SF +// +// Created by Roman Esin on 16.07.2020. +// + +import SwiftUI + +// swiftlint:disable identifier_name +struct Pixel { + var a: UInt8 + var r: UInt8 + var g: UInt8 + var b: UInt8 +} + +class PixelImage { + var width: Int + var height: Int + var pixels: [Pixel] + + static func random(width: Int, height: Int) -> PixelImage { + var pixels: [Pixel] = [] + for _ in 0..<(width * height) { + pixels.append(Pixel(a: 255, + r: .random(in: 0...255), + g: .random(in: 0...255), + b: .random(in: 0...255))) + } + return PixelImage(width: width, height: height, pixels: pixels) + } + + /// Returns random symmetrixal `PixelImage` with given size. + /// - Parameters: + /// - width: Width of the image. + /// - height: Height of the image. + /// - Returns: Random symmetrixal `PixelImage` with given size. + static func randomSymmetrical(color: Color, width: Int, height: Int) -> PixelImage { + var pixels: [Pixel] = [] + let clear = Pixel(a: 0, + r: 0, + g: 0, + b: 0) + + let uiColor = UIColor(color) + var a: CGFloat = 0 + var r: CGFloat = 0 + var g: CGFloat = 0 + var b: CGFloat = 0 + uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) + + let color = Pixel(a: 255, + r: UInt8(r * 255), + g: UInt8(g * 255), + b: UInt8(b * 255)) + + var slice: [Pixel] = [] + let num = width % 2 + for _ in 0.. 0 && height > 0, pixels.count == width * height else { return nil } + var data = pixels + guard let providerRef = CGDataProvider(data: Data(bytes: &data, + count: data.count * MemoryLayout.size) as CFData) + else { return nil } + guard let cgim = CGImage( + width: width, + height: height, + bitsPerComponent: 8, + bitsPerPixel: 32, + bytesPerRow: width * MemoryLayout.size, + space: CGColorSpaceCreateDeviceRGB(), + bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue), + provider: providerRef, + decode: nil, + shouldInterpolate: false, + intent: .defaultIntent) + else { return nil } + self.init(cgImage: cgim) + } +} diff --git a/Project SF/Views/NavigationBarLabel.swift b/Project SF/Views/NavigationBarLabel.swift index 93b7ea0..ccf041b 100644 --- a/Project SF/Views/NavigationBarLabel.swift +++ b/Project SF/Views/NavigationBarLabel.swift @@ -63,6 +63,34 @@ struct NavigationLabel: View { } } +struct NavigationBarButton: View { + + let title: String? + let systemName: String + let action: () -> Void + + var body: some View { + Button( + action: action, + label: { + if let title = title { + Label(title, systemImage: systemName) + .font(.title2) + } else { + Image(systemName: systemName) + .font(.title2) + } + } + ) + } + + init(title: String? = nil, systemName: String, action: @escaping () -> Void) { + self.title = title + self.systemName = systemName + self.action = action + } +} + struct NavigationButton: View { let title: String? = nil diff --git a/Project SF/Views/Tabs/Competitions/CompetitionCell.swift b/Project SF/Views/Tabs/Competitions/CompetitionCell.swift index 0713c3c..4786f54 100644 --- a/Project SF/Views/Tabs/Competitions/CompetitionCell.swift +++ b/Project SF/Views/Tabs/Competitions/CompetitionCell.swift @@ -62,7 +62,7 @@ struct CompetitionCell: View { struct CompetitionCell_Previews: PreviewProvider { static var previews: some View { - var competitions: [Competition] = [ + let competitions: [Competition] = [ Competition( name: "Competition1", startDate: Date() - 100000, diff --git a/Project SF/Views/Tabs/Competitions/CompetitionDetailView.swift b/Project SF/Views/Tabs/Competitions/CompetitionDetailView.swift index 7aa02ae..b8c21b6 100644 --- a/Project SF/Views/Tabs/Competitions/CompetitionDetailView.swift +++ b/Project SF/Views/Tabs/Competitions/CompetitionDetailView.swift @@ -18,6 +18,16 @@ struct CompetitionDetailView: View { struct CompetitionDetailView_Previews: PreviewProvider { static var previews: some View { - CompetitionDetailView(competition: Competition(name: "Competition Name", startDate: Date(), endDate: Date() + 123)) + CompetitionDetailView(competition: Competition( + name: "Competition2", + startDate: Date(), + endDate: Date() + 1000000, + creatingUser: CompetingPerson(name: "Me", points: 5500), + people: [ + CompetingPerson(name: "Person1", points: 5000), + CompetingPerson(name: "Person2", points: 200), + CompetingPerson(name: "Person3", points: 500) + ] + )) } } diff --git a/Project SF/Views/Tabs/Profile/Settings/ProfileImageCreator.swift b/Project SF/Views/Tabs/Profile/Settings/ProfileImageCreator.swift new file mode 100644 index 0000000..e2accf8 --- /dev/null +++ b/Project SF/Views/Tabs/Profile/Settings/ProfileImageCreator.swift @@ -0,0 +1,72 @@ +// +// ProfileImageCreator.swift +// Project SF +// +// Created by Roman Esin on 16.07.2020. +// + +import SwiftUI + +struct ProfileImageCreator: View { + + @Environment(\.presentationMode) var presentationMode + @Binding var image: UIImage? + @Binding var color: Color + + var body: some View { + NavigationView { + VStack { + if let image = image { + Image(uiImage: image) + .interpolation(.none) + .renderingMode(.template) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 200, height: 200) + .clipShape(Circle()) + .foregroundColor(color) + + GroupBox { + ColorPicker("Select foreground color", selection: $color, supportsOpacity: false) + } + .padding(.top) + } + RoundedButton("Generate image") { + withAnimation { + image = UIImage(pixelImage: .randomSymmetrical(color: .white, width: 7, height: 7)) + } + } + .padding(.top) + } + .padding(.horizontal) + .navigationTitle("Profile Image Creator") + } + .onDisappear { + if image == nil { + color = .clear + } + } + } + + init(_ image: Binding, color: Binding) { + DispatchQueue.main.async { + var shouldRemoveImage = false + if color.wrappedValue == .clear { + color.wrappedValue = .black + shouldRemoveImage = true + } + if image.wrappedValue != nil && shouldRemoveImage { + image.wrappedValue = nil + } + } + _image = image + _color = color + } +} + +struct ProfileImageCreator_Previews: PreviewProvider { + static var previews: some View { + ProfileImageCreator(.constant(UIImage(pixelImage: .randomSymmetrical(color: .red, width: 10, height: 10))), + color: .constant(Color.red)) + } +} diff --git a/Project SF/Views/Tabs/Profile/Settings/ProfileSettings.swift b/Project SF/Views/Tabs/Profile/Settings/ProfileSettings.swift index d69801d..83f628a 100644 --- a/Project SF/Views/Tabs/Profile/Settings/ProfileSettings.swift +++ b/Project SF/Views/Tabs/Profile/Settings/ProfileSettings.swift @@ -16,30 +16,45 @@ struct ProfileSettings: View { @StateObject var keyboard = KeyboardManager() @State var profilePicture: UIImage? - @State var showImageSelectionView = false + @State var color = Color.clear + + @State var showSheet = false + @State var selectedSheet = 0 + @State var showSelectAlert = false var body: some View { // This VStack and empty text is required to fix the navigation title glitching out on scroll // so ScrollView isn't the topmost view. NavScrollView { Button(action: { - showImageSelectionView = true - }, label: { +// profilePicture = UIImage(pixelImage: .randomSymmetrical(width: 6, height: 6)) + showSelectAlert = true + }) { if profilePicture == nil { Image(systemName: "person.crop.circle.badge.plus") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100) } else { - Image(uiImage: profilePicture!) - .renderingMode(.original) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: 100, height: 100) - .clipShape(Circle()) + if color != .clear { + Image(uiImage: profilePicture!) + .interpolation(.none) + .renderingMode(.template) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 100, height: 100) + .clipShape(Circle()) + .foregroundColor(color) + } else { + Image(uiImage: profilePicture!) + .renderingMode(.original) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 100, height: 100) + .clipShape(Circle()) + } } - }) - .padding(.bottom) + } TextField("Name", text: $name) .font(.headline) @@ -86,8 +101,29 @@ struct ProfileSettings: View { } .padding(.horizontal) .navigationTitle("Profile") - .sheet(isPresented: $showImageSelectionView) { - ImageSelectionView(image: $profilePicture) + .actionSheet(isPresented: $showSelectAlert) { + ActionSheet(title: Text("Select profile image"), + message: nil, + buttons: [ + .default(Text("Open profile image creator"), action: { + selectedSheet = 0 + showSheet = true + }), .default(Text("Select from image gallery"), action: { + selectedSheet = 1 + showSheet = true + }), .cancel()]) + } + .onChange(of: showSheet, perform: { showSheet in + if !showSheet && selectedSheet == 1 { + color = .clear + } + }) + .sheet(isPresented: $showSheet) { + if selectedSheet == 0 { + ProfileImageCreator($profilePicture, color: $color) + } else { + ImageSelectionView(image: $profilePicture) + } } } } diff --git a/Project SF/Views/Tabs/Profile/Settings/SettingsView.swift b/Project SF/Views/Tabs/Profile/Settings/SettingsView.swift index f9d107a..0fa94c6 100644 --- a/Project SF/Views/Tabs/Profile/Settings/SettingsView.swift +++ b/Project SF/Views/Tabs/Profile/Settings/SettingsView.swift @@ -21,6 +21,9 @@ struct AboutFooter: View { } struct SettingsView: View { + + @Environment(\.presentationMode) var presentationMode + var body: some View { List { Section(header: Text("General")) {