Skip to content

Commit

Permalink
refactor: fix sidepanel ficker
Browse files Browse the repository at this point in the history
  • Loading branch information
juliajforesti committed Aug 21, 2024
1 parent a2a498f commit 99c8af4
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 62 deletions.
76 changes: 39 additions & 37 deletions apps/meteor/client/views/room/RoomOpener.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { RoomType } from '@rocket.chat/core-typings';
import { Box, States, StatesIcon, StatesSubtitle, StatesTitle } from '@rocket.chat/fuselage';
import { useFeaturePreview } from '@rocket.chat/ui-client';
import { FeaturePreview, FeaturePreviewOff, FeaturePreviewOn } from '@rocket.chat/ui-client';
import type { ReactElement } from 'react';
import React, { lazy, Suspense } from 'react';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -31,47 +31,49 @@ const RoomOpener = ({ type, reference }: RoomOpenerProps): ReactElement => {
const { data, error, isSuccess, isError, isLoading } = useOpenRoom({ type, reference });
const { t } = useTranslation();

const isSidepanelFeatureEnabled = useFeaturePreview('sidepanelNavigation');

return (
<Suspense fallback={<RoomSkeleton />}>
{isLoading && <RoomSkeleton />}
{isSuccess && (
<RoomProvider rid={data.rid}>
<Box display='flex' w='full' h='full'>
{!isDirectMessageRoom(type) && isSidepanelFeatureEnabled && <RoomSidePanel rid={data.rid} />}
<Box display='flex' w='full' h='full'>
<FeaturePreview feature='sidepanelNavigation'>
<FeaturePreviewOff>{null}</FeaturePreviewOff>
<FeaturePreviewOn>{!isDirectMessageRoom(type) && <RoomSidePanel />}</FeaturePreviewOn>
</FeaturePreview>

<Suspense fallback={<RoomSkeleton />}>
{isLoading && <RoomSkeleton />}
{isSuccess && (
<RoomProvider rid={data.rid}>
<Room />
</Box>
</RoomProvider>
)}
{isError &&
(() => {
if (error instanceof OldUrlRoomError) {
return <RoomSkeleton />;
}
</RoomProvider>
)}
{isError &&
(() => {
if (error instanceof OldUrlRoomError) {
return <RoomSkeleton />;
}

if (error instanceof RoomNotFoundError) {
return <RoomNotFound />;
}
if (error instanceof RoomNotFoundError) {
return <RoomNotFound />;
}

if (error instanceof NotAuthorizedError) {
return <NotAuthorizedPage />;
}
if (error instanceof NotAuthorizedError) {
return <NotAuthorizedPage />;
}

return (
<RoomLayout
header={<Header />}
body={
<States>
<StatesIcon name='circle-exclamation' variation='danger' />
<StatesTitle>{t('core.Error')}</StatesTitle>
<StatesSubtitle>{getErrorMessage(error)}</StatesSubtitle>
</States>
}
/>
);
})()}
</Suspense>
return (
<RoomLayout
header={<Header />}
body={
<States>
<StatesIcon name='circle-exclamation' variation='danger' />
<StatesTitle>{t('core.Error')}</StatesTitle>
<StatesSubtitle>{getErrorMessage(error)}</StatesSubtitle>
</States>
}
/>
);
})()}
</Suspense>
</Box>
);
};

Expand Down
69 changes: 48 additions & 21 deletions apps/meteor/client/views/room/SidePanel/RoomSidePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* eslint-disable react/no-multi-comp */
import type { IDiscussionMessage, IRoom, ITeam } from '@rocket.chat/core-typings';
import { SidePanel, SidePanelList } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import { useTranslation, useUserId } from '@rocket.chat/ui-contexts';
import React, { memo, useMemo } from 'react';

import GenericError from '../../../components/GenericError';
import { useRecordList } from '../../../hooks/lists/useRecordList';
import { useRoomInfoEndpoint } from '../../../hooks/useRoomInfoEndpoint';
import { useOpenedRoom, useSecondLevelOpenedRoom } from '../../../lib/RoomManager';
import { AsyncStatePhase } from '../../../lib/asyncState';
import { useTeamsChannelList } from '../../teams/contextualBar/channels/hooks/useTeamsChannelList';
import { useDiscussionsList } from '../contextualBar/Discussions/useDiscussionsList';
Expand All @@ -18,68 +20,93 @@ type DataResult = {
team?: ITeam | undefined;
};

