diff --git a/packages/react/src/views/ChatBody/ChatBody.js b/packages/react/src/views/ChatBody/ChatBody.js index a582244d0..721c2d2dc 100644 --- a/packages/react/src/views/ChatBody/ChatBody.js +++ b/packages/react/src/views/ChatBody/ChatBody.js @@ -1,11 +1,19 @@ /* eslint-disable no-shadow */ -import React, { useCallback, useContext, useEffect, useState } from 'react'; +import React, { + useCallback, + useContext, + useEffect, + useState, + useRef, +} from 'react'; import PropTypes from 'prop-types'; import { css } from '@emotion/react'; import { Box, Throbber, useComponentOverrides, + Modal, + useTheme, } from '@embeddedchat/ui-elements'; import RCContext from '../../context/RCInstance'; import { @@ -33,21 +41,23 @@ const ChatBody = ({ scrollToBottom, }) => { const { classNames, styleOverrides } = useComponentOverrides('ChatBody'); - - const styles = getChatbodyStyles(); + const { theme, mode } = useTheme(); + const styles = getChatbodyStyles(theme, mode); const [scrollPosition, setScrollPosition] = useState(0); const [popupVisible, setPopupVisible] = useState(false); const [, setIsUserScrolledUp] = useState(false); const [otherUserMessage, setOtherUserMessage] = useState(false); - + const [isOverflowing, setIsOverflowing] = useState(false); const { RCInstance, ECOptions } = useContext(RCContext); + const showAnnouncement = ECOptions?.showAnnouncement; const messages = useMessageStore((state) => state.messages); const threadMessages = useMessageStore((state) => state.threadMessages); - + const [isModalOpen, setModalOpen] = useState(false); const setThreadMessages = useMessageStore((state) => state.setThreadMessages); const upsertMessage = useMessageStore((state) => state.upsertMessage); const removeMessage = useMessageStore((state) => state.removeMessage); const isChannelPrivate = useChannelStore((state) => state.isChannelPrivate); + const channelInfo = useChannelStore((state) => state.channelInfo); const isLoginIn = useLoginStore((state) => state.isLoginIn); const [isThreadOpen, threadMainMessage] = useMessageStore((state) => [ @@ -182,7 +192,24 @@ const ChatBody = ({ const showNewMessagesPopup = () => { setPopupVisible(true); }; + const announcementRef = useRef(null); + + const toggleModal = () => { + setModalOpen(!isModalOpen); + }; + + const checkOverflow = () => { + if (announcementRef.current) { + setIsOverflowing( + announcementRef.current.scrollWidth > + announcementRef.current.clientWidth + ); + } + }; + useEffect(() => { + checkOverflow(); + }, [channelInfo.announcement, showAnnouncement]); useEffect(() => { const currentRef = messageListRef.current; currentRef.addEventListener('scroll', handleScroll); @@ -204,6 +231,44 @@ const ChatBody = ({ return ( <> + {channelInfo.announcement && showAnnouncement && ( + + + {channelInfo.announcement} + + + )} + {isModalOpen && ( + + + Announcement + + + + {channelInfo.announcement} + + + )} { +export const getChatbodyStyles = (theme, mode) => { const styles = { chatbodyContainer: css` flex: 1; @@ -14,6 +15,23 @@ export const getChatbodyStyles = () => { padding-top: 70px; margin-top: 0.25rem; `, + announcementStyles: css` + display: flex; + justify-content: center; + padding: 7px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + background-color: ${mode === 'light' + ? lighten(theme.colors.info, 0.78) + : darken(theme.colors.primary, 0.7)}; + `, + announcementTextBox: css` + max-width: 80%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + `, }; return styles; diff --git a/packages/react/src/views/ChatHeader/ChatHeader.js b/packages/react/src/views/ChatHeader/ChatHeader.js index 010739977..817ff4097 100644 --- a/packages/react/src/views/ChatHeader/ChatHeader.js +++ b/packages/react/src/views/ChatHeader/ChatHeader.js @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useMemo } from 'react'; +import { css } from '@emotion/react'; import PropTypes from 'prop-types'; import { Box, @@ -8,6 +9,7 @@ import { useToastBarDispatch, useComponentOverrides, useTheme, + Avatar, } from '@embeddedchat/ui-elements'; import { useRCContext } from '../../context/RCInstance'; import { @@ -115,7 +117,10 @@ const ChatHeader = ({ ); const setShowAllFiles = useFileStore((state) => state.setShowAllFiles); const setShowMentions = useMentionsStore((state) => state.setShowMentions); - + const getChannelAvatarURL = (channelname) => { + const host = RCInstance.getHost(); + return `${host}/avatar/${channelname}`; + }; const handleGoBack = async () => { if (isUserAuthenticated) { getMessagesAndRoles(); @@ -347,7 +352,6 @@ const ChatHeader = ({ > - {isUserAuthenticated ? ( <> @@ -355,17 +359,40 @@ const ChatHeader = ({ level={3} className="ec-chat-header--channelName" css={styles.clearSpacing} + style={{ + display: 'flex', + alignItems: 'center', + gap: '0.2rem', + }} > - {channelInfo.name || channelName || 'channelName'} + + + setExclusiveState(setShowChannelinfo)} + > + +
+ {channelInfo.name || channelName || 'channelName'} +
+
+ {fullScreen && ( + + {channelInfo.topic || ''} + + )} +
- {fullScreen && ( -

- {channelInfo.description || ''} -

- )} ) : ( { margin: 0; padding: 0; `, - chatHeaderChild: css` ${rowCentreAlign} padding: 0 0.75rem; @@ -43,6 +42,16 @@ const getChatHeaderStyles = ({ theme, mode }) => { position:relative; gap: 0.5rem; `, + channelName: css` + display: flex; + align-items: center; + gap: 0.1rem; + cursor: pointer; + `, + channelTopic: css` + opacity: 0.8rem; + font-size: 1rem; + `, }; return styles; }; diff --git a/packages/react/src/views/EmbeddedChat.js b/packages/react/src/views/EmbeddedChat.js index 00557f289..17b1ff1a4 100644 --- a/packages/react/src/views/EmbeddedChat.js +++ b/packages/react/src/views/EmbeddedChat.js @@ -44,6 +44,7 @@ const EmbeddedChat = (props) => { toastBarPosition = 'bottom right', showRoles = false, showAvatar = true, + showAnnouncement = true, showUsername = false, showName = true, enableThreads = false, @@ -204,6 +205,7 @@ const EmbeddedChat = (props) => { showName, showRoles, showAvatar, + showAnnouncement, showUsername, hideHeader, anonymousMode, @@ -219,6 +221,7 @@ const EmbeddedChat = (props) => { showName, showRoles, showAvatar, + showAnnouncement, showUsername, hideHeader, anonymousMode, @@ -281,6 +284,7 @@ EmbeddedChat.propTypes = { toastBarPosition: PropTypes.string, showRoles: PropTypes.bool, showAvatar: PropTypes.bool, + showAnnouncement: PropTypes.bool, enableThreads: PropTypes.bool, theme: PropTypes.object, auth: PropTypes.oneOfType([ diff --git a/packages/react/src/views/RoomInformation/RoomInformation.js b/packages/react/src/views/RoomInformation/RoomInformation.js index 3cfdefad0..b4e26764c 100644 --- a/packages/react/src/views/RoomInformation/RoomInformation.js +++ b/packages/react/src/views/RoomInformation/RoomInformation.js @@ -9,11 +9,12 @@ import { } from '@embeddedchat/ui-elements'; import RCContext from '../../context/RCInstance'; import { useChannelStore } from '../../store'; +import getRoomInformationStyles from './RoomInformation.styles'; import useSetExclusiveState from '../../hooks/useSetExclusiveState'; const Roominfo = () => { const { RCInstance } = useContext(RCContext); - + const styles = getRoomInformationStyles(); const channelInfo = useChannelStore((state) => state.channelInfo); const { variantOverrides } = useComponentOverrides('RoomMember'); const viewType = variantOverrides.viewType || 'Sidebar'; @@ -44,34 +45,35 @@ const Roominfo = () => { overflow: auto; `} > - - - # {channelInfo.name} - - - Description - - - {channelInfo.description} - + + + + # {channelInfo.name} + {channelInfo.description && ( + <> + Description + {channelInfo.description} + + )} + {channelInfo.topic && ( + <> + Topic + {channelInfo.topic} + + )} + {channelInfo.announcement && ( + <> + Announcement + {channelInfo.announcement} + + )}
diff --git a/packages/react/src/views/RoomInformation/RoomInformation.styles.js b/packages/react/src/views/RoomInformation/RoomInformation.styles.js new file mode 100644 index 000000000..9ab039b94 --- /dev/null +++ b/packages/react/src/views/RoomInformation/RoomInformation.styles.js @@ -0,0 +1,25 @@ +import { css } from '@emotion/react'; + +const getRoomInformationStyles = () => { + const styles = { + infoContainer: css` + margin: 16px; + display: flex; + flex-direction: column; + gap: 0.1rem; + `, + infoHeader: css` + margin-block: 5px; + font-weight: 900; + `, + info: css` + word-wrap: break-word; + overflow-wrap: anywhere; + white-space: normal; + `, + }; + + return styles; +}; + +export default getRoomInformationStyles;