import { useLayoutEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import useKey from 'react-use/lib/useKey'; import { getOldBottomMessageId, getOldTopMessageId, getSortedMessagesTypesOfSelectedConversation, } from '../../state/selectors/conversations'; import { useSelectedConversationKey } from '../../state/selectors/selectedConversation'; import { MessageDateBreak } from './message/message-item/DateBreak'; import { CommunityInvitation } from './message/message-item/GroupInvitation'; import { GroupUpdateMessage } from './message/message-item/GroupUpdateMessage'; import { Message } from './message/message-item/Message'; import { MessageRequestResponse } from './message/message-item/MessageRequestResponse'; import { CallNotification } from './message/message-item/notification-bubble/CallNotification'; import { IsDetailMessageViewContext } from '../../contexts/isDetailViewContext'; import { SessionLastSeenIndicator } from './SessionLastSeenIndicator'; import { TimerNotification } from './TimerNotification'; import { DataExtractionNotification } from './message/message-item/DataExtractionNotification'; import { InteractionNotification } from './message/message-item/InteractionNotification'; import { assertUnreachable } from '../../types/sqlSharedTypes'; import type { WithMessageId } from '../../session/types/with'; function isNotTextboxEvent(e: KeyboardEvent) { return (e?.target as any)?.type === undefined; } let previousRenderedConvo: string | undefined; export const SessionMessagesList = (props: { scrollAfterLoadMore: ( messageIdToScrollTo: string, type: 'load-more-top' | 'load-more-bottom' ) => void; onPageUpPressed: () => void; onPageDownPressed: () => void; onHomePressed: () => void; onEndPressed: () => void; }) => { const messagesProps = useSelector(getSortedMessagesTypesOfSelectedConversation); const convoKey = useSelectedConversationKey(); const [didScroll, setDidScroll] = useState(false); const oldTopMessageId = useSelector(getOldTopMessageId); const oldBottomMessageId = useSelector(getOldBottomMessageId); useLayoutEffect(() => { const newTopMessageId = messagesProps.length ? messagesProps[messagesProps.length - 1].messageId : undefined; if (oldTopMessageId !== newTopMessageId && oldTopMessageId && newTopMessageId) { props.scrollAfterLoadMore(oldTopMessageId, 'load-more-top'); } const newBottomMessageId = messagesProps.length ? messagesProps[0].messageId : undefined; if (newBottomMessageId !== oldBottomMessageId && oldBottomMessageId && newBottomMessageId) { props.scrollAfterLoadMore(oldBottomMessageId, 'load-more-bottom'); } }); useKey('PageUp', () => { props.onPageUpPressed(); }); useKey('PageDown', () => { props.onPageDownPressed(); }); useKey('Home', e => { if (isNotTextboxEvent(e)) { props.onHomePressed(); } }); useKey('End', e => { if (isNotTextboxEvent(e)) { props.onEndPressed(); } }); if (didScroll && previousRenderedConvo !== convoKey) { setDidScroll(false); previousRenderedConvo = convoKey; } return ( {messagesProps.map(messageProps => { const { messageId } = messageProps; let ComponentToRender: React.FC | undefined; switch (messageProps.message.messageType) { case 'group-notification': { ComponentToRender = GroupUpdateMessage; break; } case 'group-invitation': { ComponentToRender = CommunityInvitation; break; } case 'message-request-response': { ComponentToRender = MessageRequestResponse; break; } case 'data-extraction': { ComponentToRender = DataExtractionNotification; break; } case 'timer-notification': { ComponentToRender = TimerNotification; break; } case 'call-notification': { ComponentToRender = CallNotification; break; } case 'interaction-notification': { ComponentToRender = InteractionNotification; break; } case 'regular-message': { ComponentToRender = Message; break; } default: assertUnreachable( messageProps.message.messageType, `unhandled case with ${messageProps.message.messageType}` ); } const unreadIndicator = messageProps.showUnreadIndicator ? ( ) : null; const dateBreak = messageProps.showDateBreak !== undefined ? ( ) : null; return [ , unreadIndicator, dateBreak, ]; })} ); };