getting decently far in handling the data for friends and all
This commit is contained in:
@@ -37,6 +37,8 @@ final class AuthSessionStore: ObservableObject, SessionStore {
|
|||||||
var userFriendsDict: [String: UserFriends] = [:] // all active and inactive relationships
|
var userFriendsDict: [String: UserFriends] = [:] // all active and inactive relationships
|
||||||
|
|
||||||
// transformed data for the views
|
// transformed data for the views
|
||||||
|
@Published var friendsArr: [String] = []
|
||||||
|
@Published var inboxUsersArr: [String] = []
|
||||||
@Published var relevantUsersDict: [String: User] = [:] // all cached/snapshotted users from db for app use
|
@Published var relevantUsersDict: [String: User] = [:] // all cached/snapshotted users from db for app use
|
||||||
@Published var relevantMessagesByUserDict: [String: [Message]] = [:] // note, this is all messages related to me
|
@Published var relevantMessagesByUserDict: [String: [Message]] = [:] // note, this is all messages related to me
|
||||||
|
|
||||||
@@ -217,7 +219,7 @@ extension AuthSessionStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: keeping the @Published user object updated
|
// MARK: keeping the @Published user object updated
|
||||||
// TODO: THIS WON"T UPDATE VIEW since user is a reference type...can manually publish...research and learn more
|
// TODO: THIS WON'T UPDATE VIEW since user is a reference type...can manually publish...research and learn more
|
||||||
self.firestoreService.getUserRealtime(userId: currUserId!) {[weak self] realtimeUpdatedUser in
|
self.firestoreService.getUserRealtime(userId: currUserId!) {[weak self] realtimeUpdatedUser in
|
||||||
if realtimeUpdatedUser != nil {
|
if realtimeUpdatedUser != nil {
|
||||||
print("up to date user: \(realtimeUpdatedUser)")
|
print("up to date user: \(realtimeUpdatedUser)")
|
||||||
@@ -228,24 +230,18 @@ extension AuthSessionStore {
|
|||||||
|
|
||||||
// MARK: keeping the friends list updated
|
// MARK: keeping the friends list updated
|
||||||
// TODO: break into firestoreService metadata of each change...later tho since this listener will barely get changes
|
// TODO: break into firestoreService metadata of each change...later tho since this listener will barely get changes
|
||||||
// different actions on additions, modifications, and removals
|
|
||||||
|
|
||||||
// parse through the new result set
|
|
||||||
// if already exists in dict, then make sure not to delete the associated list
|
|
||||||
|
|
||||||
// order: when the relationship was created...also easy for user
|
|
||||||
// limit: for my protection of db costs lol
|
|
||||||
// TODO: use the indexes I created
|
|
||||||
let friendsListener = db.collection("user_friends").whereField("userId", isEqualTo: currUserId).limit(to: 100)
|
let friendsListener = db.collection("user_friends").whereField("userId", isEqualTo: currUserId).limit(to: 100)
|
||||||
.addSnapshotListener { querySnapshot, error in
|
.addSnapshotListener { querySnapshot, error in
|
||||||
|
print("friends listener activated")
|
||||||
|
|
||||||
guard let documents = querySnapshot?.documents else {
|
guard let documents = querySnapshot?.documents else {
|
||||||
print("Error fetching user's friends: \(error!)")
|
print("Error fetching user's friends: \(error!)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// resetting array to reset friends
|
// resetting array to reset friends
|
||||||
self.relevantUsersDict.removeAll()
|
|
||||||
self.userFriendsDict.removeAll()
|
self.userFriendsDict.removeAll()
|
||||||
|
self.friendsArr.removeAll() // updating to keep the friends in order
|
||||||
|
|
||||||
for document in querySnapshot!.documents {
|
for document in querySnapshot!.documents {
|
||||||
let userFriend:UserFriends? = try? document.data(as: UserFriends.self)
|
let userFriend:UserFriends? = try? document.data(as: UserFriends.self)
|
||||||
@@ -265,6 +261,18 @@ extension AuthSessionStore {
|
|||||||
if returnedUser != nil {
|
if returnedUser != nil {
|
||||||
self.relevantUsersDict[userFriend!.friendId] = returnedUser!
|
self.relevantUsersDict[userFriend!.friendId] = returnedUser!
|
||||||
|
|
||||||
|
// making sure that I clear the inbox if this user came from the inbox...regardless of
|
||||||
|
// whether I accepted or rejected them
|
||||||
|
if self.inboxUsersArr.contains(userFriend!.friendId) {
|
||||||
|
self.inboxUsersArr = self.inboxUsersArr.filter {inboxUserId in
|
||||||
|
return inboxUserId != userFriend!.friendId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if userFriend!.isActive {
|
||||||
|
self.friendsArr.append(userFriend!.friendId)
|
||||||
|
}
|
||||||
|
|
||||||
self.objectWillChange.send()
|
self.objectWillChange.send()
|
||||||
|
|
||||||
print("added this user to the array of users for user's circle\(returnedUser?.nickname)")
|
print("added this user to the array of users for user's circle\(returnedUser?.nickname)")
|
||||||
@@ -276,28 +284,51 @@ extension AuthSessionStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: optimize later with the conditionals
|
|
||||||
// guard let snapshot = querySnapshot else {
|
|
||||||
// print("Error fetching user's friends: \(error!)")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// snapshot.documentChanges.forEach { diff in
|
|
||||||
//
|
|
||||||
// if (diff.type == .added) {
|
|
||||||
// print("New friend in circle: \(diff.document.data())")
|
|
||||||
// }
|
|
||||||
// if (diff.type == .modified) {
|
|
||||||
// // maybe it was deactivated or activated
|
|
||||||
// print("Modified relationship: \(diff.document.data())")
|
|
||||||
// }
|
|
||||||
// if (diff.type == .removed) {
|
|
||||||
// print("Removed city: \(diff.document.data())")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// listener for people who have me as an active friend might make inbox easier
|
||||||
|
// where friendId = me, isActive = true...this way it's a published property that can update the ui
|
||||||
|
// as inbox users is only being called on load
|
||||||
|
|
||||||
|
let inboxUsersListener = db.collection("user_friends").whereField("friendId", isEqualTo: currUserId).whereField("isActive", isEqualTo: true)
|
||||||
|
.addSnapshotListener { querySnapshot, error in
|
||||||
|
print("inbox users listener")
|
||||||
|
guard let documents = querySnapshot?.documents else {
|
||||||
|
print("Error fetching friends who have me as a friend: \(error!)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inboxUsersArr.removeAll()
|
||||||
|
|
||||||
|
for document in querySnapshot!.documents {
|
||||||
|
let userFriend:UserFriends? = try? document.data(as: UserFriends.self)
|
||||||
|
|
||||||
|
if userFriend == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this user is not already a friend, active or inactive/rejected, then get their user data and add to inbox
|
||||||
|
if self.userFriendsDict.keys.contains(userFriend!.userId) {
|
||||||
|
print("already have this user in my circle or I rejected them \(userFriend?.friendId)")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.firestoreService.getUser(userId: userFriend!.userId) {[weak self] returnedUser in
|
||||||
|
if returnedUser == nil {
|
||||||
|
print("couldn't get new user info")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("new user for inbox fetched \(returnedUser!.nickname)")
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// add data to our app cache of users for their info down the road
|
||||||
|
self?.relevantUsersDict[userFriend!.userId] = returnedUser!
|
||||||
|
self?.inboxUsersArr.append(userFriend!.userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: listener for messages
|
// MARK: listener for messages
|
||||||
|
|
||||||
@@ -309,6 +340,8 @@ extension AuthSessionStore {
|
|||||||
// SOLUTION: composite with array
|
// SOLUTION: composite with array
|
||||||
let messagesListener = db.collection("messages").whereField("senderIdReceiverIdComposite", arrayContains: currUserId).order(by: "sentTimestamp", descending: true).limit(to: 100)
|
let messagesListener = db.collection("messages").whereField("senderIdReceiverIdComposite", arrayContains: currUserId).order(by: "sentTimestamp", descending: true).limit(to: 100)
|
||||||
.addSnapshotListener { querySnapshot, error in
|
.addSnapshotListener { querySnapshot, error in
|
||||||
|
print("messages listener activated")
|
||||||
|
|
||||||
guard let documents = querySnapshot?.documents else {
|
guard let documents = querySnapshot?.documents else {
|
||||||
print("error in fetching messages: \(error!)")
|
print("error in fetching messages: \(error!)")
|
||||||
return
|
return
|
||||||
@@ -343,22 +376,6 @@ extension AuthSessionStore {
|
|||||||
} else {
|
} else {
|
||||||
self.relevantMessagesByUserDict[currMessage!.senderId]?.append(currMessage!)
|
self.relevantMessagesByUserDict[currMessage!.senderId]?.append(currMessage!)
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to get and add this user to inbox if they are not a friend, active or inactive
|
|
||||||
// self.updateInboxUsers(currMessage!.senderId)
|
|
||||||
// might be an inbox message from someone completely new, but also can be a concurrency thing, where we haven't completely fetched all friends, active or inactive with the previous listener
|
|
||||||
// no worries though as we keep everything update to date in the view
|
|
||||||
if !self.relevantUsersDict.keys.contains(currMessage!.senderId) {
|
|
||||||
self.firestoreService.getUser(userId: currMessage!.senderId) {[weak self] returnedUser in
|
|
||||||
if returnedUser == nil {
|
|
||||||
print("couldn't get new user info")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
print("new user for inbox fetched")
|
|
||||||
self?.relevantUsersDict[currMessage!.senderId] = returnedUser!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,10 +390,6 @@ extension AuthSessionStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// listener for people who have me as an active friend might make inbox easier
|
|
||||||
// where friendId = me, isActive = true...this way it's a published property that can update the ui
|
|
||||||
// as inbox users is only being called on load
|
|
||||||
|
|
||||||
self.listenersActive = true
|
self.listenersActive = true
|
||||||
|
|
||||||
// adding listeners to be able to deinit later
|
// adding listeners to be able to deinit later
|
||||||
@@ -384,6 +397,7 @@ extension AuthSessionStore {
|
|||||||
// self.dataListeners.append(currUserListener)
|
// self.dataListeners.append(currUserListener)
|
||||||
self.dataListeners.append(messagesListener)
|
self.dataListeners.append(messagesListener)
|
||||||
self.dataListeners.append(friendsListener)
|
self.dataListeners.append(friendsListener)
|
||||||
|
self.dataListeners.append(inboxUsersListener)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,27 +411,3 @@ extension AuthSessionStore {
|
|||||||
self.listenersActive = false
|
self.listenersActive = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// transforming data to make it more valuable
|
|
||||||
extension AuthSessionStore {
|
|
||||||
func getActiveFriendIds() -> [String] {
|
|
||||||
// TODO: order friends by user friend creation date as dictionaries don't have any inherent order
|
|
||||||
// they order randomly through hash value creation
|
|
||||||
var activeFriendIds: [String] = []
|
|
||||||
|
|
||||||
for (friendId, userFriend) in self.userFriendsDict {
|
|
||||||
if userFriend.isActive {
|
|
||||||
activeFriendIds.append(friendId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return activeFriendIds
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInboxUsersIds() -> [String] {
|
|
||||||
return self.relevantUsersDict.keys.filter {userId in
|
|
||||||
return !self.userFriendsDict.keys.contains(userId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ struct FindFriendsView: View {
|
|||||||
// main content
|
// main content
|
||||||
NavigationView {
|
NavigationView {
|
||||||
VStack {
|
VStack {
|
||||||
Text("You must have someone in your phone contacts to add them. Remember: \(self.authSessionStore.getActiveFriendIds().count)/10 spots filled in your circle. 🥬")
|
Text("You must have someone in your phone contacts to add them. Remember: \(self.authSessionStore.friendsArr.count)/10 spots filled in your circle. 🥬")
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.foregroundColor(Color.gray)
|
.foregroundColor(Color.gray)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
@@ -58,13 +58,11 @@ struct FindFriendsView: View {
|
|||||||
let keys = (Array(self.contactsVM.contacts.keys) as [String]).sorted()
|
let keys = (Array(self.contactsVM.contacts.keys) as [String]).sorted()
|
||||||
|
|
||||||
// checking if currcontact is already a friend
|
// checking if currcontact is already a friend
|
||||||
let activeFriendIds = self.authSessionStore.getActiveFriendIds()
|
|
||||||
|
|
||||||
let newPotentialFriends = keys.filter {contactSortProp in
|
let newPotentialFriends = keys.filter {contactSortProp in
|
||||||
if let friend = self.contactsVM.contacts[contactSortProp]?.user { // seeing if this contact is an existing user
|
if let friend = self.contactsVM.contacts[contactSortProp]?.user { // seeing if this contact is an existing user
|
||||||
// if this is already an ACTIVE friend -> don't show
|
// if this is already an ACTIVE friend -> don't show
|
||||||
// we want to show inactive friends
|
// we want to show inactive friends
|
||||||
if activeFriendIds.contains(friend.id!) {
|
if self.authSessionStore.friendsArr.contains(friend.id!) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ struct CircleGridView: View {
|
|||||||
// based on most close friends to least
|
// based on most close friends to least
|
||||||
|
|
||||||
// MARK: data entry point
|
// MARK: data entry point
|
||||||
let activeFriends = self.authSessionStore.getActiveFriendIds()
|
let activeFriends = self.authSessionStore.friendsArr
|
||||||
let inboxUsers = self.authSessionStore.getInboxUsersIds()
|
let inboxUsers = self.authSessionStore.inboxUsersArr
|
||||||
|
|
||||||
ScrollViewReader {scrollReaderValue in
|
ScrollViewReader {scrollReaderValue in
|
||||||
ScrollView([.horizontal, .vertical], showsIndicators: false) {
|
ScrollView([.horizontal, .vertical], showsIndicators: false) {
|
||||||
@@ -152,7 +152,7 @@ struct CircleGridView: View {
|
|||||||
// inbox users
|
// inbox users
|
||||||
ForEach(0..<inboxUsers.count, id: \.self) {inboxValue in
|
ForEach(0..<inboxUsers.count, id: \.self) {inboxValue in
|
||||||
let inboxUserId = inboxUsers[inboxValue]
|
let inboxUserId = inboxUsers[inboxValue]
|
||||||
let adjustedValue = inboxValue + self.authSessionStore.getActiveFriendIds().count // IMPORTANT: accounting for the active friends iterations
|
let adjustedValue = inboxValue + activeFriends.count // IMPORTANT: accounting for the active friends iterations
|
||||||
GeometryReader {gridProxy in
|
GeometryReader {gridProxy in
|
||||||
let scale = getScale(proxy: gridProxy, itemNumber: adjustedValue, userId: inboxUserId) * 0.75 // don't want inbox to match size of active
|
let scale = getScale(proxy: gridProxy, itemNumber: adjustedValue, userId: inboxUserId) * 0.75 // don't want inbox to match size of active
|
||||||
|
|
||||||
@@ -161,6 +161,8 @@ struct CircleGridView: View {
|
|||||||
.foregroundColor(NirvanaColor.dimTeal)
|
.foregroundColor(NirvanaColor.dimTeal)
|
||||||
.font(.title)
|
.font(.title)
|
||||||
|
|
||||||
|
Text("\(activeFriends.count)")
|
||||||
|
|
||||||
Circle()
|
Circle()
|
||||||
.foregroundColor(NirvanaColor.dimTeal.opacity(0.3)) // different color for a selected user
|
.foregroundColor(NirvanaColor.dimTeal.opacity(0.3)) // different color for a selected user
|
||||||
.blur(radius: 5)
|
.blur(radius: 5)
|
||||||
@@ -187,7 +189,7 @@ struct CircleGridView: View {
|
|||||||
let inboxFriendNumber = self.authSessionStore.relevantUsersDict[inboxUserId]?.phoneNumber
|
let inboxFriendNumber = self.authSessionStore.relevantUsersDict[inboxUserId]?.phoneNumber
|
||||||
|
|
||||||
self.alertText = "🌴Add to your circle?"
|
self.alertText = "🌴Add to your circle?"
|
||||||
self.alertSubtext = "\(inboxFriendName ?? "") started a convo with you... \n \(inboxFriendNumber!) \n Remember: you have \(10 - activeFriends.count) spots left!"
|
self.alertSubtext = "\(inboxFriendName ?? "") started a convo with you... \n \(inboxFriendNumber ?? "") \n Remember: you have \(10 - activeFriends.count) spots left!"
|
||||||
self.alertActive.toggle()
|
self.alertActive.toggle()
|
||||||
}
|
}
|
||||||
.animation(Animation.spring())
|
.animation(Animation.spring())
|
||||||
@@ -212,7 +214,7 @@ struct CircleGridView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// stale state for adding a contact
|
// stale state for adding a contact
|
||||||
let staleAdjustedValue = self.authSessionStore.getActiveFriendIds().count + self.authSessionStore.getInboxUsersIds().count
|
let staleAdjustedValue = activeFriends.count + inboxUsers.count
|
||||||
GeometryReader {gridProxy in
|
GeometryReader {gridProxy in
|
||||||
let scale = getScale(proxy: gridProxy, itemNumber: staleAdjustedValue, userId: nil) * 0.75 // adjusting size as stale states should be the smallest
|
let scale = getScale(proxy: gridProxy, itemNumber: staleAdjustedValue, userId: nil) * 0.75 // adjusting size as stale states should be the smallest
|
||||||
Button {
|
Button {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ struct InnerCircleView: View {
|
|||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
else if self.authSessionStore.getActiveFriendIds().count == 0 && self.authSessionStore.getInboxUsersIds().count == 0 {
|
else if self.authSessionStore.friendsArr.count == 0 && self.authSessionStore.inboxUsersArr.count == 0 {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Image("undraw_fall_is_coming_yl-0-x")
|
Image("undraw_fall_is_coming_yl-0-x")
|
||||||
.renderingMode(.original)
|
.renderingMode(.original)
|
||||||
@@ -102,7 +102,7 @@ struct InnerCircleView: View {
|
|||||||
|
|
||||||
// helper for new users
|
// helper for new users
|
||||||
// TODO: make it back to 1 instead of 10...testing
|
// TODO: make it back to 1 instead of 10...testing
|
||||||
if self.authSessionStore.getActiveFriendIds().count == 1 && self.selectedFriendIndex == nil { // don't show if bottom metadata showing
|
if self.authSessionStore.friendsArr.count == 1 && self.selectedFriendIndex == nil { // don't show if bottom metadata showing
|
||||||
ZStack(alignment: .bottomTrailing) {
|
ZStack(alignment: .bottomTrailing) {
|
||||||
Color.clear
|
Color.clear
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user