const componentOwnerId = props.componentOwnerId; const readMessage = props.readMessage; const handleReaction = props.handleReaction; const openThread = props.openThread; const setOpenThread = props.setOpenThread; const activeChat = props.activeChat; const curbApi = props.curbApi; const accountId = props.accountId; const incomingMessages = props.incomingMessages; const updatedMessages = props.updatedMessages; const resetImage = props.resetImage; const sendMessage = props.sendMessage; const getIconFromCache = props.getIconFromCache; const isThread = props.isThread; const isReadOnly = props.isReadOnly; const toggleEmojiSelector = props.toggleEmojiSelector; const isEmojiSelectorVisible = props.isEmojiSelectorVisible; const channelMeta = props.channelMeta; const channelUserList = props.channelUserList; const deletedMessages = props.deletedMessages; const setDeletedMessages = props.setDeletedMessages; const ContainerPadding = styled.div` @media (max-width: 1024px) { height: calc(100vh - 160px) !important; padding-left: 0px !important; padding-right: 0px !important; } scrollbar-color: black black; ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-thumb { background-color: black; border-radius: 6px; } ::-webkit-scrollbar-thumb:hover { background-color: black; } * { scrollbar-color: black black; } html::-webkit-scrollbar { width: 12px; } html::-webkit-scrollbar-thumb { background-color: black; border-radius: 6px; } html::-webkit-scrollbar-thumb:hover { background-color: black; } `; const ThreadTitle = styled.div` color: #fff; font-size: 24px; font-style: normal; font-weight: 500; line-height: 120%; `; const ThreadContainer = styled.div` position: relative; padding-bottom: 20px; border-bottom: 2px solid #282933; display: flex; justify-content: space-between; @media (max-width: 1024px) { margin-right: 16px; padding-top: 104px; } `; const CloseSvg = styled.svg` fill: #777583; :hover { fill: #fff; } cursor: pointer; `; const Wrapper = styled.div` @media (max-width: 1024px) { width: 100% !important; } `; const containerPaddingStyle = { display: "flex", flexDirection: "row", paddingTop: "1rem", paddingLeft: "2.5rem", paddingRight: "2.5rem", paddingBottom: "2.5rem", scrollBehavior: "smooth", height: "calc(100vh - 241px)", }; const chatStyle = { height: "", width: "", }; const wrapperStyle = { height: "100%", width: "100%", }; const CloseButtonSvg = ({ onClose }) => ( <CloseSvg onClick={onClose} xmlns="http://www.w3.org/2000/svg" width="24" height="24" className="bi bi-x-circle" viewBox="0 0 16 16" > <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z" /> <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" /> </CloseSvg> ); const ThreadHeader = ({ onClose }) => ( <ThreadContainer> <ThreadTitle>Thread</ThreadTitle> <CloseButtonSvg onClose={onClose} /> </ThreadContainer> ); const loadInitialMessages = () => { if (isThread && openThread.id) { return curbApi.fetchMessages({ chat: activeChat, limit: 20, parentMessageId: openThread.id, }); } return curbApi.fetchMessages({ chat: activeChat, limit: 20 }); }; const loadPrevMessages = (id) => { if (isThread && id) { return curbApi.fetchMessages({ chat: activeChat, beforeId: id, limit: 20, parentMessageId: openThread.id, }); } return curbApi.fetchMessages({ chat: activeChat, beforeId: id, limit: 20 }); }; const setThread = useCallback((message) => { setOpenThread(message); }, []); const isModerator = channelUserList?.some( (user) => user.id === accountId && user.moderator === true ); const isOwner = accountId === channelMeta.createdBy; const deleteMessage = useCallback( (message, setDeleteMessageResponse) => { curbApi.deleteMessage({ message, chat: activeChat, threadId: openThread.id, callback: (err, result) => { if (err) { setDeleteMessageResponse(err); } else { setDeletedMessages((prev) => prev + 1); } }, }); }, [activeChat, curbApi] ); const renderMessage = useMemo( () => createMessageRenderer({ handleReaction, getIconFromCache, accountId, isThread, setThread: setThread ? setThread : undefined, toggleEmojiSelector, deleteMessage, canDeleteMessage: isOwner || isModerator, canEditMessage: isModerator, }), [isOwner, isModerator] ); if (openThread && isThread) { chatStyle.height = "calc(100% - 124px)"; chatStyle.width = "100%"; chatStyle["overflow"] = "hidden"; containerPaddingStyle.flexDirection = "column"; containerPaddingStyle.paddingLeft = "0px"; containerPaddingStyle.height = "100%"; containerPaddingStyle["width"] = "100%"; wrapperStyle.width = "100%"; } else if (openThread && !isThread) { chatStyle.height = "100%"; chatStyle.width = "100%"; containerPaddingStyle.paddingRight = "0px"; wrapperStyle.width = "60%"; } else { chatStyle.height = "100%"; chatStyle.width = "100%"; chatStyle["overflow"] = "hidden"; } const EmojiPopupContainer = styled.div` position: absolute; bottom: 70px; right: 2.5rem; `; return ( <Wrapper style={wrapperStyle}> <ContainerPadding style={containerPaddingStyle}> {openThread && isThread && ( <ThreadHeader openThread={openThread} onClose={() => setOpenThread(undefined)} /> )} <VirtualizedChat loadInitialMessages={loadInitialMessages} loadPrevMessages={loadPrevMessages} deletedMessages={deletedMessages} incomingMessages={incomingMessages} updatedMessages={updatedMessages} onItemNewItemRender={readMessage} shouldTriggerNewItemIndicator={(message) => message.sender !== accountId } render={renderMessage} chatId={isThread ? openThread.id : activeChat} // re-render the chat when the chat/thread changes style={chatStyle} /> </ContainerPadding> <Widget src={`${componentOwnerId}/widget/Calimero.Curb.Chat.MessageInput`} props={{ componentOwnerId, selectedChat: activeChat.type === "channel" ? activeChat.name : activeChat.id, sendMessage: sendMessage, resetImage: resetImage, openThread, isThread, isReadOnly, }} /> </Wrapper> );