Skip to content

Commit

Permalink
[FIX] Opening a new DM from user card (#24623)
Browse files Browse the repository at this point in the history
* Change `useRoomIcon` signature

* Fix `IRoom[t]` and `ISubscription[t]`

* Ensure `IRoom['uids']` is not mandatory

* Fix some typings
  • Loading branch information
tassoevan authored Mar 10, 2022
1 parent d3b1b16 commit c04d544
Show file tree
Hide file tree
Showing 21 changed files with 201 additions and 106 deletions.
2 changes: 1 addition & 1 deletion client/hooks/usePresence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Presence = 'online' | 'offline' | 'busy' | 'away' | 'loading';
* @returns UserPresence
* @public
*/
export const usePresence = (uid: string): UserPresence | undefined => {
export const usePresence = (uid: string | undefined): UserPresence | undefined => {
const subscription = useMemo(
() => ({
getCurrentValue: (): UserPresence | undefined => (uid ? Presence.store.get(uid) : undefined),
Expand Down
23 changes: 17 additions & 6 deletions client/hooks/useRoomIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { ReactNode } from 'react';
import { Icon } from '@rocket.chat/fuselage';
import React, { ComponentProps, ReactElement } from 'react';

import { IRoom, isDirectMessageRoom } from '../../definition/IRoom';
import { IRoom } from '../../definition/IRoom';
import { ReactiveUserStatus } from '../components/UserStatus';

export const colors = {
Expand All @@ -10,7 +11,9 @@ export const colors = {
offline: 'neutral-600',
};

export const useRoomIcon = (room: IRoom): ReactNode | { name: string; color?: string } | null => {
export const useRoomIcon = (
room: Pick<IRoom, 't' | 'prid' | 'teamMain' | 'uids' | 'u'>,
): ReactElement | ComponentProps<typeof Icon> | null => {
if (room.prid) {
return { name: 'baloons' };
}
Expand All @@ -19,13 +22,21 @@ export const useRoomIcon = (room: IRoom): ReactNode | { name: string; color?: st
return { name: room.t === 'p' ? 'team-lock' : 'team' };
}

if (isDirectMessageRoom(room)) {
if (room.t === 'd') {
if (room.uids && room.uids.length > 2) {
return { name: 'balloon' };
}
if (room.u && room.uids && room.uids.length > 0) {
return <ReactiveUserStatus uid={room.uids.find((uid) => uid !== room.u._id) || room.u._id} />;

if (room.uids && room.uids.length > 0) {
const uid = room.uids.find((uid) => uid !== room?.u?._id) || room?.u?._id;

if (!uid) {
return null;
}

return <ReactiveUserStatus uid={uid} />;
}

return { name: 'at' };
}

Expand Down
8 changes: 5 additions & 3 deletions client/lib/RoomManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,12 @@ export const useHandleRoom = <T extends IRoom>(rid: IRoom['_id']): AsyncState<T>
const room = uid ? subscription || _room : _room;

useEffect(() => {
if (room) {
update();
resolve(room);
if (!room) {
return;
}

update();
resolve(room);
}, [resolve, update, room]);

return state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const VoipInfo = ({ room, onClickClose /* , onClickReport, onClickCall */
const phoneNumber = Array.isArray(v?.phone) ? v?.phone[0]?.phoneNumber : v?.phone;
const shouldShowWrapup = useMemo(() => lastMessage?.t === 'voip-call-wrapup' && lastMessage?.msg, [lastMessage]);
const shouldShowTags = useMemo(() => tags && tags.length > 0, [tags]);
const _name = name || fname;

return (
<>
Expand All @@ -48,12 +49,12 @@ export const VoipInfo = ({ room, onClickClose /* , onClickReport, onClickCall */
</Box>
</InfoPanel.Field>
{servedBy && <AgentField isSmall agent={servedBy} />}
{v && (name || fname) && (
{v && _name && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Contact')}</InfoPanel.Label>
<Box display='flex'>
<UserAvatar size='x28' username={name || fname} />
<UserCard.Username mis='x8' title={name || fname} name={name || fname} status={<UserStatus status={v?.status} />} />
<UserAvatar size='x28' username={_name} />
<UserCard.Username mis='x8' title={_name} name={_name} status={<UserStatus status={v?.status} />} />
</Box>
</InfoPanel.Field>
)}
Expand Down
15 changes: 0 additions & 15 deletions client/views/room/Header/DirectRoomHeader.js

This file was deleted.

32 changes: 32 additions & 0 deletions client/views/room/Header/DirectRoomHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { ReactElement } from 'react';

import { IRoom } from '../../../../definition/IRoom';
import { useUserId } from '../../../contexts/UserContext';
import { usePresence } from '../../../hooks/usePresence';
import RoomHeader from './RoomHeader';

type DirectRoomHeaderProps = {
room: IRoom;
slots: {
start?: unknown;
preContent?: unknown;
insideContent?: unknown;
posContent?: unknown;
end?: unknown;
toolbox?: {
pre?: unknown;
content?: unknown;
pos?: unknown;
};
};
};

const DirectRoomHeader = ({ room, slots }: DirectRoomHeaderProps): ReactElement => {
const userId = useUserId();
const directUserId = room.uids?.filter((uid) => uid !== userId).shift();
const directUserData = usePresence(directUserId);

return <RoomHeader slots={slots} room={room} topic={directUserData?.statusText} />;
};

export default DirectRoomHeader;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { memo, useMemo } from 'react';
import React, { memo, ReactElement, useMemo } from 'react';

import { IRoom } from '../../../../definition/IRoom';
import BurgerMenu from '../../../components/BurgerMenu';
import TemplateHeader from '../../../components/Header';
import { useLayout } from '../../../contexts/LayoutContext';
Expand All @@ -8,7 +9,11 @@ import OmnichannelRoomHeader from './Omnichannel/OmnichannelRoomHeader';
import VoipRoomHeader from './Omnichannel/VoipRoomHeader';
import RoomHeader from './RoomHeader';

const Header = ({ room }) => {
type HeaderProps = {
room: IRoom;
};

const Header = ({ room }: HeaderProps): ReactElement | null => {
const { isMobile, isEmbedded, showTopNavbarEmbeddedLayout } = useLayout();

const slots = useMemo(
Expand All @@ -26,7 +31,7 @@ const Header = ({ room }) => {
return null;
}

if (room.t === 'd' && room.uids?.length < 3) {
if (room.t === 'd' && (room.uids?.length ?? 0) < 3) {
return <DirectRoomHeader slots={slots} room={room} />;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import React from 'react';
import React, { ReactElement } from 'react';

import { isOmnichannelRoom } from '../../../../definition/IRoom';
import { IRoom, isOmnichannelRoom } from '../../../../definition/IRoom';
import Header from '../../../components/Header';
import { OmnichannelRoomIcon } from '../../../components/RoomIcon/OmnichannelRoomIcon';
import { useRoomIcon } from '../../../hooks/useRoomIcon';

const HeaderIconWithRoom = ({ room }) => {
type HeaderIconWithRoomProps = {
room: IRoom;
};

const HeaderIconWithRoom = ({ room }: HeaderIconWithRoomProps): ReactElement => {
const icon = useRoomIcon(room);
if (isOmnichannelRoom(room)) {
return <OmnichannelRoomIcon room={room} size='x20' placement='default' />;
}

return <Header.Icon icon={icon} />;
};
export default HeaderIconWithRoom;
19 changes: 17 additions & 2 deletions client/views/room/Header/Omnichannel/OmnichannelRoomHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,27 @@ import { useCurrentRoute } from '../../../../contexts/RouterContext';
import { useOmnichannelRoom } from '../../contexts/RoomContext';
import { ToolboxActionConfig } from '../../lib/Toolbox';
import { ToolboxContext, useToolboxContext } from '../../lib/Toolbox/ToolboxContext';
import RoomHeader, { RoomHeaderProps } from '../RoomHeader';
import RoomHeader from '../RoomHeader';
import { BackButton } from './BackButton';
import QuickActions from './QuickActions';
import { useQuickActions } from './QuickActions/hooks/useQuickActions';

const OmnichannelRoomHeader: FC<RoomHeaderProps> = ({ slots: parentSlot }) => {
type OmnichannelRoomHeaderProps = {
slots: {
start?: unknown;
preContent?: unknown;
insideContent?: unknown;
posContent?: unknown;
end?: unknown;
toolbox?: {
pre?: unknown;
content?: unknown;
pos?: unknown;
};
};
};

const OmnichannelRoomHeader: FC<OmnichannelRoomHeaderProps> = ({ slots: parentSlot }) => {
const [name] = useCurrentRoute();
const { isMobile } = useLayout();
const room = useOmnichannelRoom();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import React from 'react';
import React, { ReactElement } from 'react';

import { IRoom } from '../../../../definition/IRoom';
import Header from '../../../components/Header';
import { useRoomIcon } from '../../../hooks/useRoomIcon';
import { roomCoordinator } from '../../../lib/rooms/roomCoordinator';

const ParentRoom = ({ room }) => {
const href = roomCoordinator.getRouteLink(room.t, room);
type ParentRoomProps = {
room: Pick<IRoom, '_id' | 't' | 'name' | 'fname' | 'prid' | 'u'>;
};

const ParentRoom = ({ room }: ParentRoomProps): ReactElement => {
const href = roomCoordinator.getRouteLink(room.t, room) || undefined;
const icon = useRoomIcon(room);

return (
Expand Down
17 changes: 0 additions & 17 deletions client/views/room/Header/ParentRoomWithData.js

This file was deleted.

28 changes: 28 additions & 0 deletions client/views/room/Header/ParentRoomWithData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { ReactElement } from 'react';

import { IRoom } from '../../../../definition/IRoom';
import { useUserSubscription } from '../../../contexts/UserContext';
import ParentRoom from './ParentRoom';
import ParentRoomWithEndpointData from './ParentRoomWithEndpointData';

type ParentRoomWithDataProps = {
room: IRoom;
};

const ParentRoomWithData = ({ room }: ParentRoomWithDataProps): ReactElement => {
const { prid } = room;

if (!prid) {
throw new Error('Parent room ID is missing');
}

const subscription = useUserSubscription(prid);

if (subscription) {
return <ParentRoom room={subscription} />;
}

return <ParentRoomWithEndpointData rid={prid} />;
};

export default ParentRoomWithData;
34 changes: 0 additions & 34 deletions client/views/room/Header/ParentRoomWithEndpointData.js

This file was deleted.

27 changes: 27 additions & 0 deletions client/views/room/Header/ParentRoomWithEndpointData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { ReactElement } from 'react';

import { IRoom } from '../../../../definition/IRoom';
import Header from '../../../components/Header';
import { AsyncStatePhase } from '../../../hooks/useAsyncState';
import { useEndpointData } from '../../../hooks/useEndpointData';
import ParentRoom from './ParentRoom';

type ParentRoomWithEndpointDataProps = {
rid: IRoom['_id'];
};

const ParentRoomWithEndpointData = ({ rid }: ParentRoomWithEndpointDataProps): ReactElement | null => {
const { phase, value } = useEndpointData('rooms.info', { roomId: rid });

if (AsyncStatePhase.LOADING === phase) {
return <Header.Tag.Skeleton />;
}

if (AsyncStatePhase.REJECTED === phase || !value?.room) {
return null;
}

return <ParentRoom room={value.room} />;
};

export default ParentRoomWithEndpointData;
Loading

0 comments on commit c04d544

Please sign in to comment.