import classNames from 'classnames'; import { isNil } from 'lodash'; import React, { useCallback } from 'react'; import { contextMenu } from 'react-contexify'; import { createPortal } from 'react-dom'; import { useDispatch, useSelector } from 'react-redux'; import { Avatar, AvatarSize } from '../../avatar/Avatar'; import { openConversationWithMessages } from '../../../state/ducks/conversations'; import { updateUserDetailsModal } from '../../../state/ducks/modalDialog'; import { ContextConversationProvider, useConvoIdFromContext, } from '../../../contexts/ConvoIdContext'; import { useAvatarPath, useConversationUsername, useHasUnread, useIsBlocked, useIsPrivate, useMentionedUs, } from '../../../hooks/useParamSelector'; import { isSearching } from '../../../state/selectors/search'; import { useSelectedConversationKey } from '../../../state/selectors/selectedConversation'; import { MemoConversationListItemContextMenu } from '../../menu/ConversationListItemContextMenu'; import { ConversationListItemHeaderItem } from './HeaderItem'; import { MessageItem } from './MessageItem'; type PropsHousekeeping = { style?: object; }; type Props = { conversationId: string } & PropsHousekeeping; const Portal = ({ children }: { children: any }) => { return createPortal(children, document.querySelector('.inbox.index') as Element); }; const AvatarItem = () => { const conversationId = useConvoIdFromContext(); const userName = useConversationUsername(conversationId); const isPrivate = useIsPrivate(conversationId); const avatarPath = useAvatarPath(conversationId); const dispatch = useDispatch(); function onPrivateAvatarClick() { dispatch( updateUserDetailsModal({ conversationId, userName: userName || '', authorAvatarPath: avatarPath, }) ); } return (
); }; const ConversationListItemInner = (props: Props) => { const { conversationId, style } = props; const key = `conversation-item-${conversationId}`; const hasUnread = useHasUnread(conversationId); let hasUnreadMentionedUs = useMentionedUs(conversationId); let isBlocked = useIsBlocked(conversationId); const isSearch = useSelector(isSearching); const selectedConvo = useSelectedConversationKey(); const isSelectedConvo = conversationId === selectedConvo && !isNil(selectedConvo); if (isSearch) { // force isBlocked and hasUnreadMentionedUs to be false, we just want to display the row without any special style when showing search results hasUnreadMentionedUs = false; isBlocked = false; } const triggerId = `${key}-ctxmenu`; const openConvo = useCallback( (e: React.MouseEvent) => { // mousedown is invoked sooner than onClick, but for both right and left click if (e.button === 0) { void openConversationWithMessages({ conversationKey: conversationId, messageId: null }); } }, [conversationId] ); return (
{ e.stopPropagation(); e.preventDefault(); }} onContextMenu={e => { contextMenu.show({ id: triggerId, event: e, }); }} style={style} className={classNames( 'module-conversation-list-item', hasUnread ? 'module-conversation-list-item--has-unread' : null, hasUnreadMentionedUs ? 'module-conversation-list-item--mentioned-us' : null, isSelectedConvo ? 'module-conversation-list-item--is-selected' : null, isBlocked ? 'module-conversation-list-item--is-blocked' : null )} >
); }; export const ConversationListItem = ConversationListItemInner;