-
Notifications
You must be signed in to change notification settings - Fork 298
Expand file tree
/
Copy pathCardAudio.tsx
More file actions
121 lines (111 loc) · 3.9 KB
/
Copy pathCardAudio.tsx
File metadata and controls
121 lines (111 loc) · 3.9 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
110
111
112
113
114
115
116
117
118
119
120
121
import { type AudioPlayerState, ProgressBar, useAudioPlayer } from '../../AudioPlayback';
import { useComponentContext, useMessageContext } from '../../../context';
import { useStateStore } from '../../../store';
import { PlayButton } from '../../Button';
import type { AudioProps } from '../Audio';
import React from 'react';
import { IconLink as DefaultIconLink } from '../../Icons';
import { SafeAnchor } from '../../SafeAnchor';
import type { CardProps } from './Card';
const getHostFromURL = (url?: string | null) => {
if (url !== undefined && url !== null) {
const [trimmedUrl] = url.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '').split('/');
return trimmedUrl;
}
return null;
};
const SourceLink = ({
author_name,
showUrl,
url,
}: Pick<CardProps, 'author_name'> & { url: string; showUrl?: boolean }) => {
const { icons: { IconLink = DefaultIconLink } = {} } = useComponentContext();
return (
<div
className='str-chat__message-attachment-card--source-link'
data-testid='card-source-link'
>
<IconLink />
<SafeAnchor
className='str-chat__message-attachment-card--url'
href={url}
rel='noopener noreferrer'
target='_blank'
>
{showUrl ? url : author_name || getHostFromURL(url)}
</SafeAnchor>
</div>
);
};
const audioPlayerStateSelector = (state: AudioPlayerState) => ({
durationSeconds: state.durationSeconds,
isPlaying: state.isPlaying,
progress: state.progressPercent,
secondsElapsed: state.secondsElapsed,
});
const AudioWidget = ({ mimeType, src }: { src: string; mimeType?: string }) => {
/**
* 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({
mimeType,
requester:
message?.id &&
`${threadList ? (message.parent_id ?? message.id) : ''}${message.id}`,
src,
});
const { durationSeconds, isPlaying, progress, secondsElapsed } =
useStateStore(audioPlayer?.state, audioPlayerStateSelector) ?? {};
if (!audioPlayer) return null;
return (
<div className='str-chat__message-attachment-card-audio-widget--first-row'>
<div className='str-chat__message-attachment-audio-widget--play-controls'>
<PlayButton isPlaying={!!isPlaying} onClick={audioPlayer.togglePlay} />
</div>
<ProgressBar
durationSeconds={durationSeconds}
progress={progress ?? 0}
secondsElapsed={secondsElapsed}
seek={audioPlayer.seek}
/>
</div>
);
};
export const CardAudio = ({
attachment: {
asset_url,
author_name,
mime_type,
og_scrape_url,
text,
title,
title_link,
},
}: AudioProps) => {
const url = title_link || og_scrape_url;
const dataTestId = 'card-audio-widget';
const rootClassName = 'str-chat__message-attachment-card-audio-widget';
return (
<div className={rootClassName} data-testid={dataTestId}>
{asset_url && <AudioWidget mimeType={mime_type} src={asset_url} />}
<div className='str-chat__message-attachment-audio-widget--second-row'>
{url && <SourceLink author_name={author_name} url={url} />}
{title && (
<div className='str-chat__message-attachment-audio-widget--title'>{title}</div>
)}
{text && (
<div className='str-chat__message-attachment-audio-widget--description'>
{text}
</div>
)}
</div>
</div>
);
};