Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,41 +1,21 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { isDirectMessageRoom, isMultipleDirectMessageRoom, isOmnichannelRoom, isVideoConfMessage } from '@rocket.chat/core-typings';
import { isOmnichannelRoom } from '@rocket.chat/core-typings';
import { SidebarV2Action, SidebarV2Actions, SidebarV2ItemBadge, SidebarV2ItemIcon } from '@rocket.chat/fuselage';
import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts';
import { useLayout } from '@rocket.chat/ui-contexts';
import type { TFunction } from 'i18next';
import type { AllHTMLAttributes, ComponentType, ReactElement, ReactNode } from 'react';
import { memo, useMemo } from 'react';

import { normalizeSidebarMessage } from './normalizeSidebarMessage';
import { RoomIcon } from '../../components/RoomIcon';
import { roomCoordinator } from '../../lib/rooms/roomCoordinator';
import { isIOsDevice } from '../../lib/utils/isIOsDevice';
import { useOmnichannelPriorities } from '../../omnichannel/hooks/useOmnichannelPriorities';
import { getNavigationMessagePreview } from '../../views/navigation/lib/getNavigationMessagePreview';
import RoomMenu from '../RoomMenu';
import { OmnichannelBadges } from '../badges/OmnichannelBadges';
import type { useAvatarTemplate } from '../hooks/useAvatarTemplate';
import { useUnreadDisplay } from '../hooks/useUnreadDisplay';

export const getMessage = (room: SubscriptionWithRoom, lastMessage: IMessage | undefined, t: TFunction): string | undefined => {
if (!lastMessage) {
return t('No_messages_yet');
}
if (isVideoConfMessage(lastMessage)) {
return t('Call_started');
}
if (!lastMessage.u) {
return normalizeSidebarMessage(lastMessage, t);
}
if (lastMessage.u?.username === room.u?.username) {
return `${t('You')}: ${normalizeSidebarMessage(lastMessage, t)}`;
}
if (isDirectMessageRoom(room) && !isMultipleDirectMessageRoom(room)) {
return normalizeSidebarMessage(lastMessage, t);
}
return `${lastMessage.u.name || lastMessage.u.username}: ${normalizeSidebarMessage(lastMessage, t)}`;
};

