import React from 'react'; import PropTypes from 'prop-types'; import './Message.scss'; import Linkify from 'linkifyjs/react'; import ReactMarkdown from 'react-markdown'; import gfm from 'remark-gfm'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { coy } from 'react-syntax-highlighter/dist/esm/styles/prism'; import parse from 'html-react-parser'; import twemoji from 'twemoji'; import { getUsername } from '../../../util/matrixUtil'; import Text from '../../atoms/text/Text'; import RawIcon from '../../atoms/system-icons/RawIcon'; import Avatar from '../../atoms/avatar/Avatar'; import Tooltip from '../../atoms/tooltip/Tooltip'; import ReplyArrowIC from '../../../../public/res/ic/outlined/reply-arrow.svg'; const components = { code({ // eslint-disable-next-line react/prop-types inline, className, children, }) { const match = /language-(\w+)/.exec(className || ''); return !inline && match ? ( {String(children).replace(/\n$/, '')} ) : ( {String(children)} ); }, }; function linkifyContent(content) { return {content}; } function genMarkdown(content) { return {content}; } function PlaceholderMessage() { return (
); } function MessageHeader({ userId, name, color, time, }) { return (
{name}
{time}
); } MessageHeader.propTypes = { userId: PropTypes.string.isRequired, name: PropTypes.string.isRequired, color: PropTypes.string.isRequired, time: PropTypes.string.isRequired, }; function MessageReply({ userId, name, color, content, }) { return (
{name} <>{` ${content}`}
); } MessageReply.propTypes = { userId: PropTypes.string.isRequired, name: PropTypes.string.isRequired, color: PropTypes.string.isRequired, content: PropTypes.string.isRequired, }; function MessageContent({ content, isMarkdown, isEdited }) { return (
{ isMarkdown ? genMarkdown(content) : linkifyContent(content) }
{ isEdited && (edited)}
); } MessageContent.defaultProps = { isMarkdown: false, isEdited: false, }; MessageContent.propTypes = { content: PropTypes.node.isRequired, isMarkdown: PropTypes.bool, isEdited: PropTypes.bool, }; function MessageReactionGroup({ children }) { return (
{ children }
); } MessageReactionGroup.propTypes = { children: PropTypes.node.isRequired, }; function genReactionMsg(userIds, reaction) { let msg = ''; userIds.forEach((userId, index) => { if (index === 0) msg += getUsername(userId); else if (index === userIds.length - 1) msg += ` and ${getUsername(userId)}`; else msg += `, ${getUsername(userId)}`; }); return ( <> {`${msg} reacted with`} {parse(twemoji.parse(reaction))} ); } function MessageReaction({ reaction, users, isActive, onClick, }) { return ( {genReactionMsg(users, reaction)}} > ); } MessageReaction.propTypes = { reaction: PropTypes.node.isRequired, users: PropTypes.arrayOf(PropTypes.string).isRequired, isActive: PropTypes.bool.isRequired, onClick: PropTypes.func.isRequired, }; function Message({ avatar, header, reply, content, reactions, }) { const msgClass = header === null ? ' message--content-only' : ' message--full'; return (
{avatar !== null && avatar}
{header !== null && header} {reply !== null && reply} {content} {reactions !== null && reactions}
); } Message.defaultProps = { avatar: null, header: null, reply: null, reactions: null, }; Message.propTypes = { avatar: PropTypes.node, header: PropTypes.node, reply: PropTypes.node, content: PropTypes.node.isRequired, reactions: PropTypes.node, }; export { Message, MessageHeader, MessageReply, MessageContent, MessageReactionGroup, MessageReaction, PlaceholderMessage, };