diff --git a/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx b/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx index e9f243de736a6..27c45e2774e87 100644 --- a/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx +++ b/apps/meteor/client/views/room/Sidepanel/RoomSidepanel.tsx @@ -1,7 +1,6 @@ /* eslint-disable react/no-multi-comp */ import { Box, Sidepanel, SidepanelListItem } from '@rocket.chat/fuselage'; -import { useEndpoint, useUserPreference } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { useUserPreference } from '@rocket.chat/ui-contexts'; import React, { memo } from 'react'; import { Virtuoso } from 'react-virtuoso'; @@ -11,6 +10,7 @@ import { useOpenedRoom, useSecondLevelOpenedRoom } from '../../../lib/RoomManage import RoomSidepanelListWrapper from './RoomSidepanelListWrapper'; import RoomSidepanelLoading from './RoomSidepanelLoading'; import RoomSidepanelItem from './SidepanelItem'; +import { useTeamsListChildrenUpdate } from './hooks/useTeamslistChildren'; const RoomSidepanel = () => { const parentRid = useOpenedRoom(); @@ -29,20 +29,12 @@ const RoomSidepanelWithData = ({ parentRid, openedRoom }: { parentRid: string; o const roomInfo = useRoomInfoEndpoint(parentRid); const sidepanelItems = roomInfo.data?.room?.sidepanel?.items || roomInfo.data?.parent?.sidepanel?.items; - const listRoomsAndDiscussions = useEndpoint('GET', '/v1/teams.listChildren'); - const result = useQuery({ - queryKey: ['sidepanel', 'list', parentRid, sidepanelItems], - queryFn: () => - listRoomsAndDiscussions({ - roomId: parentRid, - sort: JSON.stringify({ lm: -1 }), - type: sidepanelItems?.length === 1 ? sidepanelItems[0] : undefined, - }), - enabled: roomInfo.isFetched && !!sidepanelItems, - staleTime: Infinity, - keepPreviousData: true, - }); - + const result = useTeamsListChildrenUpdate( + parentRid, + !roomInfo.data ? null : roomInfo.data.room?.teamId, + // eslint-disable-next-line no-nested-ternary + !sidepanelItems ? null : sidepanelItems?.length === 1 ? sidepanelItems[0] : undefined, + ); if (roomInfo.isSuccess && !roomInfo.data.room?.sidepanel && !roomInfo.data.parent?.sidepanel) { return null; } diff --git a/apps/meteor/client/views/room/Sidepanel/SidepanelItem/RoomSidepanelItem.tsx b/apps/meteor/client/views/room/Sidepanel/SidepanelItem/RoomSidepanelItem.tsx index 67ef4c3c7d5d0..dceb69e1aba31 100644 --- a/apps/meteor/client/views/room/Sidepanel/SidepanelItem/RoomSidepanelItem.tsx +++ b/apps/meteor/client/views/room/Sidepanel/SidepanelItem/RoomSidepanelItem.tsx @@ -1,4 +1,4 @@ -import type { IRoom, Serialized } from '@rocket.chat/core-typings'; +import type { IRoom, ISubscription, Serialized } from '@rocket.chat/core-typings'; import { useUserSubscription } from '@rocket.chat/ui-contexts'; import React, { memo } from 'react'; @@ -17,7 +17,7 @@ const RoomSidepanelItem = ({ room, openedRoom, viewMode }: RoomSidepanelItemProp const SidepanelItem = useTemplateByViewMode(); const subscription = useUserSubscription(room._id); - const itemData = useItemData({ ...room, ...subscription } as any, { viewMode, openedRoom }); // as any because of divergent and overlaping timestamp types in subs and room (type Date vs type string) + const itemData = useItemData({ ...room, ...subscription } as ISubscription & IRoom, { viewMode, openedRoom }); // as any because of divergent and overlaping timestamp types in subs and room (type Date vs type string) if (!subscription) { return ; diff --git a/apps/meteor/client/views/room/Sidepanel/hooks/useItemData.tsx b/apps/meteor/client/views/room/Sidepanel/hooks/useItemData.tsx index f5a89b9df25db..a6de01e220848 100644 --- a/apps/meteor/client/views/room/Sidepanel/hooks/useItemData.tsx +++ b/apps/meteor/client/views/room/Sidepanel/hooks/useItemData.tsx @@ -51,7 +51,7 @@ export const useItemData = ( const itemData = useMemo( () => ({ unread: highlighted, - selected: room._id === openedRoom, + selected: room.rid === openedRoom, t, href: roomCoordinator.getRouteLink(room.t, room) || '', title: roomCoordinator.getRoomName(room.t, room) || '', diff --git a/apps/meteor/client/views/room/Sidepanel/hooks/useTeamslistChildren.ts b/apps/meteor/client/views/room/Sidepanel/hooks/useTeamslistChildren.ts new file mode 100644 index 0000000000000..7c688dab80f88 --- /dev/null +++ b/apps/meteor/client/views/room/Sidepanel/hooks/useTeamslistChildren.ts @@ -0,0 +1,87 @@ +import { useEndpoint } from '@rocket.chat/ui-contexts'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useCallback, useEffect, useMemo } from 'react'; + +import { ChatRoom } from '../../../../../app/models/client'; + +export const useTeamsListChildrenUpdate = ( + parentRid: string, + teamId?: string | null, + sidepanelItems?: 'channels' | 'discussions' | null, +) => { + const queryClient = useQueryClient(); + + const query = useMemo(() => { + const query: Parameters[0] = { + $or: [ + { + _id: parentRid, + }, + { + prid: parentRid, + }, + ], + }; + + if (teamId && query.$or) { + query.$or.push({ + teamId, + }); + } + return query; + }, [parentRid, teamId]); + + const teamList = useEndpoint('GET', '/v1/teams.listChildren'); + + const listRoomsAndDiscussions = useEndpoint('GET', '/v1/teams.listChildren'); + const result = useQuery({ + queryKey: ['sidepanel', 'list', parentRid, sidepanelItems], + queryFn: () => + listRoomsAndDiscussions({ + roomId: parentRid, + sort: JSON.stringify({ lm: -1 }), + type: sidepanelItems || undefined, + }), + enabled: sidepanelItems !== null && teamId !== null, + refetchInterval: 5 * 60 * 1000, + keepPreviousData: true, + }); + + const { mutate: update } = useMutation({ + mutationFn: useCallback(async () => { + queryClient.setQueryData(['sidepanel', 'list', parentRid, sidepanelItems], (data: Awaited> | void) => { + if (!data) { + return; + } + data.data = ChatRoom.find(query, { + sort: { + lm: -1, + }, + }) + .fetch() + .map((item) => JSON.parse(JSON.stringify(item))); + return { ...data }; + }); + }, [parentRid, query, queryClient, sidepanelItems]), + }); + + useEffect(() => { + const liveQueryHandle = ChatRoom.find(query).observe({ + added: () => { + queueMicrotask(update); + }, + changed: () => { + queueMicrotask(update); + }, + removed: () => { + queueMicrotask(update); + }, + }); + + return () => { + liveQueryHandle.stop(); + }; + }, [update, query]); + + return result; +};