diff --git a/README.md b/README.md index 32a1d80..c753224 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,21 @@ const result = await leaveConversation(conversationId, isSilent); | `conversationId` | `string` | **Required** | | `isSilent` | `boolean` | If `true`, send a system message to the conversation to notify the action | +#### Delete conversation +- Use `useConversation` hook to get `deleteConversation` function. + +```typescript +import {useConversation} from 'rn-firebase-chat'; + +const {deleteConversation} = useConversation(); + +const result = await deleteConversation(conversationId, softDelete); +``` +| Parameter | Type | Description | +| :--------------- | :-------- | :------------------------------------------------------------------------ | +| `conversationId` | `string` | **Required** | +| `softDelete` | `boolean` | If `true`, just delete the conversation from user's list. Otherwise, completely delete the conversation from lists of other members as well. Message history will not be cleared on both case but cannot be accessed. | + ## Contributing See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. diff --git a/src/hooks.ts b/src/hooks.ts index a8f801c..ed682b0 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -76,7 +76,10 @@ const useTypingIndicator = ( const useConversation = () => { const firebaseInstance = useRef(FirestoreServices.getInstance()).current; - return { leaveConversation: firebaseInstance.leaveConversation }; + return { + leaveConversation: firebaseInstance.leaveConversation, + deleteConversation: firebaseInstance.deleteConversation, + }; }; export { useChatContext, useChatSelector, useTypingIndicator, useConversation }; diff --git a/src/services/firebase/firestore.ts b/src/services/firebase/firestore.ts index f66ca86..1166d16 100644 --- a/src/services/firebase/firestore.ts +++ b/src/services/firebase/firestore.ts @@ -823,4 +823,76 @@ export class FirestoreServices { return false; } }; + + checkConversationExist = async (id: string) => { + const conversation = await firestore() + .collection( + this.getUrlWithPrefix( + `${FireStoreCollection.users}/${this.userId}/${FireStoreCollection.conversations}` + ) + ) + .doc(id) + .get(); + + return conversation?.exists; + }; + + /** + * delete conversation from list + * @param forAllMembers indicates whether to remove conversation for all other members or simply remove from user's list + */ + deleteConversation = async ( + conversationId: string, + forAllMembers?: boolean + ): Promise => { + try { + const isConversationExist = + !!conversationId && (await this.checkConversationExist(conversationId)); + if (!isConversationExist) { + console.error('Conversation does not exist'); + return false; + } + + /** Get conversation ref from current user's conversations collection */ + const userConversation = firestore() + .collection( + this.getUrlWithPrefix( + `${FireStoreCollection.users}/${this.userId}/${FireStoreCollection.conversations}` + ) + ) + .doc(conversationId); + + /** Get ID array of conversation's partners (exclude current user) */ + const partnerIds = ( + (await userConversation.get())?.data() as ConversationProps + )?.members?.filter((e) => e !== this.userId); + + /** Delete latest message of that conversation for user (exclude from list) */ + await userConversation.delete(); + if (!forAllMembers) return true; + + /** Delete latest message of that conversation for all other partners */ + const partnerBatch = firestore().batch(); + partnerIds?.forEach(async (id) => { + if (id) { + const doc = firestore() + .collection( + this.getUrlWithPrefix( + `${FireStoreCollection.users}/${id}/${FireStoreCollection.conversations}` + ) + ) + .doc(conversationId); + partnerBatch.delete(doc); + } + }); + await partnerBatch.commit(); + + return true; + } catch (e) { + if (e instanceof Error) { + throw new Error(e.message); + } + return false; + } + }; }