UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

68 lines (67 loc) 5.27 kB
import React from 'react'; import { FileSizeIndicator, PlaybackRateButton, PlayButton, WaveProgressBar, } from './components'; import { displayDuration } from './utils'; import { FileIcon } from '../ReactFileUtilities'; import { useMessageContext, useTranslationContext } from '../../context'; import { useAudioPlayer } from '../AudioPlayback/'; import { useStateStore } from '../../store'; const rootClassName = 'str-chat__message-attachment__voice-recording-widget'; const audioPlayerStateSelector = (state) => ({ canPlayRecord: state.canPlayRecord, isPlaying: state.isPlaying, playbackRate: state.currentPlaybackRate, progress: state.progressPercent, secondsElapsed: state.secondsElapsed, }); // todo: finish creating a BaseAudioPlayer derived from VoiceRecordingPlayerUI and AudioAttachmentUI const VoiceRecordingPlayerUI = ({ audioPlayer }) => { const { canPlayRecord, isPlaying, playbackRate, progress, secondsElapsed } = useStateStore(audioPlayer?.state, audioPlayerStateSelector) ?? {}; const displayedDuration = secondsElapsed || audioPlayer.durationSeconds; return (React.createElement("div", { className: rootClassName, "data-testid": 'voice-recording-widget' }, React.createElement(PlayButton, { isPlaying: !!isPlaying, onClick: audioPlayer.togglePlay }), React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__metadata' }, React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__title', "data-testid": 'voice-recording-title', title: audioPlayer.title }, audioPlayer.title), React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__audio-state' }, React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__timer' }, audioPlayer.durationSeconds ? (displayDuration(displayedDuration)) : (React.createElement(FileSizeIndicator, { fileSize: audioPlayer.fileSize, maximumFractionDigits: 0 }))), React.createElement(WaveProgressBar, { progress: progress, seek: audioPlayer.seek, waveformData: audioPlayer.waveformData || [] }))), React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__right-section' }, isPlaying ? (React.createElement(PlaybackRateButton, { disabled: !canPlayRecord, onClick: audioPlayer.increasePlaybackRate }, playbackRate?.toFixed(1), "x")) : (React.createElement(FileIcon, { big: true, mimeType: audioPlayer.mimeType, size: 40 }))))); }; export const VoiceRecordingPlayer = ({ attachment, playbackRates, }) => { const { t } = useTranslationContext(); const { asset_url, duration = 0, file_size, mime_type, title = t('Voice message'), waveform_data, } = attachment; /** * Introducing message context. This could be breaking change, therefore the fallback to {} is provided. * If this component is used outside the message context, then there will be no audio player namespacing * => scrolling away from the message in virtualized ML would create a new AudioPlayer instance. * * Edge case: the requester (message) has multiple attachments with the same assetURL - does not happen * with the default SDK components, but can be done with custom API calls.In this case all the Audio * widgets will share the state. */ const { message, threadList } = useMessageContext() ?? {}; const audioPlayer = useAudioPlayer({ durationSeconds: duration ?? 0, fileSize: file_size, mimeType: mime_type, playbackRates, requester: message?.id && `${threadList ? (message.parent_id ?? message.id) : ''}${message.id}`, src: asset_url, title, waveformData: waveform_data, }); return audioPlayer ? React.createElement(VoiceRecordingPlayerUI, { audioPlayer: audioPlayer }) : null; }; export const QuotedVoiceRecording = ({ attachment }) => { const { t } = useTranslationContext(); const title = attachment.title || t('Voice message'); return (React.createElement("div", { className: rootClassName, "data-testid": 'quoted-voice-recording-widget' }, React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__metadata' }, title && (React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__title', "data-testid": 'voice-recording-title', title: title }, title)), React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__audio-state' }, React.createElement("div", { className: 'str-chat__message-attachment__voice-recording-widget__timer' }, attachment.duration ? (displayDuration(attachment.duration)) : (React.createElement(FileSizeIndicator, { fileSize: attachment.file_size, maximumFractionDigits: 0 }))))), React.createElement(FileIcon, { big: true, mimeType: attachment.mime_type, size: 34 }))); }; export const VoiceRecording = ({ attachment, isQuoted }) => isQuoted ? (React.createElement(QuotedVoiceRecording, { attachment: attachment })) : (React.createElement(VoiceRecordingPlayer, { attachment: attachment }));