UNPKG

@botonic/react

Version:

Build Chatbots using React

116 lines 5.91 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import React, { useContext, useEffect, useRef, useState } from 'react'; import { ROLES } from '../../constants'; import { SENDERS } from '../../index-types'; import { WebchatContext } from '../../webchat/context'; import { BotonicContainerId } from '../constants'; import TypingIndicator from '../typing-indicator'; import { IntroMessage } from './intro-message'; import { ScrollButton } from './scroll-button'; import { MessageContainer, ScrollableMessageList } from './styles'; import { UnreadMessagesBanner } from './unread-messages-banner'; import { useNotifications } from './use-notifications'; const SCROLL_TIMEOUT = 200; const scrollOptionsEnd = { block: 'end', }; const scrollOptionsCenter = { block: 'center', }; export const WebchatMessageList = () => { const { webchatState, resetUnreadMessages, setLastMessageVisible, scrollableMessagesListRef, } = useContext(WebchatContext); const { notificationsEnabled } = useNotifications(); const [firstUnreadMessageId, setFirstUnreadMessageId] = useState(); const lastMessageRef = useRef(null); const typingRef = useRef(null); const unreadMessagesBannerRef = useRef(null); const scrollToTyping = () => { setTimeout(() => { var _a; (_a = typingRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView(scrollOptionsEnd); }, SCROLL_TIMEOUT); }; const scrollToLastMessage = () => { setTimeout(() => { var _a; (_a = lastMessageRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView(scrollOptionsEnd); }, SCROLL_TIMEOUT); }; const scrollToBanner = () => { setTimeout(() => { var _a; (_a = unreadMessagesBannerRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView(scrollOptionsCenter); }, SCROLL_TIMEOUT); }; const handleScrollToBottom = () => { resetUnreadMessages(); if (webchatState.typing) { scrollToTyping(); return; } scrollToLastMessage(); }; const showUnreadMessagesBanner = (messageComponentId) => { return (!webchatState.isInputFocused && firstUnreadMessageId && messageComponentId === firstUnreadMessageId && webchatState.numUnreadMessages > 0); }; useEffect(() => { var _a; const firstUnreadMessage = webchatState.messagesComponents.find(message => message.props.isUnread); setFirstUnreadMessageId((_a = firstUnreadMessage === null || firstUnreadMessage === void 0 ? void 0 : firstUnreadMessage.props) === null || _a === void 0 ? void 0 : _a.id); }, [webchatState.messagesComponents]); useEffect(() => { if (webchatState.messagesComponents.length > 0 && lastMessageRef.current) { const observer = new IntersectionObserver(entries => { entries.forEach(entry => { setLastMessageVisible(entry.isIntersecting); }); }); observer.observe(lastMessageRef.current); } }, [webchatState.messagesComponents]); useEffect(() => { if (!notificationsEnabled) { if (webchatState.typing) { scrollToTyping(); return; } scrollToLastMessage(); } }, [webchatState.typing, webchatState.messagesComponents]); useEffect(() => { if (webchatState.isWebchatOpen && notificationsEnabled) { if (unreadMessagesBannerRef.current) { scrollToBanner(); return; } if (webchatState.typing) { scrollToTyping(); return; } scrollToLastMessage(); } }, [ firstUnreadMessageId, webchatState.isWebchatOpen, webchatState.typing, webchatState.messagesComponents, ]); const showScrollButton = webchatState.numUnreadMessages > 0 && !webchatState.isLastMessageVisible; return (_jsxs(_Fragment, { children: [_jsxs(ScrollableMessageList, Object.assign({ id: BotonicContainerId.ScrollableMessagesList, ref: scrollableMessagesListRef, role: ROLES.MESSAGE_LIST }, { children: [_jsx(IntroMessage, {}), webchatState.messagesComponents.map((messageComponent, index) => { var _a, _b; const messageId = messageComponent.props.id; const sentBySystem = ((_a = messageComponent.props) === null || _a === void 0 ? void 0 : _a.sentBy) === SENDERS.system; // Check if system message is followed by a regular message (user/bot) const nextMessage = webchatState.messagesComponents[index + 1]; const isSystemMessageFollowedByMessage = sentBySystem && nextMessage && ((_b = nextMessage.props) === null || _b === void 0 ? void 0 : _b.sentBy) !== SENDERS.system; return (_jsxs(React.Fragment, { children: [_jsxs(MessageContainer, Object.assign({ role: sentBySystem ? ROLES.SYSTEM_MESSAGE : ROLES.MESSAGE, "$isLastSystemMessage": isSystemMessageFollowedByMessage }, { children: [showUnreadMessagesBanner(messageId) && (_jsx(UnreadMessagesBanner, { unreadMessagesBannerRef: unreadMessagesBannerRef })), messageComponent] })), index === webchatState.messagesComponents.length - 1 && (_jsx("div", { ref: lastMessageRef, style: { content: '', } }))] }, messageId)); }), webchatState.typing && _jsx(TypingIndicator, { ref: typingRef })] })), showScrollButton && _jsx(ScrollButton, { handleClick: handleScrollToBottom })] })); }; //# sourceMappingURL=index.js.map