diff --git a/nirvana-ios.xcodeproj/project.pbxproj b/nirvana-ios.xcodeproj/project.pbxproj index 2692ad5..f995612 100644 --- a/nirvana-ios.xcodeproj/project.pbxproj +++ b/nirvana-ios.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 894E80C327702E5900624B72 /* AddBasicInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894E80C227702E5800624B72 /* AddBasicInfoViewModel.swift */; }; 896CE6FE27707E6B00DB474E /* CircleNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896CE6FD27707E6B00DB474E /* CircleNavigationView.swift */; }; 896CE7002770847400DB474E /* CircleFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896CE6FF2770847400DB474E /* CircleFooterView.swift */; }; + 896CE7022770892F00DB474E /* CircleGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896CE7012770892F00DB474E /* CircleGridView.swift */; }; 89AD5573276DD790001658E0 /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AD5572276DD790001658E0 /* SplashView.swift */; }; 89AD5575276DE724001658E0 /* PhoneCodeVerificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AD5574276DE724001658E0 /* PhoneCodeVerificationView.swift */; }; 89AD5578276DEAB3001658E0 /* LogoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AD5577276DEAB3001658E0 /* LogoHeaderView.swift */; }; @@ -101,6 +102,7 @@ 894E80C227702E5800624B72 /* AddBasicInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddBasicInfoViewModel.swift; sourceTree = ""; }; 896CE6FD27707E6B00DB474E /* CircleNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleNavigationView.swift; sourceTree = ""; }; 896CE6FF2770847400DB474E /* CircleFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleFooterView.swift; sourceTree = ""; }; + 896CE7012770892F00DB474E /* CircleGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleGridView.swift; sourceTree = ""; }; 89AD5572276DD790001658E0 /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = ""; }; 89AD5574276DE724001658E0 /* PhoneCodeVerificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneCodeVerificationView.swift; sourceTree = ""; }; 89AD5577276DEAB3001658E0 /* LogoHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoHeaderView.swift; sourceTree = ""; }; @@ -337,6 +339,7 @@ 89BCABE6276B3D64009E9B10 /* InnerCircleViewModel.swift */, 896CE6FD27707E6B00DB474E /* CircleNavigationView.swift */, 896CE6FF2770847400DB474E /* CircleFooterView.swift */, + 896CE7012770892F00DB474E /* CircleGridView.swift */, ); path = InnerCircle; sourceTree = ""; @@ -536,6 +539,7 @@ 89BCABED276D2B05009E9B10 /* WavesGlassBackgroundView.swift in Sources */, 89F05BA6276ACD830002E9C7 /* ContactsPickerView.swift in Sources */, 8904DEC8277055E90071E6CA /* OnboardingTrioView.swift in Sources */, + 896CE7022770892F00DB474E /* CircleGridView.swift in Sources */, 89BDCDEA27697F9C00577829 /* UserMenu.swift in Sources */, 89BCABE7276B3D64009E9B10 /* InnerCircleViewModel.swift in Sources */, 89AD557C276DF86A001658E0 /* FirestoreService.swift in Sources */, diff --git a/nirvana-ios/Views/InnerCircle/CircleFooterView.swift b/nirvana-ios/Views/InnerCircle/CircleFooterView.swift index 2ef1e04..8f7110f 100644 --- a/nirvana-ios/Views/InnerCircle/CircleFooterView.swift +++ b/nirvana-ios/Views/InnerCircle/CircleFooterView.swift @@ -20,15 +20,14 @@ struct CircleFooterView: View { Spacer() HStack { - if self.selectedUserIndex != nil { - Image("Artboards_Diversity_Avatars_by_Netguru-\(self.selectedUserIndex! + 1)") - .resizable() - .scaledToFit() - .background(NirvanaColor.teal.opacity(0.1)) - .frame(width: 40, height: 40) - .clipShape(Circle()) - .padding(5) - } + Image("Artboards_Diversity_Avatars_by_Netguru-1") + .resizable() + .scaledToFit() + .background(NirvanaColor.teal.opacity(0.1)) + .frame(width: 40, height: 40) + .clipShape(Circle()) + .padding(5) + VStack (alignment: .leading) { @@ -59,11 +58,11 @@ struct CircleFooterView: View { FooterControlsView() } .padding() - .offset( - x:0, - y:self.selectedUserIndex == nil ? 150 : 0 - ) - .animation(Animation.spring(), value: self.selectedUserIndex) +// .offset( +// x:0, +// y:self.selectedUserIndex == nil ? 150 : 0 +// ) +// .animation(Animation.spring(), value: self.selectedUserIndex) } } diff --git a/nirvana-ios/Views/InnerCircle/CircleGridView.swift b/nirvana-ios/Views/InnerCircle/CircleGridView.swift new file mode 100644 index 0000000..c51751b --- /dev/null +++ b/nirvana-ios/Views/InnerCircle/CircleGridView.swift @@ -0,0 +1,188 @@ +// +// CircleGridView.swift +// nirvana-ios +// +// Created by Arjun Patel on 12/20/21. +// + +import SwiftUI +import NavigationStack + +struct CircleGridView: View { + @EnvironmentObject var authSessionStore: AuthSessionStore + @EnvironmentObject var navigationStack: NavigationStack + + let universalSize = UIScreen.main.bounds + + // magic variables for grid + // TODO: make the top left person or one horizontal person be in the center of screen...makes the top honeycomb pop + private static var numberOfItems: Int = 59 + private static let size: CGFloat = UIScreen.main.bounds.height*0.15 // scaling with screen size + private static let spacingBetweenColumns: CGFloat = 0 + private static let spacingBetweenRows: CGFloat = 0 + private static let totalColumns: Int = Int(log2(Double(Self.numberOfItems))) // scaling the circles and calculating column count + + @State private var selectedUserIndex: Int? = nil + + // TODO: change the size to adaptive or something to make outer ring items shrink their overall size and fit better + let gridItems: [GridItem] = Array( + repeating: GridItem(.fixed(Self.size), spacing: spacingBetweenColumns, alignment: .center), + count: totalColumns) + + private let big:CGFloat = 1 + private let medium:CGFloat = 0.75 + private let small:CGFloat = 0.5 + private let supersmall:CGFloat = 0.3 + + // TODO: centered honeycomb + side: maybe have two honeycombs: one in the center of 7 people and then everyone else surrounding + // TODO: maybe make our "center" offset to a little to the top left to make it more honeycomb from top left + private let center: CGPoint = CGPoint(x: UIScreen.main.bounds.width*0.5,y: UIScreen.main.bounds.height*0.5) + + var body: some View { + gridContent + } + + private var gridContent: some View { + // main communication hub + // TODO: client side, sort the honeycomb from top left to bottom right + // based on most close friends to least + ScrollViewReader {scrollReaderValue in + ScrollView([.horizontal, .vertical], showsIndicators: false) { + LazyVGrid( + columns: gridItems, + alignment: .center, + spacing: Self.spacingBetweenRows + ) { + ForEach(0.. Color { + if (userIndex == self.selectedUserIndex) { // user clicked on this user + return NirvanaColor.dimTeal.opacity(0.4) + } +// else if self.usersWithNewMessage.contains(userIndex) { // this user has a message +// return Color.orange.opacity(0.8) +// } + + return Color.white.opacity(0.4) + } + + // getting the proxy of an individual item + // and decoding into a scale that the item should take + private func getScale(proxy: GeometryProxy, itemNumber: Int) -> CGFloat { + // if this user is selected + if itemNumber == self.selectedUserIndex { + return big + 0.2 + } + + // if this user that we are rendering + // has a new message for us + // TODO: too much memory usage doing this across the board +// if self.usersWithNewMessage.contains(itemNumber) { +// return big + 0.2 +// } + + let posRelToGrid = proxy.frame(in: .global) // relative to the entire screen + let midX = getRowNumber(itemNumber) % 2 == 0 ? posRelToGrid.midX + (Self.size / 2) + (Self.spacingBetweenColumns / 2) : posRelToGrid.midX + let midY = posRelToGrid.midY + + let xdelta = abs(midX - self.center.x) + let ydelta = abs(midY - self.center.y) + + let innerCircleXAcceptance = Self.size * 0.75 + let innerCircleYAcceptance = Self.size * 0.75 + let outerRingXAcceptance = self.universalSize.width * 0.4 + let outerRingYAcceptance = self.universalSize.height * 0.25 + let wayOutRingXAcceptance = self.universalSize.width * 0.425 + let wayOutRingYAcceptance = self.universalSize.height * 0.375 + + + if xdelta <= innerCircleXAcceptance && ydelta < innerCircleYAcceptance { + return big + } else if xdelta <= outerRingXAcceptance && ydelta < outerRingYAcceptance { + return medium + } else if xdelta <= wayOutRingXAcceptance && ydelta < wayOutRingYAcceptance { + return small + } + return supersmall + } + + private static func distanceBetweenPoints(p1: CGPoint, p2: CGPoint) -> CGFloat { + let xDist = abs(p2.x - p1.x) + let yDist = abs(p2.y - p2.y) + + return CGFloat( + sqrt( + pow(xDist, 2) + pow(yDist, 2) + ) + ) + } + //get row number given a value/item number in the list + private func getRowNumber(_ value: Int) -> Int { + return value / Self.totalColumns + } + private func honeycombOffSetX(_ value: Int) -> CGFloat { + let rowNumber = self.getRowNumber(value) + + // make every even row have the honeycomb offset + if rowNumber % 2 == 0 { + return Self.size / 2 + Self.spacingBetweenColumns / 2 // account for the column spacing from before + } + + return 0 + } +} + +struct CircleGridView_Previews: PreviewProvider { + static var previews: some View { + CircleGridView() + } +} diff --git a/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift b/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift index 8f73f04..d478d4c 100644 --- a/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift +++ b/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift @@ -44,7 +44,7 @@ struct CircleNavigationView: View { Image((self.authSessionStore.user?.avatar)!) .resizable() .scaledToFit() - .background(NirvanaColor.teal.opacity(0.1)) + .background(NirvanaColor.teal.opacity(0.5)) .frame(width: 40, height: 40) .clipShape(Circle()) .padding(5) diff --git a/nirvana-ios/Views/InnerCircle/InnerCircleView.swift b/nirvana-ios/Views/InnerCircle/InnerCircleView.swift index b4b0089..e99c19b 100644 --- a/nirvana-ios/Views/InnerCircle/InnerCircleView.swift +++ b/nirvana-ios/Views/InnerCircle/InnerCircleView.swift @@ -14,17 +14,13 @@ struct InnerCircleView: View { let universalSize = UIScreen.main.bounds - // TESTING - // users who will have a thumping thing because they sent a message - @State var usersWithNewMessage: [Int] = [] - var body: some View { ZStack { // background WavesGlassBackgroundView() // content - gridContent + CircleGridView() // header VStack(alignment: .leading) { @@ -36,175 +32,9 @@ struct InnerCircleView: View { CircleFooterView() } - .onAppear() { - // TESTING - // fake like these users sent a message to view - DispatchQueue.main.asyncAfter(deadline: .now() + 3) { - self.usersWithNewMessage = [1, 5, 10] - } + .onAppear() { } } - - // magic variables for grid - // TODO: make the top left person or one horizontal person be in the center of screen...makes the top honeycomb pop - private static var numberOfItems: Int = 12 - private static let size: CGFloat = UIScreen.main.bounds.height*0.15 // scaling with screen size - private static let spacingBetweenColumns: CGFloat = 0 - private static let spacingBetweenRows: CGFloat = 0 - private static let totalColumns: Int = Int(log2(Double(Self.numberOfItems))) // scaling the circles and calculating column count - - @State private var selectedUserIndex: Int? = nil - - // TODO: change the size to adaptive or something to make outer ring items shrink their overall size and fit better - let gridItems: [GridItem] = Array( - repeating: GridItem(.fixed(Self.size), spacing: spacingBetweenColumns, alignment: .center), - count: totalColumns) - - private let big:CGFloat = 1 - private let medium:CGFloat = 0.75 - private let small:CGFloat = 0.5 - private let supersmall:CGFloat = 0.3 - - // TODO: centered honeycomb + side: maybe have two honeycombs: one in the center of 7 people and then everyone else surrounding - // TODO: maybe make our "center" offset to a little to the top left to make it more honeycomb from top left - private let center: CGPoint = CGPoint(x: UIScreen.main.bounds.width*0.5,y: UIScreen.main.bounds.height*0.5) - - private var gridContent: some View { - // main communication hub - // TODO: client side, sort the honeycomb from top left to bottom right - // based on most close friends to least - ScrollViewReader {scrollReaderValue in - ScrollView([.horizontal, .vertical], showsIndicators: false) { - LazyVGrid( - columns: gridItems, - alignment: .center, - spacing: Self.spacingBetweenRows - ) { - ForEach(0.. Color { - if (userIndex == self.selectedUserIndex) { // user clicked on this user - return NirvanaColor.dimTeal.opacity(0.4) - } else if self.usersWithNewMessage.contains(userIndex) { // this user has a message - return Color.orange.opacity(0.8) - } - - return Color.white.opacity(0.4) - } - - // getting the proxy of an individual item - // and decoding into a scale that the item should take - private func getScale(proxy: GeometryProxy, itemNumber: Int) -> CGFloat { - // if this user is selected - if itemNumber == self.selectedUserIndex { - return big + 0.2 - } - - // if this user that we are rendering - // has a new message for us - // TODO: too much memory usage doing this across the board - if self.usersWithNewMessage.contains(itemNumber) { - return big + 0.2 - } - - let posRelToGrid = proxy.frame(in: .global) // relative to the entire screen - let midX = getRowNumber(itemNumber) % 2 == 0 ? posRelToGrid.midX + (Self.size / 2) + (Self.spacingBetweenColumns / 2) : posRelToGrid.midX - let midY = posRelToGrid.midY - - let xdelta = abs(midX - self.center.x) - let ydelta = abs(midY - self.center.y) - - let innerCircleXAcceptance = Self.size * 0.75 - let innerCircleYAcceptance = Self.size * 0.75 - let outerRingXAcceptance = self.universalSize.width * 0.4 - let outerRingYAcceptance = self.universalSize.height * 0.25 - let wayOutRingXAcceptance = self.universalSize.width * 0.425 - let wayOutRingYAcceptance = self.universalSize.height * 0.375 - - - if xdelta <= innerCircleXAcceptance && ydelta < innerCircleYAcceptance { - return big - } else if xdelta <= outerRingXAcceptance && ydelta < outerRingYAcceptance { - return medium - } else if xdelta <= wayOutRingXAcceptance && ydelta < wayOutRingYAcceptance { - return small - } - return supersmall - } - - private static func distanceBetweenPoints(p1: CGPoint, p2: CGPoint) -> CGFloat { - let xDist = abs(p2.x - p1.x) - let yDist = abs(p2.y - p2.y) - - return CGFloat( - sqrt( - pow(xDist, 2) + pow(yDist, 2) - ) - ) - } - //get row number given a value/item number in the list - private func getRowNumber(_ value: Int) -> Int { - return value / Self.totalColumns - } - private func honeycombOffSetX(_ value: Int) -> CGFloat { - let rowNumber = self.getRowNumber(value) - - // make every even row have the honeycomb offset - if rowNumber % 2 == 0 { - return Self.size / 2 + Self.spacingBetweenColumns / 2 // account for the column spacing from before - } - - return 0 - } } struct InnerCircleView_Previews: PreviewProvider {