Skip to content

Commit

Permalink
Watch thread main message mutations
Browse files Browse the repository at this point in the history
  • Loading branch information
tassoevan committed Dec 20, 2022
1 parent a567697 commit f57ef6f
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 6 deletions.
11 changes: 8 additions & 3 deletions apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx
Expand Up @@ -23,16 +23,21 @@ type ThreadProps = {
};

const Thread = ({ tmid }: ThreadProps): ReactElement => {
const mainMessageQueryResult = useThreadMainMessageQuery(tmid);
const goToThreadList = useGoToThreadList();
const closeTabBar = useTabBarClose();

const mainMessageQueryResult = useThreadMainMessageQuery(tmid, {
onDelete: () => {
closeTabBar();
},
});

const room = useRoom();
const subscription = useRoomSubscription();

const t = useTranslation();
const dispatchToastMessage = useToastMessageDispatch();

const closeTabBar = useTabBarClose();
const goToThreadList = useGoToThreadList();
const canExpand = useLayoutContextualBarExpanded();
const [expanded, setExpanded] = useLocalStorage('expand-threads', false);

Expand Down
@@ -1,23 +1,116 @@
import { isThreadMainMessage } from '@rocket.chat/core-typings';
import type { IMessage, IThreadMainMessage } from '@rocket.chat/core-typings';
import { useStream } from '@rocket.chat/ui-contexts';
import type { UseQueryResult } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import { useQueryClient, useQuery } from '@tanstack/react-query';
import { useCallback, useEffect, useRef } from 'react';

import type { FieldExpression, Query } from '../../../../../lib/minimongo';
import { createFilterFromQuery } from '../../../../../lib/minimongo';
import { useRoom } from '../../../contexts/RoomContext';
import { useGetMessageByID } from './useGetMessageByID';

export const useThreadMainMessageQuery = (tmid: IMessage['_id']): UseQueryResult<IThreadMainMessage, Error> => {
type RoomMessagesRidEvent = IMessage;

type NotifyRoomRidDeleteMessageEvent = { _id: IMessage['_id'] };

type NotifyRoomRidDeleteMessageBulkEvent = {
rid: IMessage['rid'];
excludePinned: boolean;
ignoreDiscussion: boolean;
ts: FieldExpression<Date>;
users: string[];
};

const createDeleteCriteria = (params: NotifyRoomRidDeleteMessageBulkEvent): ((message: IMessage) => boolean) => {
const query: Query<IMessage> = { ts: params.ts };

if (params.excludePinned) {
query.pinned = { $ne: true };
}

if (params.ignoreDiscussion) {
query.drid = { $exists: false };
}
if (params.users?.length) {
query['u.username'] = { $in: params.users };
}

return createFilterFromQuery<IMessage>(query);
};

const useSubscribeToMessage = () => {
const subscribeToRoomMessages = useStream('room-messages');
const subscribeToNotifyRoom = useStream('notify-room');

return useCallback(
(message: IMessage, { onMutate, onDelete }: { onMutate?: (message: IMessage) => void; onDelete?: () => void }) => {
const unsubscribeFromRoomMessages = subscribeToRoomMessages(message.rid, (event: RoomMessagesRidEvent) => {
if (message._id === event._id) onMutate?.(event);
});

const unsubscribeFromDeleteMessage = subscribeToNotifyRoom(
`${message.rid}/deleteMessage`,
(event: NotifyRoomRidDeleteMessageEvent) => {
if (message._id === event._id) onDelete?.();
},
);

const unsubscribeFromDeleteMessageBulk = subscribeToNotifyRoom(
`${message.rid}/deleteMessageBulk`,
(params: NotifyRoomRidDeleteMessageBulkEvent) => {
const matchDeleteCriteria = createDeleteCriteria(params);
if (matchDeleteCriteria(message)) onDelete?.();
},
);

return () => {
unsubscribeFromRoomMessages();
unsubscribeFromDeleteMessage();
unsubscribeFromDeleteMessageBulk();
};
},
[subscribeToNotifyRoom, subscribeToRoomMessages],
);
};

export const useThreadMainMessageQuery = (
tmid: IMessage['_id'],
{ onDelete }: { onDelete?: () => void } = {},
): UseQueryResult<IThreadMainMessage, Error> => {
const room = useRoom();

const getMessage = useGetMessageByID();
const subscribeToMessage = useSubscribeToMessage();

return useQuery(['rooms', room._id, 'threads', tmid, 'main-message'] as const, async () => {
const queryClient = useQueryClient();
const unsubscribeRef = useRef<(() => void) | undefined>();

useEffect(() => {
return () => {
unsubscribeRef.current?.();
};
}, []);

return useQuery(['rooms', room._id, 'threads', tmid, 'main-message'] as const, async ({ queryKey }) => {
const mainMessage = await getMessage(tmid);

if (!mainMessage && !isThreadMainMessage(mainMessage)) {
throw new Error('Invalid main message');
}

unsubscribeRef.current?.();

unsubscribeRef.current = subscribeToMessage(mainMessage, {
onMutate: () => {
queryClient.invalidateQueries(queryKey, { exact: true });
},
onDelete: () => {
onDelete?.();
queryClient.invalidateQueries(queryKey, { exact: true });
},
});

return mainMessage;
});
};

0 comments on commit f57ef6f

Please sign in to comment.