Files
2022-02-13 11:25:12 -08:00

262 lines
6.7 KiB
TypeScript

import {
addDoc,
collection,
doc,
Firestore,
getFirestore,
serverTimestamp,
setDoc,
runTransaction,
writeBatch,
arrayUnion,
arrayRemove,
} from "firebase/firestore";
import Conversation, {
AudioClip,
ConversationMember,
ConversationMemberState,
Link,
} from "../models/conversation";
import Collections from "./collections";
import { cloudStorageService } from "./index";
export default class ConversationService {
private db: Firestore = getFirestore();
async test(): Promise<boolean> {
const docRef = doc(this.db, "test", "test");
await setDoc(
docRef,
{ hi: " hiii", lastUpdatedDate: serverTimestamp() },
{ merge: true }
);
return false;
}
async createConversation(
conversation: Conversation,
members: ConversationMember[]
) {
try {
const newConvoRef = doc(
this.db,
Collections.conversations,
conversation.id
);
const newConvo = await runTransaction(this.db, async (transaction) => {
transaction.set(
newConvoRef,
{
...conversation,
createdDate: serverTimestamp(),
lastActivityDate: serverTimestamp(),
},
{ merge: true }
);
return newConvoRef;
});
const batch = writeBatch(this.db);
members.forEach((mem) => {
const newMemberRef = doc(
this.db,
Collections.conversations,
newConvo.id,
Collections.conversationMembers,
mem.id
);
batch.set(newMemberRef, { ...mem, createdDate: serverTimestamp() });
});
await batch.commit();
console.log(
"submitted batch write for each new member of this conversation"
);
} catch (e) {
console.error(e);
throw new Error("Problem in creating conversation");
}
}
async updateUserConvoRelationship(
userId: string,
convoId: string,
newState: ConversationMemberState,
changeLastInteractionDate: boolean = true
) {
const docRef = doc(
this.db,
Collections.conversations,
convoId,
Collections.conversationMembers,
userId
);
const newUpdates = changeLastInteractionDate
? {
state: newState,
lastUpdatedDate: serverTimestamp(),
lastInteractionDate: serverTimestamp(),
}
: {
state: newState,
lastUpdatedDate: serverTimestamp(),
};
await setDoc(docRef, newUpdates, { merge: true });
}
async sendAudioClip(
createdByUserId: string,
audioMp3File: File,
convoId: string
) {
// upload to cloud storage
const downloadUrl = await cloudStorageService.uploadMessageAudioFile(
audioMp3File
);
const newAudioClip = new AudioClip(downloadUrl, createdByUserId);
newAudioClip.audioDataUrl = downloadUrl;
const audioClipRef = doc(
this.db,
Collections.conversations,
convoId,
Collections.conversationAudioClips,
newAudioClip.id
);
const conversationDoc = doc(this.db, Collections.conversations, convoId);
const userConvoAssocDoc = doc(
this.db,
Collections.conversations,
convoId,
Collections.conversationMembers,
createdByUserId
);
await runTransaction(this.db, async (transaction) => {
// want to add to the long term collection of all audio clips for a conversation
transaction.set(
audioClipRef,
{ ...newAudioClip, createdDate: serverTimestamp() },
{ merge: true }
);
// want to make updates to the conversation document itself: set the last item for just the basic information to be
// published to users
transaction.set(
conversationDoc,
{
lastActivityDate: serverTimestamp(),
cachedAudioClip: { ...newAudioClip, createdDate: serverTimestamp() },
},
{ merge: true }
);
// update the user's convo assoc so that their last interaction was set properly
transaction.set(
userConvoAssocDoc,
{
lastInteractionDate: serverTimestamp(),
},
{ merge: true }
);
});
}
async updateTldr(convoId: string, newTldr: string, updateUserId: string) {
// todo make sure that this user is allowed to update it
const docRef = doc(this.db, Collections.conversations, convoId);
await setDoc(
docRef,
{
tldr: newTldr,
lastActivityDate: serverTimestamp(),
lastUpdatedBy: updateUserId,
},
{ merge: true }
);
}
async joinLiveConversation(convoId: string, userJoiningId: string) {
// todo: make sure that user is part of the convo or valid in it
const docRef = doc(this.db, Collections.conversations, convoId);
await setDoc(
docRef,
{
membersInLiveRoom: arrayUnion(userJoiningId),
lastActivityDate: serverTimestamp(),
lastUpdatedBy: userJoiningId,
},
{ merge: true }
);
}
async leaveLiveConversation(convoId: string, userJoiningId: string) {
// todo: make sure that user is part of the convo or valid in it
const docRef = doc(this.db, Collections.conversations, convoId);
await setDoc(
docRef,
{
membersInLiveRoom: arrayRemove(userJoiningId),
lastActivityDate: serverTimestamp(),
lastUpdatedBy: userJoiningId,
},
{ merge: true }
);
}
async shareLink(createdByUserId: string, link: Link, convoId: string) {
const linkRef = doc(
this.db,
Collections.conversations,
convoId,
Collections.conversationLinks,
link.id
);
const conversationDoc = doc(this.db, Collections.conversations, convoId);
const userConvoAssocDoc = doc(
this.db,
Collections.conversations,
convoId,
Collections.conversationMembers,
createdByUserId
);
await runTransaction(this.db, async (transaction) => {
// want to add to the long term collection of all links for a conversation
transaction.set(
linkRef,
{ ...link, createdDate: serverTimestamp() },
{ merge: true }
);
// want to make updates to the conversation document itself: set the last item for just the basic information to be
// published to users
transaction.set(
conversationDoc,
{
lastActivityDate: serverTimestamp(),
cachedLink: { ...link, createdDate: serverTimestamp() },
},
{ merge: true }
);
// update the user's convo assoc so that their last interaction was set properly
transaction.set(
userConvoAssocDoc,
{
lastInteractionDate: serverTimestamp(),
},
{ merge: true }
);
});
}
}