it's just a mess
This commit is contained in:
@@ -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,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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user