import React, { useEffect, useState } from 'react'; import type { SendbirdFileMessage } from '@sendbird/uikit-utils'; import { millsToMSS } from '@sendbird/uikit-utils'; import Box from '../../components/Box'; import Icon from '../../components/Icon'; import PressBox from '../../components/PressBox'; import ProgressBar from '../../components/ProgressBar'; import Text from '../../components/Text'; import createStyleSheet from '../../styles/createStyleSheet'; import useUIKitTheme from '../../theme/useUIKitTheme'; import LoadingSpinner from '../LoadingSpinner'; import MessageContainer from './MessageContainer'; import type { GroupChannelMessageProps } from './index'; export type VoiceFileMessageState = { status: 'preparing' | 'playing' | 'paused'; currentTime: number; duration: number; }; type Props = GroupChannelMessageProps< SendbirdFileMessage, { durationMetaArrayKey?: string; onUnmount: () => void; initialCurrentTime?: number; onSubscribeStatus?: (channelUrl: string, messageId: number, subscriber: (currentTime: number) => void) => void; onUnsubscribeStatus?: (channelUrl: string, messageId: number, subscriber: (currentTime: number) => void) => void; } >; const VoiceFileMessage = (props: Props) => { const { onLongPress, variant = 'incoming', onToggleVoiceMessage, message, durationMetaArrayKey = 'KEY_VOICE_MESSAGE_DURATION', onUnmount, initialCurrentTime, onSubscribeStatus, onUnsubscribeStatus, } = props; const { colors } = useUIKitTheme(); const [state, setState] = useState(() => { const meta = message.metaArrays.find((it) => it.key === durationMetaArrayKey); const value = meta?.value?.[0]; const initialDuration = value ? parseInt(value, 10) : 0; return { status: 'paused', currentTime: initialCurrentTime || 0, duration: initialDuration, }; }); useEffect(() => { return () => { onUnmount(); }; }, []); useEffect(() => { const updateCurrentTime = (currentTime: number) => { setState((prev) => ({ ...prev, currentTime })); }; onSubscribeStatus?.(props.channel.url, props.message.messageId, updateCurrentTime); return () => { onUnsubscribeStatus?.(props.channel.url, props.message.messageId, updateCurrentTime); }; }, []); const uiColors = colors.ui.groupChannelMessage[variant]; const remainingTime = state.duration - state.currentTime; return ( onToggleVoiceMessage?.(state, setState)} onLongPress={onLongPress}> {state.status === 'preparing' ? ( ) : ( )} {millsToMSS(state.currentTime === 0 ? state.duration : remainingTime)} } /> {props.children} ); }; const styles = createStyleSheet({ container: { borderRadius: 16, overflow: 'hidden', }, image: { maxWidth: 240, width: 240, height: 160, borderRadius: 16, overflow: 'hidden', }, }); export default VoiceFileMessage;