diff --git a/.changeset/eight-clouds-count.md b/.changeset/eight-clouds-count.md new file mode 100644 index 0000000000000..25ecce7dc886a --- /dev/null +++ b/.changeset/eight-clouds-count.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes intermittent "Channel Not Joined" screen when opening rooms in embedded mode. diff --git a/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx b/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx index 919990af1a985..aaeee3f060cdc 100644 --- a/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx +++ b/apps/meteor/client/views/room/RoomOpenerEmbedded.tsx @@ -1,8 +1,7 @@ -import type { RoomType } from '@rocket.chat/core-typings'; +import type { ISubscription, RoomType } from '@rocket.chat/core-typings'; import { Box, States, StatesIcon, StatesSubtitle, StatesTitle } from '@rocket.chat/fuselage'; import { Header } from '@rocket.chat/ui-client'; -import { useEndpoint, useStream, useUserId } from '@rocket.chat/ui-contexts'; -import { useQuery } from '@tanstack/react-query'; +import { useStream, useUserId } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import { lazy, Suspense, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; @@ -10,15 +9,12 @@ import { useTranslation } from 'react-i18next'; import NotSubscribedRoom from './NotSubscribedRoom'; import RoomSkeleton from './RoomSkeleton'; import { useOpenRoom } from './hooks/useOpenRoom'; -import { LegacyRoomManager } from '../../../app/ui-utils/client'; import { SubscriptionsCachedStore } from '../../cachedStores'; import { getErrorMessage } from '../../lib/errorHandling'; import { NotAuthorizedError } from '../../lib/errors/NotAuthorizedError'; import { NotSubscribedToRoomError } from '../../lib/errors/NotSubscribedToRoomError'; import { OldUrlRoomError } from '../../lib/errors/OldUrlRoomError'; import { RoomNotFoundError } from '../../lib/errors/RoomNotFoundError'; -import { subscriptionsQueryKeys } from '../../lib/queryKeys'; -import { mapSubscriptionFromApi } from '../../lib/utils/mapSubscriptionFromApi'; const RoomProvider = lazy(() => import('./providers/RoomProvider')); const RoomNotFound = lazy(() => import('./RoomNotFound')); @@ -34,47 +30,23 @@ type RoomOpenerProps = { const RoomOpenerEmbedded = ({ type, reference }: RoomOpenerProps): ReactElement => { const { data, error, isSuccess, isError, isLoading } = useOpenRoom({ type, reference }); const uid = useUserId(); - - const getSubscription = useEndpoint('GET', '/v1/subscriptions.getOne'); - const subscribeToNotifyUser = useStream('notify-user'); const rid = data?.rid; - const { data: subscriptionData, refetch } = useQuery({ - queryKey: rid ? subscriptionsQueryKeys.subscription(rid) : [], - queryFn: () => { - if (!rid) { - throw new Error('Room not found'); - } - return getSubscription({ roomId: rid }); - }, - enabled: !!rid, - }); useEffect(() => { - if (!subscriptionData?.subscription) { + if (!uid || !rid) { return; } - SubscriptionsCachedStore.upsertSubscription(mapSubscriptionFromApi(subscriptionData.subscription)); - - // yes this must be done here, this is already called in useOpenRoom, but it skips subscription streams because of the subscriptions list is empty - // now that we inserted the subscription, we can open the room - LegacyRoomManager.open({ typeName: type + reference, rid: subscriptionData.subscription.rid }); - }, [subscriptionData, type, rid, reference]); - - useEffect(() => { - if (!uid) { - return; - } return subscribeToNotifyUser(`${uid}/subscriptions-changed`, (event, sub) => { if (sub.rid !== rid || event === 'removed') { return; } - refetch(); + SubscriptionsCachedStore.upsertSubscription(sub as ISubscription); }); - }, [refetch, rid, subscribeToNotifyUser, uid]); + }, [rid, subscribeToNotifyUser, uid]); const { t } = useTranslation(); diff --git a/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx b/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx index 873ade90377dd..35edbf4e78ee1 100644 --- a/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx +++ b/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx @@ -1,19 +1,75 @@ +import { useEndpoint, useMethod, useRouter, useUserId } from '@rocket.chat/ui-contexts'; +import { useQuery } from '@tanstack/react-query'; import type { ReactElement, ReactNode } from 'react'; -import { useEffect } from 'react'; +import { useEffect, useMemo } from 'react'; import { RoomsCachedStore, SubscriptionsCachedStore } from '../../../cachedStores'; +import { roomsQueryKeys } from '../../../lib/queryKeys'; +import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; +import { mapSubscriptionFromApi } from '../../../lib/utils/mapSubscriptionFromApi'; import PageLoading from '../PageLoading'; import { useMainReady } from '../hooks/useMainReady'; const EmbeddedPreload = ({ children }: { children: ReactNode }): ReactElement => { const ready = useMainReady(); + const router = useRouter(); + const uid = useUserId(); + + const roomParams = useMemo(() => { + const routeName = router.getRouteName(); + if (!routeName) { + return null; + } + + const identifier = roomCoordinator.getRouteNameIdentifier(routeName); + if (!identifier) { + return null; + } + + const directives = roomCoordinator.getRoomDirectives(identifier); + if (!directives?.extractOpenRoomParams) { + return null; + } + + return directives.extractOpenRoomParams(router.getRouteParameters()); + }, [router]); + + const getRoomByTypeAndName = useMethod('getRoomByTypeAndName'); + const getSubscription = useEndpoint('GET', '/v1/subscriptions.getOne'); + + const shouldFetch = !!roomParams && !!uid; + + const { isLoading, isSuccess, isError } = useQuery({ + queryKey: roomParams ? roomsQueryKeys.roomReference(roomParams.reference, roomParams.type, uid ?? undefined) : [], + queryFn: async () => { + if (!roomParams) { + return null; + } + + const roomData = await getRoomByTypeAndName(roomParams.type, roomParams.reference); + if (!roomData?._id) { + return null; + } + + const subResult = await getSubscription({ roomId: roomData._id }); + if (subResult.subscription) { + SubscriptionsCachedStore.upsertSubscription(mapSubscriptionFromApi(subResult.subscription)); + } + + return subResult; + }, + enabled: shouldFetch, + retry: false, + }); useEffect(() => { - SubscriptionsCachedStore.setReady(true); - RoomsCachedStore.setReady(true); - }, [ready]); + if (!shouldFetch || isSuccess || isError) { + SubscriptionsCachedStore.setReady(true); + RoomsCachedStore.setReady(true); + } + }, [shouldFetch, isSuccess, isError]); - if (!ready) { + if (!ready || (shouldFetch && isLoading)) { return ; }