astarting data stuff
This commit is contained in:
@@ -53,8 +53,11 @@ all conversations in the conversation map and place in right category /\*\*
|
|||||||
### Data Needed
|
### Data Needed
|
||||||
|
|
||||||
- live conversations going on right now and which people are in them
|
- live conversations going on right now and which people are in them
|
||||||
- all inbox-like conversations such as today, last 7 days, etc
|
- all inbox-like conversations such as today, last 7 days, etc a. being able to
|
||||||
a. being able to play the last message in the conversation with a play button
|
play the last message in the conversation with a play button b. see if there
|
||||||
b. see if there is a new update in the conversation which I have not viewed
|
is a new update in the conversation which I have not viewed c. how many new
|
||||||
- priority conversations
|
audio clips or links are in the conversation
|
||||||
a. need to be able to play any messages from there
|
- priority conversations a. need to be able to play last convo chunk from here
|
||||||
|
and reply from here
|
||||||
|
|
||||||
|
- drawer a. need all links in all conversations where I am active b.
|
||||||
|
|||||||
@@ -1,22 +1,6 @@
|
|||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
import { Timestamp } from "firebase/firestore";
|
import { Timestamp } from "firebase/firestore";
|
||||||
|
|
||||||
export class CompleteConversation {
|
|
||||||
id: string; // conversation id
|
|
||||||
|
|
||||||
conversation: Conversation;
|
|
||||||
|
|
||||||
constructor(convo: Conversation) {
|
|
||||||
this.conversation = convo;
|
|
||||||
this.id = this.conversation.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
userMember?: ConversationMember;
|
|
||||||
|
|
||||||
members: ConversationMember[] = [] as ConversationMember[];
|
|
||||||
audioClips: AudioClip[] = [] as AudioClip[];
|
|
||||||
links: Link[] = [] as Link[];
|
|
||||||
}
|
|
||||||
export default class Conversation {
|
export default class Conversation {
|
||||||
id: string = uuid();
|
id: string = uuid();
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export default class ConversationService {
|
|||||||
{
|
{
|
||||||
...conversation,
|
...conversation,
|
||||||
createdDate: serverTimestamp(),
|
createdDate: serverTimestamp(),
|
||||||
|
lastActivityDate: serverTimestamp(),
|
||||||
},
|
},
|
||||||
{ merge: true }
|
{ merge: true }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { User } from "@nirvana/common/models/user";
|
import { User } from "@nirvana/common/models/user";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { RefObject, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { FaPlus, FaRegTimesCircle, FaSearch } from "react-icons/fa";
|
import { FaPlus, FaRegTimesCircle, FaSearch } from "react-icons/fa";
|
||||||
import { usersIndex } from "../../services/algoliaSearchService";
|
import { usersIndex } from "../../services/algoliaSearchService";
|
||||||
import SimpleLoadingDot from "../Loading/SimpleLoadingDot";
|
import SimpleLoadingDot from "../Loading/SimpleLoadingDot";
|
||||||
@@ -164,10 +164,10 @@ export default function CreateConversation() {
|
|||||||
|
|
||||||
toast.success("Created Conversation");
|
toast.success("Created Conversation");
|
||||||
|
|
||||||
// router.push({
|
router.push({
|
||||||
// pathname: Routes.home,
|
pathname: Routes.home,
|
||||||
// query: { page: QueryRoutes.convos },
|
query: { page: QueryRoutes.convos },
|
||||||
// });
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error("Problem in creating conversation");
|
toast.error("Problem in creating conversation");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import UserStatusBubble from "../UserDetails/UserStatusBubble";
|
|||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
const { currUser } = useAuth();
|
const { currUser } = useAuth();
|
||||||
console.log(currUser);
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,11 @@ import KeyboardShortcutHandler from "../../components/MainTabsOrPages/KeyboardSh
|
|||||||
import SearchResults from "../../components/FullPageExperiences/SearchResults";
|
import SearchResults from "../../components/FullPageExperiences/SearchResults";
|
||||||
import { QueryRoutes, Routes } from "@nirvana/common/helpers/routes";
|
import { QueryRoutes, Routes } from "@nirvana/common/helpers/routes";
|
||||||
import ViewConvo from "../../components/MainTabsOrPages/ViewConvo";
|
import ViewConvo from "../../components/MainTabsOrPages/ViewConvo";
|
||||||
|
import MainRecoilDataHandler from "../../recoil/MainRecoilDataHandler";
|
||||||
|
|
||||||
export default function Me() {
|
export default function Me() {
|
||||||
|
// TODO: if not authenticated, take user away
|
||||||
|
|
||||||
// figure out what content to render from here
|
// figure out what content to render from here
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const currPage = router.query.page;
|
const currPage = router.query.page;
|
||||||
@@ -113,6 +116,8 @@ export default function Me() {
|
|||||||
Me.getLayout = function (content: ReactElement) {
|
Me.getLayout = function (content: ReactElement) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
|
<MainRecoilDataHandler />
|
||||||
|
|
||||||
<KeyboardShortcutHandler />
|
<KeyboardShortcutHandler />
|
||||||
|
|
||||||
<Header />
|
<Header />
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import Conversation, {
|
||||||
|
ConversationMember,
|
||||||
|
} from "@nirvana/common/models/conversation";
|
||||||
|
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 } from "recoil";
|
||||||
|
import { useAuth } from "../contexts/authContext";
|
||||||
|
import { allRelevantConversations, allUsersConversations } from "./main";
|
||||||
|
|
||||||
|
const db = getFirestore();
|
||||||
|
|
||||||
|
export default function MainRecoilDataHandler() {
|
||||||
|
const { currUser } = useAuth();
|
||||||
|
|
||||||
|
const [userConvos, setUserConvos] = useRecoilState(allUsersConversations);
|
||||||
|
const [relevantConvos, setRelevantConvos] = useRecoilState(
|
||||||
|
allRelevantConversations
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const unsubs: Unsubscribe[] = [] as Unsubscribe[];
|
||||||
|
|
||||||
|
const convoSubs: Unsubscribe[] = [] as Unsubscribe;
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
try {
|
||||||
|
// 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) => {
|
||||||
|
if (change.type === "added" || change.type === "modified") {
|
||||||
|
const newConvoMember: ConversationMember =
|
||||||
|
change.doc.data() as ConversationMember;
|
||||||
|
newConvoMember.id = change.doc.id;
|
||||||
|
console.log("modified convo member found: ", change.doc.data());
|
||||||
|
|
||||||
|
// update all user convo associations
|
||||||
|
setUserConvos((prevMap) => {
|
||||||
|
return new Map(prevMap.set(newConvoMember.id, newConvoMember));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
console.log(convoId);
|
||||||
|
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);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
toast.error("Problem in retrieving data");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsubs.forEach((unsub) => {
|
||||||
|
unsub();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
@@ -1,10 +1,69 @@
|
|||||||
|
import Conversation, {
|
||||||
|
ConversationMember,
|
||||||
|
AudioClip,
|
||||||
|
Link,
|
||||||
|
} from "@nirvana/common/models/conversation";
|
||||||
|
|
||||||
import { atom } from "recoil";
|
import { atom } from "recoil";
|
||||||
|
|
||||||
// export enum RecoilActions {
|
export enum RecoilActions {
|
||||||
// CURR_PAGE_PATH = "CURR_PAGE_PATH",
|
CURR_PAGE_PATH = "CURR_PAGE_PATH",
|
||||||
// }
|
ALL_COMPLETE_CONVERSATIONS = "ALL_COMPLETE_CONVERSATIONS",
|
||||||
|
ALL_USERS_CONVERSATION_RELATIONSHIPS = "ALL_USERS_CONVERSATION_RELATIONSHIPS",
|
||||||
|
ALL_RELEVANT_CONVERSATIONS = "ALL_RELEVANT_CONVERSATIONS",
|
||||||
|
}
|
||||||
|
|
||||||
// export const currPagePath = atom({
|
// export const currPagePath = atom({
|
||||||
// key: RecoilActions.CURR_PAGE_PATH, // unique ID (with respect to other atoms/selectors)
|
// key: RecoilActions.CURR_PAGE_PATH, // unique ID (with respect to other atoms/selectors)
|
||||||
// default: "/s", // default value (aka initial value)
|
// default: "/s", // default value (aka initial value)
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
export class CompleteConversation {
|
||||||
|
id: string; // conversation id
|
||||||
|
|
||||||
|
get isLive(): boolean {
|
||||||
|
return this.members?.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// method/property for knowing if this there is a new activity for me in this conversation
|
||||||
|
|
||||||
|
// method/property for getting the latest link if valid
|
||||||
|
|
||||||
|
// method/property to get the latest convo chunk/last person talking
|
||||||
|
|
||||||
|
conversation: Conversation;
|
||||||
|
|
||||||
|
constructor(convo: Conversation) {
|
||||||
|
this.conversation = convo;
|
||||||
|
this.id = this.conversation.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
userMember?: ConversationMember;
|
||||||
|
|
||||||
|
members: ConversationMember[] = [] as ConversationMember[];
|
||||||
|
audioClips: AudioClip[] = [] as AudioClip[];
|
||||||
|
links: Link[] = [] as Link[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// map cache of all complete conversation objects
|
||||||
|
export const allCompleteConversations = atom({
|
||||||
|
key: RecoilActions.ALL_COMPLETE_CONVERSATIONS,
|
||||||
|
default: new Map<string, CompleteConversation>(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// map cache of all relevant users
|
||||||
|
|
||||||
|
// selector for the convos that have members in the live room
|
||||||
|
|
||||||
|
// selectors for convos: inbox/default, live, later, done, priority
|
||||||
|
|
||||||
|
// approach: fill in all "bottom" level atoms, and then build the tree later with selectors
|
||||||
|
export const allUsersConversations = atom({
|
||||||
|
key: RecoilActions.ALL_USERS_CONVERSATION_RELATIONSHIPS,
|
||||||
|
default: new Map<string, ConversationMember>(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const allRelevantConversations = atom({
|
||||||
|
key: RecoilActions.ALL_RELEVANT_CONVERSATIONS,
|
||||||
|
default: new Map<string, Conversation>(),
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user