UNPKG

@100mslive/roomkit-react

Version:

![Banner](https://github.com/100mslive/web-sdks/blob/06c65259912db6ccd8617f2ecb6fef51429251ec/prebuilt-banner.png)

155 lines (142 loc) 4.21 kB
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useMedia } from 'react-use'; import { selectIsLargeRoom, selectLocalPeerID, selectPeerNameByID, useCustomEvent, useHMSActions, useHMSStore, useHMSVanillaStore, } from '@100mslive/react-sdk'; import { Box, Flex } from '../../Layout'; import { Text } from '../../Text'; import { config as cssConfig, keyframes } from '../../Theme'; import { EMOJI_REACTION_TYPE } from '../common/constants'; let emojiCount = 1; const flyAndFade = keyframes({ '20%': { opacity: 1 }, '100%': { bottom: '60%', opacity: 0 }, }); const wiggleLeftRight = keyframes({ '0%': { marginLeft: '-50px' }, '100%': { marginLeft: '50px' }, }); const wiggleRightLeft = keyframes({ '0%': { marginLeft: '50px' }, '100%': { marginLeft: '-50px' }, }); const getStartingPoints = isMobile => { let arr = []; const min = 5; const max = isMobile ? 30 : 20; const inc = isMobile ? 8 : 5; for (let i = min; i <= max; i += inc) { arr.push(i); } return arr; }; export function FlyingEmoji() { const localPeerId = useHMSStore(selectLocalPeerID); const vanillaStore = useHMSVanillaStore(); const hmsActions = useHMSActions(); const [emojis, setEmojis] = useState([]); const isMobile = useMedia(cssConfig.media.md); const isLargeRoom = useHMSStore(selectIsLargeRoom); const startingPoints = useMemo(() => getStartingPoints(isMobile), [isMobile]); const showFlyingEmoji = useCallback( async ({ emojiId, senderId }) => { if (!emojiId || !senderId || document.hidden) { return; } let senderPeerName = vanillaStore.getState(selectPeerNameByID(senderId)); if (!senderPeerName && isLargeRoom) { const sender = await hmsActions.getPeer(senderId); senderPeerName = sender?.name; } const nameToShow = localPeerId === senderId ? 'You' : senderPeerName; const startingPoint = startingPoints[emojiCount % startingPoints.length]; const id = emojiCount++; setEmojis(emojis => { return [ ...emojis, { id: id, emojiId: emojiId, senderName: nameToShow, startingPoint: `${startingPoint}%`, wiggleType: Math.random() < 0.5 ? 0 : 1, }, ]; }); }, [vanillaStore, isLargeRoom, localPeerId, startingPoints, hmsActions], ); useCustomEvent({ type: EMOJI_REACTION_TYPE, onEvent: showFlyingEmoji, }); useEffect(() => { window.showFlyingEmoji = showFlyingEmoji; }, [showFlyingEmoji]); return ( <Box css={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, overflow: 'hidden', pointerEvents: 'none', userSelect: 'none', zIndex: 999, }} > {emojis.map(emoji => { return ( <Flex key={emoji.id} css={{ left: emoji.startingPoint, flexDirection: 'column', alignItems: 'center', position: 'absolute', bottom: 0, animation: `${flyAndFade()} 5s forwards, ${ emoji.wiggleType === 0 ? wiggleLeftRight() : wiggleRightLeft() } 1s ease-in-out infinite alternate`, }} onAnimationEnd={() => setEmojis(emojis.filter(item => item.id !== emoji.id))} > <Box> <em-emoji id={emoji.emojiId} size="48px" set="apple" /> </Box> {emoji.senderName ? ( <Box css={{ width: 'fit-content', padding: '$2 $4', background: '$surface_bright', borderRadius: '$1', }} > <Text css={{ fontSize: '$space$6', lineHeight: '$xs', color: '$on_surface_high', }} > {emoji.senderName} </Text> </Box> ) : ( '' )} </Flex> ); })} </Box> ); }