192 lines
6.5 KiB
TypeScript
192 lines
6.5 KiB
TypeScript
import Conversation, {
|
|
ConversationMember,
|
|
} from "@nirvana/common/models/conversation";
|
|
import User from "@nirvana/common/models/user";
|
|
import Collections from "@nirvana/common/services/collections";
|
|
import {
|
|
collection,
|
|
collectionGroup,
|
|
doc,
|
|
getFirestore,
|
|
onSnapshot,
|
|
query,
|
|
Unsubscribe,
|
|
where,
|
|
} from "firebase/firestore";
|
|
import { useEffect } from "react";
|
|
import toast from "react-hot-toast";
|
|
import { useRecoilState, useSetRecoilState } from "recoil";
|
|
import { useAuth } from "../contexts/authContext";
|
|
import {
|
|
allRelevantContactsAtom,
|
|
allRelevantConversationsAtom,
|
|
allUsersConversationsAtom,
|
|
nirvanaUserDataAtom,
|
|
} from "./main";
|
|
|
|
import { firestoreDb as db } from "../services/firebaseService";
|
|
import { userService } from "@nirvana/common/services";
|
|
|
|
export default function MainRecoilDataHandler() {
|
|
const { currUser } = useAuth();
|
|
const [nirvanaUser, setNirvanaUser] = useRecoilState(nirvanaUserDataAtom);
|
|
|
|
const [userConvos, setUserConvos] = useRecoilState(allUsersConversationsAtom);
|
|
const [relevantConvos, setRelevantConvos] = useRecoilState(
|
|
allRelevantConversationsAtom
|
|
);
|
|
|
|
const [relContacts, setRelContacts] = useRecoilState(allRelevantContactsAtom);
|
|
|
|
useEffect(() => {
|
|
const unsubs: Unsubscribe[] = [] as Unsubscribe[];
|
|
|
|
(async function () {
|
|
try {
|
|
// get my current user profile and stay updated to my status
|
|
const unsubUser = onSnapshot(
|
|
doc(db, Collections.users, currUser!.uid),
|
|
(doc) => {
|
|
if (doc.exists()) {
|
|
const nirvanaUser = doc.data() as User;
|
|
setNirvanaUser(nirvanaUser);
|
|
} else {
|
|
window.open("/teams/profile", "_self");
|
|
}
|
|
}
|
|
);
|
|
unsubs.push(unsubUser);
|
|
|
|
// get all conversations that I am a part of
|
|
const q = query(
|
|
collectionGroup(db, Collections.conversationMembers),
|
|
where("id", "==", currUser?.uid)
|
|
);
|
|
const unsubscribeUserConvoMember = onSnapshot(q, (snapshot) => {
|
|
snapshot.docChanges().forEach((change) => {
|
|
const newConvoMember: ConversationMember =
|
|
change.doc.data() as ConversationMember;
|
|
newConvoMember.id = change.doc.id;
|
|
|
|
if (change.type === "added" || change.type === "modified") {
|
|
// if we are adding a new convo relevant to me, then start a convo listener for this convo
|
|
const convoId = change.doc.ref.parent.parent!.id;
|
|
|
|
// update all user convo associations
|
|
setUserConvos((prevMap) => {
|
|
return new Map(prevMap.set(convoId, newConvoMember));
|
|
});
|
|
|
|
// if we are adding a new convo relevant to me, then start a convo listener for this convo
|
|
|
|
// find if this is a done, later, or inbox, and only add listeners accordingly
|
|
// if (change.type === "added" && convoId) {
|
|
// const unsubConvo = onSnapshot(
|
|
// doc(db, Collections.conversations, convoId),
|
|
// (convoDoc) => {
|
|
// const updatedConvo = convoDoc.data() as Conversation;
|
|
// console.log("got convo data and subscribed");
|
|
// console.log(updatedConvo);
|
|
|
|
// setRelevantConvos((prevMap) => {
|
|
// return new Map(prevMap.set(convoId, updatedConvo));
|
|
// });
|
|
// }
|
|
// );
|
|
|
|
// // todo : remove specific listeners if they are no longer priority conversations
|
|
|
|
// unsubs.push(unsubConvo);
|
|
// }
|
|
}
|
|
if (change.type === "removed") {
|
|
console.log("Removed convo member: ", change.doc.data());
|
|
}
|
|
});
|
|
});
|
|
|
|
unsubs.push(unsubscribeUserConvoMember);
|
|
|
|
// get every conversation where I am in the activeMembers list
|
|
const convoQuery = query(
|
|
collection(db, Collections.conversations),
|
|
where("activeMembers", "array-contains", currUser!.uid)
|
|
);
|
|
const unsubConvosListener = onSnapshot(convoQuery, (snapshot) => {
|
|
const arrayConvos: Conversation[] = [];
|
|
snapshot.docChanges().forEach((change) => {
|
|
const newOrUpdatedConvo: Conversation =
|
|
change.doc.data() as Conversation;
|
|
newOrUpdatedConvo.id = change.doc.id;
|
|
|
|
if (change.type === "added" || change.type === "modified") {
|
|
arrayConvos.push(newOrUpdatedConvo);
|
|
}
|
|
if (change.type === "removed") {
|
|
// todo: if convo was removed for me, then take out of array
|
|
// arrayConvos.filter()
|
|
}
|
|
});
|
|
|
|
// build user's cache
|
|
let allUsersToCache: string[] = [] as string[];
|
|
|
|
arrayConvos.forEach((currconvo) => {
|
|
allUsersToCache = [...allUsersToCache, ...currconvo.activeMembers];
|
|
});
|
|
|
|
// console.log(
|
|
// "going to try caching a bunch of users...maybe some duplicates",
|
|
// allUsersToCache
|
|
// );
|
|
|
|
// if this userId is in the contacts map, then cool
|
|
// otherwise fetch with userService
|
|
|
|
allUsersToCache.map(async (oUser) => {
|
|
if (
|
|
relContacts.has(oUser) &&
|
|
relContacts.get(oUser) instanceof User
|
|
) {
|
|
// do nothing
|
|
// console.log("user already cached, no need to re-cache");
|
|
} else {
|
|
// otherwise, fetch document from firestore and then set the cache
|
|
const retrievedUser = await userService.getUser(oUser);
|
|
// console.log("fetching user to add to cache");
|
|
|
|
if (retrievedUser) {
|
|
setRelContacts(new Map(relContacts.set(oUser, retrievedUser)));
|
|
}
|
|
}
|
|
});
|
|
|
|
// add to the main convos atom, by modifying the current map
|
|
setRelevantConvos((prevConvosMap) => {
|
|
const newMap = new Map(prevConvosMap);
|
|
arrayConvos.forEach((currconvo) => {
|
|
newMap.set(currconvo.id, currconvo);
|
|
});
|
|
|
|
// console.log("updated convos: ", newMap);
|
|
|
|
return newMap;
|
|
});
|
|
});
|
|
unsubs.push(unsubConvosListener);
|
|
} catch (error) {
|
|
console.log(error);
|
|
toast.error("Problem in retrieving data");
|
|
}
|
|
})();
|
|
|
|
return () => {
|
|
unsubs.forEach((unsub) => {
|
|
unsub();
|
|
});
|
|
};
|
|
}, []);
|
|
|
|
return <></>;
|
|
}
|