good place with rreplacing ordering, and getting my sent messages and keeping things cleaner and composite key
This commit is contained in:
@@ -14,16 +14,25 @@ struct Message: Identifiable, Codable {
|
|||||||
@DocumentID var id: String? = UUID().uuidString
|
@DocumentID var id: String? = UUID().uuidString
|
||||||
var receiverId: String
|
var receiverId: String
|
||||||
var senderId: String
|
var senderId: String
|
||||||
var listenCount: Int
|
var senderIdReceiverIdComposite: [String]
|
||||||
|
var listenCount: Int?
|
||||||
var audioDataUrl:String
|
var audioDataUrl:String
|
||||||
|
|
||||||
@ServerTimestamp var sentTimestamp:Date?
|
@ServerTimestamp var sentTimestamp:Date?
|
||||||
var firstListenTimestamp:Date?
|
var firstListenTimestamp:Date?
|
||||||
|
|
||||||
|
init(sendId: String, receivId: String, audioDUrl:String) {
|
||||||
|
self.senderIdReceiverIdComposite = [sendId, receivId]
|
||||||
|
self.senderId = sendId
|
||||||
|
self.receiverId = receivId
|
||||||
|
self.audioDataUrl = audioDUrl
|
||||||
|
}
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case id
|
case id
|
||||||
case receiverId
|
case receiverId
|
||||||
case senderId
|
case senderId
|
||||||
|
case senderIdReceiverIdComposite
|
||||||
case listenCount
|
case listenCount
|
||||||
case audioDataUrl
|
case audioDataUrl
|
||||||
case sentTimestamp
|
case sentTimestamp
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ extension AuthSessionStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: keeping the friends list updated
|
// MARK: keeping the friends list updated
|
||||||
// TODO: break into firestoreService
|
// TODO: break into firestoreService metadata of each change...later tho since this listener will barely get changes
|
||||||
// different actions on additions, modifications, and removals
|
// different actions on additions, modifications, and removals
|
||||||
|
|
||||||
// parse through the new result set
|
// parse through the new result set
|
||||||
@@ -279,68 +279,50 @@ extension AuthSessionStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: keeping the list of messages updated
|
// MARK: listener for messages
|
||||||
// one listener for received messages
|
|
||||||
|
|
||||||
// don't know if we need a listener for sent messages as we can alter our model from local and add to the dictionary
|
|
||||||
|
|
||||||
|
// TODO: don't know if we need a listener for sent messages as we can alter our model from local and add to the dictionary
|
||||||
|
// senderIdReceiverIdComposite: composite array of strings which contains the senderId and receiverId as elements
|
||||||
// order: sent time should make it easy to add to dict
|
// order: sent time should make it easy to add to dict
|
||||||
// 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
|
// 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
|
||||||
// TODO: use the indexes I created
|
|
||||||
db.collection("messages").whereField("receiverId", isEqualTo: userId).order(by: "sentTimestamp").limit(to: 100)
|
// SOLUTION: composite with array
|
||||||
|
db.collection("messages").whereField("senderIdReceiverIdComposite", arrayContains: userId).order(by: "sentTimestamp", descending: true).limit(to: 100)
|
||||||
.addSnapshotListener { querySnapshot, error in
|
.addSnapshotListener { querySnapshot, error in
|
||||||
guard let documents = querySnapshot?.documents else {
|
guard let snapshot = querySnapshot else {
|
||||||
print("Error fetching messages: \(error!)")
|
print("Error fetching snapshots: \(error!)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
print("got all messages relevant")
|
try? snapshot.documentChanges.forEach { diff in
|
||||||
|
// only need to modify array on new additions...
|
||||||
self.messagesArr = documents.compactMap { (queryDocumentSnapshot) -> Message? in
|
if (diff.type == .added) {
|
||||||
do {
|
let currMessage = try diff.document.data(as: Message.self)
|
||||||
let currMessage = try queryDocumentSnapshot.data(as: Message.self)
|
print("new message received! \(currMessage)")
|
||||||
print("new message received! \(queryDocumentSnapshot.data())")
|
|
||||||
|
if currMessage != nil { // not really possible but just check
|
||||||
if currMessage != nil { // not really possible but just check
|
// if the user doesn't exist for the dictionary, then add it
|
||||||
// if the user doesn't exist for the dictionary, then add it
|
// this means it's most likely someone new (never had user_friend relationship before) messaging for the user's inbox
|
||||||
// this means it's most likely someone new (never had user_friend relationship before) messaging for the user's inbox
|
// TODO: is the firestore ordering working? maybe need clientside ordering here...just maybe...keep array of messages sorted, but this should automatically be sorted?
|
||||||
// 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
|
if self.friendMessagesDict[currMessage!.senderId] == nil {
|
||||||
if self.friendMessagesDict[currMessage!.senderId] == nil {
|
self.friendMessagesDict[currMessage!.senderId] = [currMessage!]
|
||||||
self.friendMessagesDict[currMessage!.senderId] = [currMessage!]
|
} else { // [2, 1] => [2, 1]
|
||||||
} else {
|
self.friendMessagesDict[currMessage!.senderId]?.append(currMessage!)
|
||||||
self.friendMessagesDict[currMessage!.senderId]?.append(currMessage!)
|
}
|
||||||
|
|
||||||
|
//self.objectWillChange.send()// TODO: maybe don't need? value type friendsMessagesDict? so publishes changes?
|
||||||
}
|
}
|
||||||
|
|
||||||
self.objectWillChange.send()
|
|
||||||
}
|
}
|
||||||
return currMessage
|
// no need to a alter view model as of now
|
||||||
} catch {
|
if (diff.type == .modified) {
|
||||||
print("error in trying to decode message \(error)")
|
print("Modified city: \(diff.document.data())")
|
||||||
|
}
|
||||||
|
// no feature for deleting messages as of now
|
||||||
|
if (diff.type == .removed) {
|
||||||
|
print("Removed city: \(diff.document.data())")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
// TODO: maybe need to call object will change here
|
|
||||||
|
|
||||||
// TODO: optimize later
|
|
||||||
// guard let snapshot = querySnapshot else {
|
|
||||||
// print("Error fetching messages: \(error!)")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// snapshot.documentChanges.forEach { diff in
|
|
||||||
// if (diff.type == .added) {
|
|
||||||
// print("New message: \(diff.document.data())")
|
|
||||||
//
|
|
||||||
// // keep array of messages sorted, but this should automatically be sorted?
|
|
||||||
// }
|
|
||||||
// if (diff.type == .modified) {
|
|
||||||
// // nothing to really do here
|
|
||||||
// print("Modified message: \(diff.document.data())")
|
|
||||||
// }
|
|
||||||
// if (diff.type == .removed) {
|
|
||||||
// print("Removed message: \(diff.document.data())")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func deinitDataListeners() {
|
private func deinitDataListeners() {
|
||||||
|
|||||||
@@ -169,8 +169,9 @@ struct CircleGridView: View {
|
|||||||
if self.authSessionStore.user != nil {
|
if self.authSessionStore.user != nil {
|
||||||
let userId = self.authSessionStore.user!.id // O(1) // currUser who is signed in
|
let userId = self.authSessionStore.user!.id // O(1) // currUser who is signed in
|
||||||
|
|
||||||
|
// get most recent message in the convo and see who has spoken
|
||||||
if let messagesRelatedToFriend = self.authSessionStore.friendMessagesDict[friendDbId] { // O(1)
|
if let messagesRelatedToFriend = self.authSessionStore.friendMessagesDict[friendDbId] { // O(1)
|
||||||
return messagesRelatedToFriend.last?.receiverId == userId && messagesRelatedToFriend.last?.listenCount == 0
|
return messagesRelatedToFriend.first?.receiverId == userId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,25 +285,22 @@ extension CircleGridView {
|
|||||||
|
|
||||||
// TODO: OPTIMIZATION...buffer and load all AVAssets to create AVPlayerItems before a tap happens...but this can also cause load in background if user is not playing a message right now...this isn't an optimization of the data/firestore but rather the player
|
// TODO: OPTIMIZATION...buffer and load all AVAssets to create AVPlayerItems before a tap happens...but this can also cause load in background if user is not playing a message right now...this isn't an optimization of the data/firestore but rather the player
|
||||||
|
|
||||||
// I want to play the last x messages if I was the receiver
|
// I want to play the last x messages if I was the receiver...the array is sorted from backend so that the
|
||||||
// ["sarth": [me, me]] -> play nothing
|
// most recent comes first
|
||||||
// ["sarth": [me, him, him, him]] -> play his two messages
|
// ["sarth": [ME, HIM...]] -> play nothing
|
||||||
|
// ["sarth": [HIM, HIM, me, him...]] -> play his two messages
|
||||||
|
|
||||||
// traverse through reversed list of messages and add to audio player queue
|
// traverse through reversed list of messages and add to audio player queue
|
||||||
// TODO: protect against force unwraps
|
// TODO: protect against force unwraps
|
||||||
var AVPlayerItems: [AVPlayerItem] = []
|
var AVPlayerItems: [AVPlayerItem] = []
|
||||||
let messagesRelatedToFriend = self.authSessionStore.friendMessagesDict[friend.id!]!.reversed()
|
let messagesRelatedToFriend = self.authSessionStore.friendMessagesDict[friend.id!]!
|
||||||
print("have \(messagesRelatedToFriend.count) messages to play")
|
print("have \(messagesRelatedToFriend.count) messages to play")
|
||||||
|
|
||||||
for message in messagesRelatedToFriend {
|
for message in messagesRelatedToFriend {
|
||||||
// if it's me then don't play
|
// if it's starting to get to my messages then don't play
|
||||||
if message.senderId == self.authSessionStore.user?.id {
|
if message.senderId == self.authSessionStore.user?.id {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// if I already listened to this "last" message, then break as well
|
|
||||||
if message.listenCount >= 1 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// only add to queue if we can convert the database url to a valid url here
|
// only add to queue if we can convert the database url to a valid url here
|
||||||
if let audioUrl = URL(string: message.audioDataUrl) {
|
if let audioUrl = URL(string: message.audioDataUrl) {
|
||||||
@@ -310,9 +308,11 @@ extension CircleGridView {
|
|||||||
AVPlayerItems.append(playerMessage)
|
AVPlayerItems.append(playerMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// start playing if there are messages to listen to
|
// start playing if there are messages to listen to
|
||||||
if AVPlayerItems.count > 0 {
|
if AVPlayerItems.count > 0 {
|
||||||
|
// reverse the items because we want to listen to the most recent messages in order
|
||||||
|
AVPlayerItems = AVPlayerItems.reversed()
|
||||||
queuePlayer = AVQueuePlayer(items: AVPlayerItems)
|
queuePlayer = AVQueuePlayer(items: AVPlayerItems)
|
||||||
|
|
||||||
// TODO: make sure these options are viable for different scenarios
|
// TODO: make sure these options are viable for different scenarios
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ class InnerCircleViewModel: ObservableObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let newMessage = Message(receiverId: receiverId, senderId: senderId, listenCount: 0, audioDataUrl: audioDataUrl!.absoluteString)
|
let newMessage = Message(sendId: senderId, receivId: receiverId, audioDUrl: audioDataUrl!.absoluteString)
|
||||||
|
print(newMessage)
|
||||||
// create a new message in firestore with the url for receiving user to automatically get notified
|
// create a new message in firestore with the url for receiving user to automatically get notified
|
||||||
self?.firestoreService.createMessage(message: newMessage) {[weak self] res in
|
self?.firestoreService.createMessage(message: newMessage) {[weak self] res in
|
||||||
print(res)
|
print(res)
|
||||||
|
|||||||
Reference in New Issue
Block a user