RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/components/message/variants/RoomMessage.tsx

Summary

Maintainability
A
1 hr
Test Coverage
import type { IMessage } from '@rocket.chat/core-typings';
import { Message, MessageLeftContainer, MessageContainer, CheckBox } from '@rocket.chat/fuselage';
import { useToggle } from '@rocket.chat/fuselage-hooks';
import { MessageAvatar } from '@rocket.chat/ui-avatar';
import { useTranslation, useUserId } from '@rocket.chat/ui-contexts';
import type { ComponentProps, ReactElement } from 'react';
import React, { memo } from 'react';

import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction';
import { useIsMessageHighlight } from '../../../views/room/MessageList/contexts/MessageHighlightContext';
import {
    useIsSelecting,
    useToggleSelect,
    useIsSelectedMessage,
    useCountSelected,
} from '../../../views/room/MessageList/contexts/SelectedMessagesContext';
import { useJumpToMessage } from '../../../views/room/MessageList/hooks/useJumpToMessage';
import { useUserCard } from '../../../views/room/contexts/UserCardContext';
import Emoji from '../../Emoji';
import IgnoredContent from '../IgnoredContent';
import MessageHeader from '../MessageHeader';
import MessageToolbarHolder from '../MessageToolbarHolder';
import StatusIndicators from '../StatusIndicators';
import RoomMessageContent from './room/RoomMessageContent';

type RoomMessageProps = {
    message: IMessage & { ignored?: boolean };
    showUserAvatar: boolean;
    sequential: boolean;
    unread: boolean;
    mention: boolean;
    all: boolean;
    context?: MessageActionContext;
    ignoredUser?: boolean;
    searchText?: string;
} & ComponentProps<typeof Message>;

const RoomMessage = ({
    message,
    showUserAvatar,
    sequential,
    all,
    mention,
    unread,
    context,
    ignoredUser,
    searchText,
    ...props
}: RoomMessageProps): ReactElement => {
    const t = useTranslation();
    const uid = useUserId();
    const editing = useIsMessageHighlight(message._id);
    const [displayIgnoredMessage, toggleDisplayIgnoredMessage] = useToggle(false);
    const ignored = (ignoredUser || message.ignored) && !displayIgnoredMessage;
    const { openUserCard, triggerProps } = useUserCard();

    const selecting = useIsSelecting();
    const toggleSelected = useToggleSelect(message._id);
    const selected = useIsSelectedMessage(message._id);

    useCountSelected();

    const messageRef = useJumpToMessage(message._id);

    return (
        <Message
            ref={messageRef}
            id={message._id}
            role='listitem'
            aria-roledescription={sequential ? t('sequential_message') : t('message')}
            tabIndex={0}
            aria-labelledby={`${message._id}-displayName ${message._id}-time ${message._id}-content ${message._id}-read-status`}
            onClick={selecting ? toggleSelected : undefined}
            isSelected={selected}
            isEditing={editing}
            isPending={message.temp}
            sequential={sequential}
            data-qa-editing={editing}
            data-qa-selected={selected}
            data-id={message._id}
            data-mid={message._id}
            data-unread={unread}
            data-sequential={sequential}
            data-own={message.u._id === uid}
            data-qa-type='message'
            aria-busy={message.temp}
            {...props}
        >
            <MessageLeftContainer>
                {!sequential && message.u.username && !selecting && showUserAvatar && (
                    <MessageAvatar
                        emoji={message.emoji ? <Emoji emojiHandle={message.emoji} fillContainer /> : undefined}
                        avatarUrl={message.avatar}
                        username={message.u.username}
                        size='x36'
                        onClick={(e) => openUserCard(e, message.u.username)}
                        style={{ cursor: 'pointer' }}
                        role='button'
                        {...triggerProps}
                    />
                )}
                {selecting && <CheckBox checked={selected} onChange={toggleSelected} />}
                {sequential && <StatusIndicators message={message} />}
            </MessageLeftContainer>
            <MessageContainer>
                {!sequential && <MessageHeader message={message} />}
                {ignored ? (
                    <IgnoredContent onShowMessageIgnored={toggleDisplayIgnoredMessage} />
                ) : (
                    <RoomMessageContent message={message} unread={unread} mention={mention} all={all} searchText={searchText} />
                )}
            </MessageContainer>
            {!message.private && <MessageToolbarHolder message={message} context={context} />}
        </Message>
    );
};

export default memo(RoomMessage);