diff --git a/nirvana-ios/Services/AuthSessionStore.swift b/nirvana-ios/Services/AuthSessionStore.swift index cfa1032..87c5126 100644 --- a/nirvana-ios/Services/AuthSessionStore.swift +++ b/nirvana-ios/Services/AuthSessionStore.swift @@ -39,6 +39,9 @@ final class AuthSessionStore: ObservableObject, SessionStore { // transformed data for the views @Published var friendMessagesDict: [String: [Message]] = [:] + private var dataListeners: [ListenerRegistration] = [] + private var listenersActive = false // false on app/processes killed + // TODO: temporary...should not have this here private var db = Firestore.firestore() @@ -117,10 +120,10 @@ final class AuthSessionStore: ObservableObject, SessionStore { } func logOut() { - let firebaseAuth = Auth.auth() - do { - try firebaseAuth.signOut() + try Auth.auth().signOut() + + self.deinitDataListeners() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) } @@ -132,6 +135,10 @@ final class AuthSessionStore: ObservableObject, SessionStore { } } + func getCurrentUserId() -> String? { + return Auth.auth().currentUser?.uid + } + func setupAuthListen() { // monitor authentication changes using firebase self.handler = Auth.auth().addStateDidChangeListener { [weak self] res, authUser in @@ -140,6 +147,7 @@ final class AuthSessionStore: ObservableObject, SessionStore { guard let self = self else { return } self.sessionState = authUser == nil ? SessionState.isLoggedOut : SessionState.isAuthenticated + print("set the session state to \(self.sessionState)") // get the user from the auth table in firebase auth if let uid = authUser?.uid { @@ -147,9 +155,6 @@ final class AuthSessionStore: ObservableObject, SessionStore { print("auth listener: Got user: \(uid)") print("auth listener: phone number: \(authUser?.phoneNumber)") - // MARK: data listeners for entire environment - self.activateMainDataListeners(userId: uid) - } else { // if we don't have a user, set our session to nil self.user = nil @@ -172,14 +177,9 @@ extension UIApplication { } -struct MasterUserFriendsMessagesModel { - -} - +// activate data listeners for the main data throughout the app extension AuthSessionStore { - - // get all my friends // traverse all my friends, and put them into the friendsDict @@ -195,12 +195,29 @@ extension AuthSessionStore { // I send a new message to sarth -> goes to messages database -> notification to sarth // sarth's data looks like this: [arjun: [...arjun's message, sarth's reply...]] - - - private func activateMainDataListeners(userId: String) { + func activateMainDataListeners() { + // do nothing if the snapshots are already alive + if self.listenersActive { + print("listeners already alive...no point reinitiating") + return + } + + // extra validation to make sure that we are authenticated although should be if this is called + if self.sessionState != SessionState.isAuthenticated { + print("can't initiate data listeners...user not authenticated") + return + } + + // can't get proper listeners working if don't have current user's id + let currUserId = self.getCurrentUserId() + if currUserId == nil { + print("no user id available to initiate data listeners") + return + } + // 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 - self.firestoreService.getUserRealtime(userId: userId) {[weak self] realtimeUpdatedUser in + self.firestoreService.getUserRealtime(userId: currUserId!) {[weak self] realtimeUpdatedUser in if realtimeUpdatedUser != nil { print("up to date user: \(realtimeUpdatedUser)") self?.user = realtimeUpdatedUser @@ -218,7 +235,7 @@ extension AuthSessionStore { // order: when the relationship was created...also easy for user // limit: for my protection of db costs lol // TODO: use the indexes I created - db.collection("user_friends").whereField("userId", isEqualTo: userId).limit(to: 100) + let friendsListener = db.collection("user_friends").whereField("userId", isEqualTo: currUserId).limit(to: 100) .addSnapshotListener { querySnapshot, error in guard let documents = querySnapshot?.documents else { print("Error fetching user's friends: \(error!)") @@ -281,7 +298,7 @@ extension AuthSessionStore { // limit: because each user should have most 12 friends and so would at most need 24 messages to show turns and all that...save myself from hackers here...unless a user gets 100 messages from someone, and that too at least they will be ordered // SOLUTION: composite with array - db.collection("messages").whereField("senderIdReceiverIdComposite", arrayContains: userId).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 guard let documents = querySnapshot?.documents else { print("error in fetching messages: \(error!)") @@ -304,7 +321,7 @@ extension AuthSessionStore { // this means it's most likely someone new (never had user_friend relationship before) messaging for the user's inbox // TODO: prolly want to make a call to get this sender user details for the inbox, but they should either be in the friendsArr or their are not a friend so won't be there // also add in any messages where I am the sender - if currMessage!.senderId == userId { // if I am the sender + if currMessage!.senderId == currUserId { // if I am the sender if self.friendMessagesDict[currMessage!.receiverId] == nil { self.friendMessagesDict[currMessage!.receiverId] = [currMessage!] } else { @@ -318,7 +335,6 @@ extension AuthSessionStore { self.friendMessagesDict[currMessage!.senderId]?.append(currMessage!) } } - } self.objectWillChange.send() @@ -331,9 +347,24 @@ extension AuthSessionStore { return nil } } - } - - private func deinitDataListeners() { + + self.listenersActive = true + + // adding listeners to be able to deinit later + // TODO: make sure to have this listener avaible available to deinit as well + // self.dataListeners.append(currUserListener) + self.dataListeners.append(messagesListener) + self.dataListeners.append(friendsListener) } + + func deinitDataListeners() { + for listener in self.dataListeners { + listener.remove() + } + + print("deactivated listeners!") + + self.listenersActive = false + } } diff --git a/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift b/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift index 04abb75..4687670 100644 --- a/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift +++ b/nirvana-ios/Views/InnerCircle/CircleNavigationView.swift @@ -58,6 +58,8 @@ struct CircleNavigationView: View { self.authSessionStore.logOut() + // TODO: brute force navigating out as it's not working + self.navigationStack.push(RouterView()) // once logged out, then the listener will listen and router view will take care of us thereafter } label: { Label("log out", systemImage: "rectangle.portrait.and.arrow.right") diff --git a/nirvana-ios/Views/InnerCircle/InnerCircleView.swift b/nirvana-ios/Views/InnerCircle/InnerCircleView.swift index 7cc8d15..cab7b14 100644 --- a/nirvana-ios/Views/InnerCircle/InnerCircleView.swift +++ b/nirvana-ios/Views/InnerCircle/InnerCircleView.swift @@ -116,7 +116,7 @@ struct InnerCircleView: View { Button { self.alertActive.toggle() self.alertText = "πŸ‘†πŸΌIt's simple!" - self.alertSubtext = "Press and hold to send a message. \n Tap to listen!" + self.alertSubtext = "Press and hold on a friend to send a message. \n Tap on them to listen!" } label: { Label("help!πŸ™‰", systemImage: "questionmark.circle") .font(.caption) @@ -139,6 +139,18 @@ struct InnerCircleView: View { } message: { Text(self.alertSubtext) } + .onAppear { + // activate 3 data listeners once for authsessionstore/usermanager if not already called, but authsessionstore will handle that + self.authSessionStore.activateMainDataListeners() + + // save device token + } +// .onDisappear { +// print("deiniting data listeners, but current data should still be cached!") +// +// // deactivate all data listeners +// self.authSessionStore.deinitDataListeners() +// } } } diff --git a/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift b/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift index 3552d04..501c27c 100644 --- a/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift +++ b/nirvana-ios/Views/InnerCircle/InnerCircleViewModel.swift @@ -33,6 +33,10 @@ class InnerCircleViewModel: ObservableObject { } } +} + +// audio stuff +extension InnerCircleViewModel { func startRecording() { let filePath = getTemporaryDirectory().appendingPathComponent("\(UUID().uuidString).m4a") @@ -98,3 +102,7 @@ class InnerCircleViewModel: ObservableObject { } +// handling saving device token for notifications +extension InnerCircleViewModel { + +}