it's just a mess

This commit is contained in:
talksik
2022-05-29 07:54:08 -05:00
parent f704676f62
commit 8391c94976
3 changed files with 159 additions and 41 deletions
+25 -12
View File
@@ -5,23 +5,36 @@ export default class Conversation {
constructor( constructor(
public createdByUserId: string, public createdByUserId: string,
public membersList: string[],
public name: string | null = null, public name: string | null = null,
public lastUpdatedDate = Timestamp.now(),
public createdDate = Timestamp.now(), public createdDate = Timestamp.now(),
public membersInRoom: string[] = [], public membersInRoom: string[] = [],
public lastActivityDate: Timestamp = Timestamp.now(),
) {} ) {}
} }
// export class Member { export class ConversationMember {
// constructor( constructor(
// public id: string, public id: string, // NOTE: serves as the user ID
// public userId: string, public conversationId: string,
// public role: 'admin' | 'regular',
// public joinedDate = Timestamp.now(), public role: MemberRole,
// ) {}
// } public memberState: MemberState,
public lastActiveDate: Timestamp | null = null,
public joinedDate = Timestamp.now(),
) {}
}
export enum MemberRole {
admin = 'admin',
regular = 'regular',
}
export enum MemberState {
priority = 'priority',
inbox = 'inbox',
// deleted = "deleted"
}
+48 -15
View File
@@ -48,25 +48,27 @@ import { useSnackbar } from 'notistack';
import NirvanaLogo from './NirvanaLogo'; import NirvanaLogo from './NirvanaLogo';
import Conversation from '@nirvana/core/src/models/conversation.model'; import Conversation, { ConversationMember } from '@nirvana/core/src/models/conversation.model';
import useAuth from '../providers/AuthProvider'; import useAuth from '../providers/AuthProvider';
import { import {
createOneOnOneConversation, createOneOnOneConversation,
getConversationsQueryLIVE,
getUserById, getUserById,
getUserConversationMembersQueryLIVE,
searchUsers, searchUsers,
} from '../firebase/firestore'; } from '../firebase/firestore';
import { Link, AudioClip, Image } from '@nirvana/core/src/models/content.model'; import { Link, AudioClip, Image } from '@nirvana/core/src/models/content.model';
import { useImmer } from 'use-immer'; import { useImmer } from 'use-immer';
import { User } from '@nirvana/core/src/models/user.model'; import { User } from '@nirvana/core/src/models/user.model';
import { onSnapshot } from 'firebase/firestore'; import { onSnapshot, Unsubscribe } from 'firebase/firestore';
import NirvanaAvatar from './NirvanaAvatar'; import NirvanaAvatar from './NirvanaAvatar';
import { useDebounce, useKey, useKeyPressEvent } from 'react-use'; import { useDebounce, useKey, useKeyPressEvent } from 'react-use';
import KeyboardShortcutLabel from './KeyboardShortcutLabel'; import KeyboardShortcutLabel from './KeyboardShortcutLabel';
import { getConversationQueryLIVE } from '../firebase/firestore';
type ConversationMap = { type ConversationMap = {
[conversationId: string]: Conversation; [conversationId: string]: Partial<MasterConversation>;
}; };
type UserMap = { type UserMap = {
@@ -88,6 +90,8 @@ interface ITerminalContext {
getUser?: (userId: string) => Promise<User | undefined>; getUser?: (userId: string) => Promise<User | undefined>;
} }
type MasterConversation = Conversation & { members: ConversationMember[] };
const TerminalContext = React.createContext<ITerminalContext>({ const TerminalContext = React.createContext<ITerminalContext>({
conversationMap: {}, conversationMap: {},
}); });
@@ -121,23 +125,52 @@ export function TerminalProvider({ children }: { children?: React.ReactNode }) {
const [userMap, updateUserMap] = useImmer<UserMap>({}); const [userMap, updateUserMap] = useImmer<UserMap>({});
const [contentMap, updatecontentMap] = useImmer<ConversationContentMap>({}); const [contentMap, updatecontentMap] = useImmer<ConversationContentMap>({});
// fetch conversations // fetch conversations that I am in
useEffect(() => { useEffect(() => {
const unsub = onSnapshot(getConversationsQueryLIVE(user.uid), (querySnapshot) => { const unsubs: Unsubscribe[] = [];
const conversations = querySnapshot.docs.map((doc) => doc.data());
console.log('got new or updated conversations', conversations); const unsubMyConversationMembers = onSnapshot(
getUserConversationMembersQueryLIVE(user.uid),
(querySnapshot) => {
querySnapshot.docChanges().forEach((docSnapChange) => {
const conversationMember = docSnapChange.doc.data();
const conversationId = conversationMember.conversationId;
updateConversationMap((draft) => { // start listening to conversations
conversations.forEach((convo) => { // get all of the other members
draft[convo.id] = convo; if (docSnapChange.type === 'added') {
const conversationSub = onSnapshot(getConversationQueryLIVE, (conversationSnapshot) => {
const conversation = conversationSnapshot
})
console.log('New city: ', docSnapChange.doc.data());
}
if (docSnapChange.type === 'modified') {
console.log('Modified city: ', docSnapChange.doc.data());
}
if (docSnapChange.type === 'removed') {
console.log('Removed city: ', docSnapChange.doc.data());
}
updateConversationMap((draft) => {
if (draft[conversationMember.conversationId]) {
if (draft[conversationMember.conversationId].members) {
draft[conversationMember.conversationId].members.push(conversationMember);
} else {
draft[conversationMember.conversationId].members = [conversationMember];
}
} else {
draft[conversationMember.conversationId] = { members: [conversationMember] };
}
});
}); });
}); },
);
enqueueSnackbar('got conversations...logging', { variant: 'success' }); unsubs.push(unsubMyConversationMembers)
});
return () => unsub(); return () => {
unsubs.forEach((unsub) => unsub());
};
}, [user, enqueueSnackbar, updateConversationMap]); }, [user, enqueueSnackbar, updateConversationMap]);
// cache of selected conversation // cache of selected conversation
+86 -14
View File
@@ -17,13 +17,18 @@ import {
startAt, startAt,
endAt, endAt,
addDoc, addDoc,
writeBatch,
collectionGroup,
} from 'firebase/firestore'; } from 'firebase/firestore';
import { User as FirebaseUser } from 'firebase/auth'; import { User as FirebaseUser } from 'firebase/auth';
import { firestoreDb } from './connect'; import { firestoreDb } from './connect';
import { User } from '@nirvana/core/src/models/user.model'; import { User } from '@nirvana/core/src/models/user.model';
import Conversation from '@nirvana/core/src/models/conversation.model'; import Conversation, {
import useAuth from '../providers/AuthProvider'; ConversationMember,
MemberRole,
MemberState,
} from '@nirvana/core/src/models/conversation.model';
interface Document { interface Document {
id: string; id: string;
@@ -50,11 +55,17 @@ const docPoint = <T extends Document>(collectionPath: string) =>
const collectionPoint = <T extends Document>(collectionPath: string) => const collectionPoint = <T extends Document>(collectionPath: string) =>
firestoreDb && collection(getFirestore(), collectionPath).withConverter(converter<T>()); firestoreDb && collection(getFirestore(), collectionPath).withConverter(converter<T>());
// const collectionGroupPoint = <T extends Document>(collectionPath: string) =>
// firestoreDb && collectionGroup(getFirestore(), collectionPath).withConverter(converter<T>());
const db = { const db = {
users: collectionPoint<User>(`users`), users: collectionPoint<User>(`users`),
user: (userId: string) => docPoint<User>(`users/${userId}`), user: (userId: string) => docPoint<User>(`users/${userId}`),
conversations: collectionPoint<Conversation>(`conversations`), conversations: collectionPoint<Conversation>(`conversations`),
conversation: (conversationId: string) => docPoint<User>(`conversations/${conversationId}`), conversation: (conversationId: string) =>
docPoint<Conversation>(`conversations/${conversationId}`),
conversationMembers: collectionPoint<ConversationMember>(`conversationMembers`),
conversationMember: () => docPoint<ConversationMember>(`conversationMembers`),
}; };
// enum COLLECTION { // enum COLLECTION {
@@ -127,9 +138,20 @@ export const getUserById = async (userId: string): Promise<User | undefined> =>
return undefined; return undefined;
}; };
// get the conversations for particular user // get conversation members for all conversations that I am in
export const getConversationsQueryLIVE = (userId: string) => export const getUserConversationMembersQueryLIVE = (userId: string) => {
query(db.conversations, where('membersList', 'array-contains', userId)); return query(db.conversationMembers, where('userId', '==', userId));
};
// get all conversation members for a conversation
export const getConversationMembersQueryLIVE = (conversationId: string) => {
return query(db.conversationMembers, where('conversationId', '==', conversationId));
};
// get document reference for specific conversation
export const getConversationQueryLIVE = (conversationId: string) => {
return db.conversation(conversationId);
};
/** /**
* *
@@ -141,11 +163,34 @@ export const createOneOnOneConversation = async (
otherUserId: string, otherUserId: string,
myUserId: string, myUserId: string,
): Promise<string | undefined> => { ): Promise<string | undefined> => {
const newConversation = new Conversation(myUserId, [myUserId, otherUserId], null);
try { try {
const newDoc = await addDoc(db.conversations, newConversation); const newConversation = new Conversation(myUserId);
return newDoc.id; const newDocConversationInserted = await addDoc(db.conversations, newConversation);
const batch = writeBatch(firestoreDb);
// create all members
const adminMember = new ConversationMember(
myUserId,
newDocConversationInserted.id,
MemberRole.admin,
MemberState.priority,
null,
);
const otherMember = new ConversationMember(
otherUserId,
newDocConversationInserted.id,
MemberRole.regular,
MemberState.inbox,
null,
);
batch.set(db.conversationMember(), adminMember);
batch.set(db.conversationMember(), otherMember);
await batch.commit();
return newDocConversationInserted.id;
} catch (e) { } catch (e) {
console.error('Error creating user: ', e); console.error('Error creating user: ', e);
@@ -156,11 +201,38 @@ export const createOneOnOneConversation = async (
export const createGroupConversation = async ( export const createGroupConversation = async (
otherUserIds: string[], otherUserIds: string[],
myUserId: string, myUserId: string,
): Promise<void> => { ): Promise<string> => {
const newConversation = new Conversation(myUserId, [myUserId, ...otherUserIds]);
try { try {
await addDoc(db.conversations, newConversation); const newConversation = new Conversation(myUserId);
const newDocConversationInserted = await addDoc(db.conversations, newConversation);
const batch = writeBatch(firestoreDb);
const adminMember = new ConversationMember(
myUserId,
newDocConversationInserted.id,
MemberRole.admin,
MemberState.priority,
null,
);
batch.set(db.conversationMember(), adminMember);
// create all members
otherUserIds.forEach((otherUserId) => {
const otherMember = new ConversationMember(
otherUserId,
newDocConversationInserted.id,
MemberRole.regular,
MemberState.inbox,
null,
);
batch.set(db.conversationMember(), otherMember);
});
await batch.commit();
return newDocConversationInserted.id;
} catch (e) { } catch (e) {
console.error('Error creating user: ', e); console.error('Error creating user: ', e);