diff --git a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatFooter.tsx b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatFooter.tsx index 4b04687ebe..7d4bf5178f 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatFooter.tsx +++ b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatFooter.tsx @@ -2,7 +2,7 @@ import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'reac import { useMedia } from 'react-use'; import data from '@emoji-mart/data'; import Picker from '@emoji-mart/react'; -import { selectLocalPeerName, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; +import { selectLocalPeer, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; import { EmojiIcon, PauseCircleIcon, SendIcon, VerticalMenuIcon } from '@100mslive/react-icons'; import { Box, config as cssConfig, Flex, IconButton as BaseIconButton, Popover, styled, Text } from '../../..'; import { IconButton } from '../../../IconButton'; @@ -86,9 +86,9 @@ export const ChatFooter = ({ const isMobile = useMedia(cssConfig.media.md); const { elements } = useRoomLayoutConferencingScreen(); const message_placeholder = elements?.chat?.message_placeholder || 'Send a message'; - const localPeerName = useHMSStore(selectLocalPeerName); + const localPeer = useHMSStore(selectLocalPeer); const isOverlayChat = elements?.chat?.is_overlay; - const can_disable_chat = !!elements?.chat?.real_time_controls?.can_disable_chat; + const canDisableChat = !!elements?.chat?.real_time_controls?.can_disable_chat; const sendMessage = useCallback(async () => { const message = inputRef?.current?.value; @@ -132,7 +132,7 @@ export const ChatFooter = ({ {/* {screenType !== 'hls_live_streaming' ? ( ) : null} */} - {can_disable_chat ? ( + {canDisableChat ? ( @@ -145,10 +145,16 @@ export const ChatFooter = ({ align="end" side="top" onClick={() => { - hmsActions.sessionStore.set(SESSION_STORE_KEY.CHAT_STATE, { + const chatState = { enabled: false, - updatedBy: localPeerName, - }); + updatedBy: { + peerId: localPeer?.id, + userId: localPeer?.customerUserId, + userName: localPeer?.name, + }, + updatedAt: Date.now(), + }; + hmsActions.sessionStore.set(SESSION_STORE_KEY.CHAT_STATE, chatState); }} css={{ backgroundColor: '$surface_default', diff --git a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatStates.jsx b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatStates.jsx index e7bab89a2c..68a4938909 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatStates.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatStates.jsx @@ -1,5 +1,5 @@ import React, { useCallback } from 'react'; -import { selectLocalPeerName, selectSessionStore, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; +import { selectLocalPeer, selectSessionStore, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; import { Button } from '../../../Button'; import { Box, Flex } from '../../../Layout'; import { Text } from '../../../Text'; @@ -10,17 +10,19 @@ export const ChatPaused = () => { const hmsActions = useHMSActions(); const { elements } = useRoomLayoutConferencingScreen(); const { can_disable_chat } = elements?.chat.real_time_controls || false; - const { enabled: isChatEnabled = true, updatedBy: chatStateUpdatedBy = '' } = + const { enabled: isChatEnabled = true, updatedBy: chatStateUpdatedBy } = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_STATE)) || {}; - const localPeerName = useHMSStore(selectLocalPeerName); + + const localPeer = useHMSStore(selectLocalPeer); const unPauseChat = useCallback( async () => await hmsActions.sessionStore.set(SESSION_STORE_KEY.CHAT_STATE, { enabled: true, - updatedBy: localPeerName, + updatedBy: { userName: localPeer.name, userId: localPeer?.customerUserId, peerId: localPeer.id }, + updatedAt: Date.now(), }), - [hmsActions, localPeerName], + [hmsActions, localPeer], ); return isChatEnabled ? null : ( @@ -37,7 +39,7 @@ export const ChatPaused = () => { variant="xs" css={{ color: '$on_surface_medium', maxWidth: '100%', overflow: 'hidden', textOverflow: 'ellipsis' }} > - Chat has been paused by {chatStateUpdatedBy} + Chat has been paused by {chatStateUpdatedBy?.peerId === localPeer.id ? 'you' : chatStateUpdatedBy?.userName} {can_disable_chat ? ( diff --git a/packages/roomkit-react/src/Prebuilt/components/Notifications/ChatNotifications.tsx b/packages/roomkit-react/src/Prebuilt/components/Notifications/ChatNotifications.tsx new file mode 100644 index 0000000000..52c3a7c0b1 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/Notifications/ChatNotifications.tsx @@ -0,0 +1,34 @@ +import React, { useEffect } from 'react'; +import { v4 as uuid } from 'uuid'; +import { selectLocalPeerID, selectSessionStore, useHMSStore } from '@100mslive/react-sdk'; +import { ChatIcon, ChatUnreadIcon } from '@100mslive/react-icons'; +// @ts-ignore +import { ToastManager } from '../Toast/ToastManager'; +import { SESSION_STORE_KEY } from '../../common/constants'; + +const NOTIFICATION_TIME_DIFFERENCE = 5000; + +export const ChatNotifications = () => { + const chatState = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_STATE)); + const localPeerId = useHMSStore(selectLocalPeerID); + + useEffect(() => { + if (!chatState || chatState.updatedBy?.peerId === localPeerId) { + return; + } + + const showToast = Date.now() - chatState.updatedAt < NOTIFICATION_TIME_DIFFERENCE; + + if (!showToast) { + return; + } + + const notification = { + id: uuid(), + icon: chatState.enabled ? : , + title: `Chat ${chatState.enabled ? 'resumed' : 'paused'} by ${chatState.updatedBy?.userName}`, + }; + ToastManager.addToast(notification); + }, [chatState]); + return <>; +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.tsx b/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.tsx index c23d5b2688..94c932ed33 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.tsx +++ b/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.tsx @@ -20,6 +20,7 @@ import { ToastBatcher } from '../Toast/ToastBatcher'; // @ts-ignore: No implicit Any import { ToastManager } from '../Toast/ToastManager'; import { AutoplayBlockedModal } from './AutoplayBlockedModal'; +import { ChatNotifications } from './ChatNotifications'; import { InitErrorModal } from './InitErrorModal'; import { PeerNotifications } from './PeerNotifications'; import { PermissionErrorModal } from './PermissionErrorModal'; @@ -186,6 +187,7 @@ export function Notifications() { + ); }