const shouldShowDiscussions = (data: DataResult) =>
data?.parent?.sidepanel?.items.includes('discussions') || data?.room?.sidepanel?.items.includes('discussions');
const shouldShowChannels = (data: DataResult) =>
data?.parent?.sidepanel?.items.includes('channels') || data?.room?.sidepanel?.items.includes('channels');
const RoomSidePanel = () => {
const parentRid = useOpenedRoom();
const rid = useSecondLevelOpenedRoom() ?? parentRid;

const RoomSidePanel = ({ rid }: { rid: IRoom['_id'] }) => {
const { data, isSuccess, isError } = useRoomInfoEndpoint(rid);
if (!parentRid || !rid) {
return null;
}
return <RoomSidePanelWithData parentRid={parentRid} openedRoom={rid} />;
};

const shouldShowDiscussions = (data: DataResult) => data?.room?.sidepanel?.items.includes('discussions');
const shouldShowChannels = (data: DataResult) => data?.room?.sidepanel?.items.includes('channels');

const RoomSidePanelWithData = ({ parentRid, openedRoom }: { parentRid: string; openedRoom: string }) => {
const t = useTranslation();
const uid = useUserId();
const { data, isSuccess, isError } = useRoomInfoEndpoint(parentRid);

const dicsussionOptions = useMemo(
() => ({
rid: data?.parent?._id || rid,
rid: parentRid,
}),
[data?.parent?._id, rid],
[parentRid],
);

const channelOptions = useMemo(
() =>
({
teamId: data?.team?._id || '',
...(!data?.room?.teamMain && { roomId: data?.parent?._id }),
teamId: '',
roomId: parentRid,
type: 'all',
text: '',
} as const),
[data?.parent?._id, data?.room?.teamMain, data?.team?._id],
[parentRid],
);

// IMPROVE: only fetch discussions IF parent room has sidepanel.items with discussions
// TODO: get last message from discussion
// TODO: get discussion avatar
// TODO: get discussion unread messages
const { discussionsList } = useDiscussionsList(dicsussionOptions, data?.room?.u._id || '');
const { discussionsList } = useDiscussionsList(dicsussionOptions, uid);
const { phase, error, items: discussions } = useRecordList<IDiscussionMessage>(discussionsList);

// IMPROVE: only fetch channels IF parent room has sidepanel.items with channels
// TODO: get channel avatar
// TODO: get channel unread messages
const { teamsChannelList, reload } = useTeamsChannelList(channelOptions);
const { teamsChannelList } = useTeamsChannelList(channelOptions);
const { phase: channelsPhase, error: channelsError, items: channels } = useRecordList(teamsChannelList);

if (isError || error || channelsError || !isSuccess) {
return (
<SidePanel>
<GenericError buttonAction={reload} buttonTitle={t('Reload')} />
<GenericError />
</SidePanel>
);
}
if (isSuccess && !data.room?.sidepanel && !data.parent?.sidepanel) {
if (isSuccess && !data.room?.sidepanel) {
return null;
}
if (phase === AsyncStatePhase.LOADING || channelsPhase === AsyncStatePhase.LOADING) {
return <RoomSidePanelLoading />;
}

return (
<SidePanel>
<SidePanelList>
<RoomSidePanelItem id={data.parent?._id} name={t('General')} icon={(data.parent || data.room)?.t === 'p' ? 'team-lock' : 'team'} />
<RoomSidePanelItem id={parentRid} name={t('General')} icon={data.room?.t === 'p' ? 'team-lock' : 'team'} openedRoom={openedRoom} />
{shouldShowDiscussions(data) &&
discussions.map((data) => <RoomSidePanelItem key={data.drid} id={data.drid} name={data.msg} icon='baloons' {...data} />)}
discussions.map((discussion) => (
<RoomSidePanelItem
key={discussion.drid}
id={discussion.drid}
name={discussion.msg}
icon='baloons'
openedRoom={openedRoom}
{...discussion}
/>
))}
{shouldShowChannels(data) &&
channels.map((data) => (
<RoomSidePanelItem key={data._id} id={data._id} name={data.name} icon={data.t === 'p' ? 'hashtag-lock' : 'hashtag'} {...data} />
channels.map((channel) => (
<RoomSidePanelItem
key={channel._id}
id={channel._id}
name={channel.name}
icon={channel.t === 'p' ? 'hashtag-lock' : 'hashtag'}
openedRoom={openedRoom}
{...channel}
/>
))}
</SidePanelList>
</SidePanel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import type { IRoom, IDiscussionMessage } from '@rocket.chat/core-typings';
import type { Keys } from '@rocket.chat/icons';
import React, { memo, useCallback } from 'react';

import { useSecondLevelOpenedRoom } from '../../../../lib/RoomManager';
import { goToRoomById } from '../../../../lib/utils/goToRoomById';
import { useTemplateByViewMode } from '../hooks/useTemplateByViewMode';

export type RoomSidePanelItemProps = {
id: string | undefined;
name: string | undefined;
icon: Keys;
openedRoom: string | undefined;
} & (Partial<IRoom> | Partial<IDiscussionMessage>);

const RoomSidePanelItem = (props: RoomSidePanelItemProps) => {
Expand All @@ -18,9 +18,7 @@ const RoomSidePanelItem = (props: RoomSidePanelItemProps) => {
goToRoomById(id);
}, []);

const openedRoom = useSecondLevelOpenedRoom();

return <SidepanelItem openedRoom={openedRoom} onClick={onClick} {...props} />;
return <SidepanelItem onClick={onClick} {...props} />;
};

export default memo(RoomSidePanelItem);

0 comments on commit 99c8af4

Please sign in to comment.