-
Notifications
You must be signed in to change notification settings - Fork 297
Expand file tree
/
Copy pathAudio.tsx
More file actions
109 lines (98 loc) · 4.03 KB
/
Audio.tsx
File metadata and controls
109 lines (98 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import React from 'react';
import type { Attachment } from 'stream-chat';
import { FileSizeIndicator as DefaultFileSizeIndicator } from './components';
import type { AudioPlayerState } from '../AudioPlayback/AudioPlayer';
import { useAudioPlayer } from '../AudioPlayback/WithAudioPlayback';
import { useStateStore } from '../../store';
import { useComponentContext, useMessageContext } from '../../context';
import type { AudioPlayer } from '../AudioPlayback/AudioPlayer';
import { PlayButton } from '../Button/PlayButton';
import { FileIcon } from '../FileIcon';
import { DurationDisplay, ProgressBar } from '../AudioPlayback';
type AudioAttachmentUIProps = {
audioPlayer: AudioPlayer;
};
// todo: finish creating a BaseAudioPlayer derived from VoiceRecordingPlayerUI and AudioAttachmentUI
const AudioAttachmentUI = ({ audioPlayer }: AudioAttachmentUIProps) => {
const { FileSizeIndicator = DefaultFileSizeIndicator } = useComponentContext();
const dataTestId = 'audio-widget';
const rootClassName = 'str-chat__message-attachment-audio-widget';
const { durationSeconds, isPlaying, progress, secondsElapsed } =
useStateStore(audioPlayer?.state, audioPlayerStateSelector) ?? {};
return (
<div className={rootClassName} data-testid={dataTestId}>
<div className='str-chat__message-attachment-audio-widget--play-controls'>
<PlayButton isPlaying={!!isPlaying} onClick={audioPlayer.togglePlay} />
</div>
<div className='str-chat__message-attachment-audio-widget--data'>
<div className='str-chat__message-attachment-audio-widget--text-first-row'>
<div className='str-chat__message-attachment-audio-widget--title'>
{audioPlayer.title}
</div>
<FileIcon
className='str-chat__file-icon'
mimeType={audioPlayer.mimeType}
size='sm'
/>
{/*<DownloadButton assetUrl={audioPlayer.src} />*/}
</div>
<div className='str-chat__message-attachment-audio-widget--text-second-row'>
{durationSeconds ? (
<>
<DurationDisplay
duration={durationSeconds}
isPlaying={!!isPlaying}
secondsElapsed={secondsElapsed}
/>
<ProgressBar progress={progress ?? 0} seek={audioPlayer.seek} />
</>
) : (
<>
<FileSizeIndicator fileSize={audioPlayer.fileSize} />
<ProgressBar progress={progress ?? 0} seek={audioPlayer.seek} />
</>
)}
</div>
</div>
</div>
);
};
export type AudioProps = {
attachment: Attachment;
};
const audioPlayerStateSelector = (state: AudioPlayerState) => ({
durationSeconds: state.durationSeconds,
isPlaying: state.isPlaying,
progress: state.progressPercent,
secondsElapsed: state.secondsElapsed,
});
/**
* Audio attachment with play/pause button and progress bar
*/
export const Audio = (props: AudioProps) => {
const {
attachment: { asset_url, duration, file_size, mime_type, title },
} = props;
/**
* 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,
fileSize: file_size,
mimeType: mime_type,
requester:
message?.id &&
`${threadList ? (message.parent_id ?? message.id) : ''}${message.id}`,
src: asset_url,
title,
waveformData: props.attachment.waveform_data,
});
return audioPlayer ? <AudioAttachmentUI audioPlayer={audioPlayer} /> : null;
};