type RoomListRowProps = {
extended: boolean;
t: TFunction;
Expand Down Expand Up @@ -118,7 +98,7 @@ const SidebarItemTemplateWithData = ({
const isQueued = isOmnichannelRoom(room) && room.status === 'queued';
const { enabled: isPriorityEnabled } = useOmnichannelPriorities();

const message = extended && getMessage(room, lastMessage, t);
const message = extended && getNavigationMessagePreview(room, lastMessage, t);
const subtitle = message ? <span className='message-body--unstyled' dangerouslySetInnerHTML={{ __html: message }} /> : null;

const badges = (
Expand Down
33 changes: 0 additions & 33 deletions apps/meteor/client/sidepanel/SidePanelRouter.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const useRoomsListContext = () => {
const contextValue = useContext(RoomsNavigationContext);

if (!contextValue) {
throw new Error('useRoomsListValue must be used within a RoomsNavigationContext');
throw new Error('useRoomsListContext must be used within a RoomsNavigationContext');
}

return contextValue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { isDirectMessageRoom, isMultipleDirectMessageRoom, isVideoConfMessage } from '@rocket.chat/core-typings';
import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts';
import type { TFunction } from 'i18next';

import { normalizeNavigationMessage } from './normalizeNavigationMessage';

export const getNavigationMessagePreview = (
room: SubscriptionWithRoom,
lastMessage: IMessage | undefined,
t: TFunction,
): string | undefined => {
if (!lastMessage) {
return t('No_messages_yet');
}
if (isVideoConfMessage(lastMessage)) {
return t('Call_started');
}
if (!lastMessage.u) {
return normalizeNavigationMessage(lastMessage, t);
}
if (lastMessage.u?.username === room.u?.username) {
return `${t('You')}: ${normalizeNavigationMessage(lastMessage, t)}`;
}
if (isDirectMessageRoom(room) && !isMultipleDirectMessageRoom(room)) {
return normalizeNavigationMessage(lastMessage, t);
}
return `${lastMessage.u.name || lastMessage.u.username}: ${normalizeNavigationMessage(lastMessage, t)}`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { escapeHTML } from '@rocket.chat/string-helpers';
import emojione from 'emojione';
import type { TFunction } from 'i18next';

import { filterMarkdown } from '../../../app/markdown/lib/markdown';
import { filterMarkdown } from '../../../../app/markdown/lib/markdown';

export const normalizeSidebarMessage = (message: IMessage, t: TFunction): string | undefined => {
export const normalizeNavigationMessage = (message: IMessage, t: TFunction): string | undefined => {
if (message.msg) {
return escapeHTML(filterMarkdown(emojione.shortnameToUnicode(message.msg)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { memo, useId, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { Virtuoso } from 'react-virtuoso';

import { VirtualizedScrollbars } from '../components/CustomScrollbars';
import GenericNoResults from '../components/GenericNoResults';
import { useOpenedRoom, useSecondLevelOpenedRoom } from '../lib/RoomManager';
import { usePreventDefault } from '../sidebarv2/hooks/usePreventDefault';
import RoomSidepanelListWrapper from '../views/room/Sidepanel/RoomSidepanelListWrapper';
import RoomSidepanelItem from '../views/room/Sidepanel/SidepanelItem';
import { VirtualizedScrollbars } from '../../../components/CustomScrollbars';
import GenericNoResults from '../../../components/GenericNoResults';
import { useOpenedRoom, useSecondLevelOpenedRoom } from '../../../lib/RoomManager';
import { usePreventDefault } from '../../../sidebarv2/hooks/usePreventDefault';
import RoomSidepanelListWrapper from '../../room/Sidepanel/RoomSidepanelListWrapper';
import RoomSidepanelItem from '../../room/Sidepanel/SidepanelItem';

type SidePanelProps = {
headerTitle: TranslationKey;
Expand Down Expand Up @@ -43,7 +43,7 @@ const SidePanel = ({ headerTitle, onlyUnreads, toggleOnlyUnreads, rooms }: SideP
{rooms && rooms.length === 0 && <GenericNoResults />}
<VirtualizedScrollbars>
<Virtuoso
totalCount={30}
totalCount={rooms.length}
data={rooms}
components={{ Item: SidepanelListItem, List: RoomSidepanelListWrapper }}
itemContent={(_, data) => <RoomSidepanelItem openedRoom={secondLevelOpenedRoom} room={data} />}
Expand Down
28 changes: 28 additions & 0 deletions apps/meteor/client/views/navigation/sidepanel/SidePanelRouter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import SidePanelAll from './tabs/SidePanelAll';
import { SIDE_PANEL_GROUPS, useSidePanelFilter } from '../contexts/RoomsNavigationContext';

const SidePanelRouter = () => {
const [currentTab] = useSidePanelFilter();

// TODO: figure out if we need this switch
switch (currentTab) {
case SIDE_PANEL_GROUPS.ALL:
return <SidePanelAll currentTab={currentTab} />;
// case SIDE_PANEL_GROUPS.FAVORITES:
// return <SidePanelFavorites currentTab={currentTab} />;
// case SIDE_PANEL_GROUPS.MENTIONS:
// return null; // TODO implement tab
// case SIDE_PANEL_GROUPS.DISCUSSIONS:
// return null; // TODO implement tab
// case SIDE_PANEL_GROUPS.IN_PROGRESS:
// return null; // TODO implement tab
// case SIDE_PANEL_GROUPS.QUEUE:
// return null; // TODO implement tab
// case SIDE_PANEL_GROUPS.ON_HOLD:
// return null; // TODO implement tab
// default:
// return null;
}
};

export default SidePanelRouter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { SubscriptionWithRoom, TranslationKey } from '@rocket.chat/ui-contexts';

import type { SidePanelFiltersKeys } from '../../contexts/RoomsNavigationContext';
import { useSidePanelRoomsListTab, useUnreadOnlyToggle } from '../../contexts/RoomsNavigationContext';
import SidePanel from '../SidePanel';

const SidePanelAll = ({ currentTab }: { currentTab: SidePanelFiltersKeys }) => {
const rooms = useSidePanelRoomsListTab(currentTab);
const [unreadOnly, toggleOnlyUnreads] = useUnreadOnlyToggle();

return (
<SidePanel
headerTitle={currentTab as TranslationKey}
onlyUnreads={unreadOnly}
toggleOnlyUnreads={toggleOnlyUnreads}
rooms={rooms as SubscriptionWithRoom[]}
/>
);
};

export default SidePanelAll;
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import {
IconButton,
SidebarV2Item,
SidebarV2ItemAvatarWrapper,
SidebarV2ItemCol,
SidebarV2ItemContent,
SidebarV2ItemMenu,
SidebarV2ItemRow,
SidebarV2ItemTimestamp,
SidebarV2ItemTitle,
// Tag,
} from '@rocket.chat/fuselage';
import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts';
import { memo } from 'react';
import { memo, useState } from 'react';

import { goToRoomById } from '../../../../lib/utils/goToRoomById';
import { useTemplateByViewMode } from '../../../../sidebarv2/hooks/useTemplateByViewMode';
import SidePanelParentRoom from './SidePanelParentRoom';
import { useShortTimeAgo } from '../../../../hooks/useTimeAgo';
// import { useTemplateByViewMode } from '../../../../sidebarv2/hooks/useTemplateByViewMode';
import { useItemData } from '../hooks/useItemData';

type RoomSidepanelItemProps = {
Expand All @@ -12,12 +25,48 @@ type RoomSidepanelItemProps = {
viewMode?: 'extended' | 'medium' | 'condensed';
};

const RoomSidepanelItem = ({ room, openedRoom, viewMode }: RoomSidepanelItemProps) => {
const SidepanelItem = useTemplateByViewMode();
const RoomSidepanelItem = ({ room, openedRoom }: RoomSidepanelItemProps) => {
// const SidepanelItem = useTemplateByViewMode();

const itemData = useItemData(room, { viewMode, openedRoom });
const { href, selected, avatar, unread, icon, title, time, badges, menu, subtitle, ...props } = useItemData(room, {
viewMode: 'condensed',
openedRoom,
});

return <SidepanelItem onClick={goToRoomById} {...itemData} />;
const formatDate = useShortTimeAgo();
const [menuVisibility, setMenuVisibility] = useState(!!window.DISABLE_ANIMATION);

const handleFocus = () => setMenuVisibility(true);
const handlePointerEnter = () => setMenuVisibility(true);

const parentRoomId = Boolean(room.prid || (room.teamId && !room.teamMain));

return (
<SidebarV2Item {...props} href={href} selected={selected} onFocus={handleFocus} onPointerEnter={handlePointerEnter}>
<SidebarV2ItemCol>
{parentRoomId && (
<SidebarV2ItemRow>
<SidePanelParentRoom room={room} />
</SidebarV2ItemRow>
)}
<SidebarV2ItemRow>
{avatar && <SidebarV2ItemAvatarWrapper>{avatar}</SidebarV2ItemAvatarWrapper>}
{icon && icon}
<SidebarV2ItemTitle unread={unread}>{title}</SidebarV2ItemTitle>
{time && <SidebarV2ItemTimestamp>{formatDate(time)}</SidebarV2ItemTimestamp>}
</SidebarV2ItemRow>
<SidebarV2ItemRow>
<SidebarV2ItemContent unread={unread}>{subtitle}</SidebarV2ItemContent>
{badges && badges}
{menu && (
<SidebarV2ItemMenu>
{menuVisibility ? menu : <IconButton tabIndex={-1} aria-hidden mini rcx-sidebar-v2-item__menu icon='kebab' />}
</SidebarV2ItemMenu>
)}
</SidebarV2ItemRow>
</SidebarV2ItemCol>
</SidebarV2Item>
);
};

export default memo(RoomSidepanelItem);
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { isPrivateRoom } from '@rocket.chat/core-typings';
import { useUserSubscription } from '@rocket.chat/ui-contexts';

import SidePanelTag from './SidePanelTag';
import SidePanelTagIcon from './SidePanelTagIcon';
import { roomCoordinator } from '../../../../lib/rooms/roomCoordinator';

const SidePanelParentDiscussion = ({ prid }: { prid: string }) => {
const subscription = useUserSubscription(prid);

if (!subscription) {
throw new Error('No subscription was found');
}

const icon = isPrivateRoom(subscription) ? 'hashtag-lock' : 'hashtag';
const roomName = roomCoordinator.getRoomName(subscription?.t, subscription);
const handleRedirect = () => roomCoordinator.openRouteLink(subscription.t, { ...subscription });

return (
<SidePanelTag
onKeyDown={(e) => (e.code === 'Space' || e.code === 'Enter') && handleRedirect()}
onClick={(e) => {
e.preventDefault();
handleRedirect();
}}
>
{icon && <SidePanelTagIcon icon={{ name: icon }} />}
{roomName}
</SidePanelTag>
);
};

export default SidePanelParentDiscussion;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts';

import SidePanelParentDiscussion from './SidePanelParentDiscussion';
import SidePanelParentTeam from './SidePanelParentTeam';

const SidePanelParentRoom = ({ room }: { room: SubscriptionWithRoom }) => {
if (room.prid) {
return <SidePanelParentDiscussion prid={room.prid} />;
}

return room.teamId && !room.teamMain && <SidePanelParentTeam room={room} />;
};

export default SidePanelParentRoom;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts';

import SidePanelTag from './SidePanelTag';
import SidePanelTagIcon from './SidePanelTagIcon';
import { useParentTeamData } from './useParentTeamData';

const SidePanelParentTeam = ({ room }: { room: SubscriptionWithRoom }) => {
const { redirectToMainRoom, teamName, shouldDisplayTeam, teamInfoError, isTeamPublic } = useParentTeamData(room);

if (teamInfoError || !shouldDisplayTeam) {
return null;
}

return (
<SidePanelTag
onKeyDown={(e) => (e.code === 'Space' || e.code === 'Enter') && redirectToMainRoom()}
onClick={(e) => {
e.preventDefault();
redirectToMainRoom();
}}
>
<SidePanelTagIcon icon={{ name: isTeamPublic ? 'team' : 'team-lock' }} />
{teamName}
</SidePanelTag>
);
};

export default SidePanelParentTeam;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Tag } from '@rocket.chat/fuselage';
import type { ComponentProps } from 'react';

const SidePanelTag = (props: ComponentProps<typeof Tag>) => <Tag role='button' tabIndex={0} {...props} />;

export default SidePanelTag;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Box, Icon } from '@rocket.chat/fuselage';
import type { ComponentProps, ReactElement } from 'react';
import { isValidElement } from 'react';

const SidePanelTagIcon = ({ icon }: { icon: ReactElement | Pick<ComponentProps<typeof Icon>, 'name' | 'color'> | null }) => {
if (isValidElement(icon)) {
return <Box>{icon}</Box>;
}

return icon && typeof icon === 'object' && 'name' in icon ? <Icon size='x12' mie={4} {...icon} /> : null;
};

export default SidePanelTagIcon;
Loading
Loading