@@ -10,9 +10,9 @@ import {
1010import { displayDuration } from './utils' ;
1111import { FileIcon } from '../ReactFileUtilities' ;
1212import { useMessageContext , useTranslationContext } from '../../context' ;
13- import { useAudioPlayer } from '../AudioPlayer/WithAudioPlayback ' ;
13+ import { type AudioPlayerState , useAudioPlayer } from '../AudioPlayback/ ' ;
1414import { useStateStore } from '../../store' ;
15- import type { AudioPlayerState } from '../AudioPlayer /AudioPlayer' ;
15+ import type { AudioPlayer } from '../AudioPlayback /AudioPlayer' ;
1616
1717const rootClassName = 'str-chat__message-attachment__voice-recording-widget' ;
1818
@@ -24,51 +24,16 @@ const audioPlayerStateSelector = (state: AudioPlayerState) => ({
2424 secondsElapsed : state . secondsElapsed ,
2525} ) ;
2626
27- export type VoiceRecordingPlayerProps = Pick < VoiceRecordingProps , 'attachment' > & {
28- /** An array of fractional numeric values of playback speed to override the defaults (1.0, 1.5, 2.0) */
29- playbackRates ?: number [ ] ;
27+ type VoiceRecordingPlayerUIProps = {
28+ audioPlayer : AudioPlayer ;
3029} ;
3130
32- export const VoiceRecordingPlayer = ( {
33- attachment,
34- playbackRates,
35- } : VoiceRecordingPlayerProps ) => {
36- const { t } = useTranslationContext ( 'VoiceRecordingPlayer' ) ;
37- const {
38- asset_url,
39- duration = 0 ,
40- mime_type,
41- title = t ( 'Voice message' ) ,
42- waveform_data,
43- } = attachment ;
44-
45- /**
46- * Introducing message context. This could be breaking change, therefore the fallback to {} is provided.
47- * If this component is used outside the message context, then there will be no audio player namespacing
48- * => scrolling away from the message in virtualized ML would create a new AudioPlayer instance.
49- *
50- * Edge case: the requester (message) has multiple attachments with the same assetURL - does not happen
51- * with the default SDK components, but can be done with custom API calls.In this case all the Audio
52- * widgets will share the state.
53- */
54- const { message, threadList } = useMessageContext ( ) ?? { } ;
55-
56- const audioPlayer = useAudioPlayer ( {
57- durationSeconds : duration ?? 0 ,
58- mimeType : mime_type ,
59- playbackRates,
60- requester :
61- message ?. id &&
62- `${ threadList ? ( message . parent_id ?? message . id ) : '' } ${ message . id } ` ,
63- src : asset_url ,
64- } ) ;
65-
31+ // todo: finish creating a BaseAudioPlayer derived from VoiceRecordingPlayerUI and AudioAttachmentUI
32+ const VoiceRecordingPlayerUI = ( { audioPlayer } : VoiceRecordingPlayerUIProps ) => {
6633 const { canPlayRecord, isPlaying, playbackRate, progress, secondsElapsed } =
6734 useStateStore ( audioPlayer ?. state , audioPlayerStateSelector ) ?? { } ;
6835
69- if ( ! audioPlayer ) return null ;
70-
71- const displayedDuration = secondsElapsed || duration ;
36+ const displayedDuration = secondsElapsed || audioPlayer . durationSeconds ;
7237
7338 return (
7439 < div className = { rootClassName } data-testid = 'voice-recording-widget' >
@@ -77,25 +42,25 @@ export const VoiceRecordingPlayer = ({
7742 < div
7843 className = 'str-chat__message-attachment__voice-recording-widget__title'
7944 data-testid = 'voice-recording-title'
80- title = { title }
45+ title = { audioPlayer . title }
8146 >
82- { title }
47+ { audioPlayer . title }
8348 </ div >
8449 < div className = 'str-chat__message-attachment__voice-recording-widget__audio-state' >
8550 < div className = 'str-chat__message-attachment__voice-recording-widget__timer' >
86- { attachment . duration ? (
51+ { audioPlayer . durationSeconds ? (
8752 displayDuration ( displayedDuration )
8853 ) : (
8954 < FileSizeIndicator
90- fileSize = { attachment . file_size }
55+ fileSize = { audioPlayer . fileSize }
9156 maximumFractionDigits = { 0 }
9257 />
9358 ) }
9459 </ div >
9560 < WaveProgressBar
9661 progress = { progress }
9762 seek = { audioPlayer . seek }
98- waveformData = { waveform_data || [ ] }
63+ waveformData = { audioPlayer . waveformData || [ ] }
9964 />
10065 </ div >
10166 </ div >
@@ -108,13 +73,59 @@ export const VoiceRecordingPlayer = ({
10873 { playbackRate ?. toFixed ( 1 ) } x
10974 </ PlaybackRateButton >
11075 ) : (
111- < FileIcon big = { true } mimeType = { mime_type } size = { 40 } />
76+ < FileIcon big = { true } mimeType = { audioPlayer . mimeType } size = { 40 } />
11277 ) }
11378 </ div >
11479 </ div >
11580 ) ;
11681} ;
11782
83+ export type VoiceRecordingPlayerProps = Pick < VoiceRecordingProps , 'attachment' > & {
84+ /** An array of fractional numeric values of playback speed to override the defaults (1.0, 1.5, 2.0) */
85+ playbackRates ?: number [ ] ;
86+ } ;
87+
88+ export const VoiceRecordingPlayer = ( {
89+ attachment,
90+ playbackRates,
91+ } : VoiceRecordingPlayerProps ) => {
92+ const { t } = useTranslationContext ( ) ;
93+ const {
94+ asset_url,
95+ duration = 0 ,
96+ file_size,
97+ mime_type,
98+ title = t ( 'Voice message' ) ,
99+ waveform_data,
100+ } = attachment ;
101+
102+ /**
103+ * Introducing message context. This could be breaking change, therefore the fallback to {} is provided.
104+ * If this component is used outside the message context, then there will be no audio player namespacing
105+ * => scrolling away from the message in virtualized ML would create a new AudioPlayer instance.
106+ *
107+ * Edge case: the requester (message) has multiple attachments with the same assetURL - does not happen
108+ * with the default SDK components, but can be done with custom API calls.In this case all the Audio
109+ * widgets will share the state.
110+ */
111+ const { message, threadList } = useMessageContext ( ) ?? { } ;
112+
113+ const audioPlayer = useAudioPlayer ( {
114+ durationSeconds : duration ?? 0 ,
115+ fileSize : file_size ,
116+ mimeType : mime_type ,
117+ playbackRates,
118+ requester :
119+ message ?. id &&
120+ `${ threadList ? ( message . parent_id ?? message . id ) : '' } ${ message . id } ` ,
121+ src : asset_url ,
122+ title,
123+ waveformData : waveform_data ,
124+ } ) ;
125+
126+ return audioPlayer ? < VoiceRecordingPlayerUI audioPlayer = { audioPlayer } /> : null ;
127+ } ;
128+
118129export type QuotedVoiceRecordingProps = Pick < VoiceRecordingProps , 'attachment' > ;
119130
120131export const QuotedVoiceRecording = ( { attachment } : QuotedVoiceRecordingProps ) => {
0 commit comments