@linktr.ee/messaging-react 1.30.0 → 1.31.0-rc-1776677746
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Creator-77XnrIxc.js → Creator-DGe3CQ_j.js} +131 -138
- package/dist/Creator-DGe3CQ_j.js.map +1 -0
- package/dist/{MediaPlayer-Bf-xPB8Z.js → MediaPlayer-BCsdmsON.js} +83 -89
- package/dist/MediaPlayer-BCsdmsON.js.map +1 -0
- package/dist/Visitor-DyJTWB2_.js +204 -0
- package/dist/Visitor-DyJTWB2_.js.map +1 -0
- package/dist/index.d.ts +33 -19
- package/dist/index.js +775 -767
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ChannelView.tsx +15 -13
- package/src/components/CustomMessage/CustomMessage.stories.tsx +12 -20
- package/src/components/CustomMessage/index.tsx +20 -18
- package/src/components/LockedAttachment/LockedAttachment.stories.tsx +49 -140
- package/src/components/LockedAttachment/components/Creator.tsx +45 -58
- package/src/components/LockedAttachment/components/MediaPlayer.tsx +7 -17
- package/src/components/LockedAttachment/components/Visitor.tsx +99 -88
- package/src/components/LockedAttachment/index.tsx +4 -4
- package/src/components/LockedAttachment/types.ts +9 -4
- package/src/components/MessagingShell/index.tsx +6 -4
- package/src/types.ts +18 -13
- package/dist/Creator-77XnrIxc.js.map +0 -1
- package/dist/MediaPlayer-Bf-xPB8Z.js.map +0 -1
- package/dist/Visitor-C9HSYm3D.js +0 -196
- package/dist/Visitor-C9HSYm3D.js.map +0 -1
|
@@ -21,6 +21,7 @@ export interface CreatorCardProps extends LockedAttachmentBaseProps {
|
|
|
21
21
|
isPreview?: boolean
|
|
22
22
|
placeholderTitle?: string
|
|
23
23
|
placeholderAmountText?: string
|
|
24
|
+
sourceUrl?: string
|
|
24
25
|
onDismiss?: () => void
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -43,7 +44,7 @@ const CloseButton: React.FC<CloseButtonProps> = (props) => {
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
interface CollapsedThumbnailProps {
|
|
46
|
-
|
|
47
|
+
thumbnailUrl?: string
|
|
47
48
|
mimeType: string
|
|
48
49
|
overlayIcon?: React.ElementType
|
|
49
50
|
darkOverlay?: boolean
|
|
@@ -51,7 +52,7 @@ interface CollapsedThumbnailProps {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
const CollapsedThumbnail: React.FC<CollapsedThumbnailProps> = (props) => {
|
|
54
|
-
const {
|
|
55
|
+
const { thumbnailUrl, mimeType, overlayIcon: OverlayIcon, darkOverlay, onClick } = props
|
|
55
56
|
return (
|
|
56
57
|
<button
|
|
57
58
|
type="button"
|
|
@@ -63,9 +64,9 @@ const CollapsedThumbnail: React.FC<CollapsedThumbnailProps> = (props) => {
|
|
|
63
64
|
onClick={onClick}
|
|
64
65
|
aria-label={OverlayIcon ? 'Toggle preview' : undefined}
|
|
65
66
|
>
|
|
66
|
-
{
|
|
67
|
+
{thumbnailUrl ? (
|
|
67
68
|
<img
|
|
68
|
-
src={
|
|
69
|
+
src={thumbnailUrl}
|
|
69
70
|
alt=""
|
|
70
71
|
className="absolute inset-0 h-full w-full object-cover"
|
|
71
72
|
/>
|
|
@@ -91,13 +92,13 @@ const CollapsedThumbnail: React.FC<CollapsedThumbnailProps> = (props) => {
|
|
|
91
92
|
|
|
92
93
|
|
|
93
94
|
interface AudioPreviewProps {
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
sourceUrl?: string
|
|
96
|
+
thumbnailUrl?: string
|
|
96
97
|
mimeType: string
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
const AudioPreview: React.FC<AudioPreviewProps> = (props) => {
|
|
100
|
-
const {
|
|
101
|
+
const { sourceUrl, thumbnailUrl, mimeType } = props
|
|
101
102
|
const [playing, setPlaying] = useState(false)
|
|
102
103
|
const [played, setPlayed] = useState(0)
|
|
103
104
|
const [seeking, setSeeking] = useState(false)
|
|
@@ -133,12 +134,6 @@ const AudioPreview: React.FC<AudioPreviewProps> = (props) => {
|
|
|
133
134
|
|
|
134
135
|
const [audioReady, setAudioReady] = useState(false)
|
|
135
136
|
|
|
136
|
-
useEffect(() => {
|
|
137
|
-
setPlaying(false)
|
|
138
|
-
setPlayed(0)
|
|
139
|
-
setAudioReady(false)
|
|
140
|
-
}, [source])
|
|
141
|
-
|
|
142
137
|
const getFraction = useCallback(
|
|
143
138
|
(e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent) => {
|
|
144
139
|
const track = trackRef.current
|
|
@@ -185,10 +180,10 @@ const AudioPreview: React.FC<AudioPreviewProps> = (props) => {
|
|
|
185
180
|
|
|
186
181
|
return (
|
|
187
182
|
<div className="relative">
|
|
188
|
-
{
|
|
183
|
+
{sourceUrl && (
|
|
189
184
|
<audio
|
|
190
185
|
ref={audioRef}
|
|
191
|
-
src={
|
|
186
|
+
src={sourceUrl}
|
|
192
187
|
loop
|
|
193
188
|
onCanPlay={() => setAudioReady(true)}
|
|
194
189
|
onEnded={() => {
|
|
@@ -200,12 +195,12 @@ const AudioPreview: React.FC<AudioPreviewProps> = (props) => {
|
|
|
200
195
|
</audio>
|
|
201
196
|
)}
|
|
202
197
|
<CollapsedThumbnail
|
|
203
|
-
|
|
198
|
+
thumbnailUrl={thumbnailUrl}
|
|
204
199
|
mimeType={mimeType}
|
|
205
|
-
overlayIcon={
|
|
206
|
-
onClick={
|
|
200
|
+
overlayIcon={sourceUrl && audioReady ? (playing ? PauseIcon : PlayIcon) : undefined}
|
|
201
|
+
onClick={sourceUrl && audioReady ? toggle : undefined}
|
|
207
202
|
/>
|
|
208
|
-
{
|
|
203
|
+
{sourceUrl && audioReady && (
|
|
209
204
|
<div className="absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent">
|
|
210
205
|
<div
|
|
211
206
|
ref={trackRef}
|
|
@@ -250,22 +245,18 @@ const AudioPreview: React.FC<AudioPreviewProps> = (props) => {
|
|
|
250
245
|
}
|
|
251
246
|
|
|
252
247
|
interface VideoPreviewProps {
|
|
253
|
-
|
|
254
|
-
|
|
248
|
+
sourceUrl?: string
|
|
249
|
+
thumbnailUrl?: string
|
|
255
250
|
mimeType: string
|
|
256
251
|
}
|
|
257
252
|
|
|
258
253
|
const VideoPreview: React.FC<VideoPreviewProps> = (props) => {
|
|
259
|
-
const {
|
|
254
|
+
const { sourceUrl, thumbnailUrl, mimeType } = props
|
|
260
255
|
const [expanded, setExpanded] = useState(false)
|
|
261
256
|
const collapse = () => setExpanded(false)
|
|
262
257
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}, [source])
|
|
266
|
-
|
|
267
|
-
if (!source) {
|
|
268
|
-
return <CollapsedThumbnail thumbnail={thumbnail} mimeType={mimeType} />
|
|
258
|
+
if (!sourceUrl) {
|
|
259
|
+
return <CollapsedThumbnail thumbnailUrl={thumbnailUrl} mimeType={mimeType} />
|
|
269
260
|
}
|
|
270
261
|
|
|
271
262
|
return (
|
|
@@ -275,15 +266,15 @@ const VideoPreview: React.FC<VideoPreviewProps> = (props) => {
|
|
|
275
266
|
})}
|
|
276
267
|
>
|
|
277
268
|
<MediaPlayer
|
|
278
|
-
source={
|
|
269
|
+
source={sourceUrl}
|
|
279
270
|
mimeType={mimeType}
|
|
280
|
-
poster={
|
|
271
|
+
poster={thumbnailUrl}
|
|
281
272
|
playing={expanded}
|
|
282
|
-
loop
|
|
273
|
+
loop={true}
|
|
283
274
|
controls={false}
|
|
284
|
-
|
|
275
|
+
muted={true}
|
|
276
|
+
showProgress={true}
|
|
285
277
|
onContainerClick={collapse}
|
|
286
|
-
muted
|
|
287
278
|
/>
|
|
288
279
|
{!expanded && (
|
|
289
280
|
<button
|
|
@@ -292,9 +283,9 @@ const VideoPreview: React.FC<VideoPreviewProps> = (props) => {
|
|
|
292
283
|
onClick={() => setExpanded(true)}
|
|
293
284
|
aria-label="Expand video preview"
|
|
294
285
|
>
|
|
295
|
-
{
|
|
286
|
+
{thumbnailUrl ? (
|
|
296
287
|
<img
|
|
297
|
-
src={
|
|
288
|
+
src={thumbnailUrl}
|
|
298
289
|
alt=""
|
|
299
290
|
className="absolute inset-0 h-full w-full object-cover"
|
|
300
291
|
/>
|
|
@@ -317,43 +308,38 @@ const VideoPreview: React.FC<VideoPreviewProps> = (props) => {
|
|
|
317
308
|
}
|
|
318
309
|
|
|
319
310
|
interface ImagePreviewProps {
|
|
320
|
-
|
|
321
|
-
|
|
311
|
+
sourceUrl?: string
|
|
312
|
+
thumbnailUrl?: string
|
|
322
313
|
mimeType: string
|
|
323
314
|
title?: string
|
|
324
315
|
}
|
|
325
316
|
|
|
326
317
|
const ImagePreview: React.FC<ImagePreviewProps> = (props) => {
|
|
327
|
-
const {
|
|
318
|
+
const { sourceUrl, thumbnailUrl, mimeType, title } = props
|
|
328
319
|
const [expanded, setExpanded] = useState(false)
|
|
329
|
-
const collapse = () => setExpanded(false)
|
|
330
|
-
|
|
331
|
-
useEffect(() => {
|
|
332
|
-
setExpanded(false)
|
|
333
|
-
}, [source])
|
|
334
320
|
|
|
335
|
-
if (expanded &&
|
|
321
|
+
if (expanded && sourceUrl) {
|
|
336
322
|
return (
|
|
337
323
|
<div className="relative">
|
|
338
324
|
<button
|
|
339
325
|
type="button"
|
|
340
326
|
className="block w-full cursor-pointer border-0 p-0 text-left appearance-none"
|
|
341
|
-
onClick={
|
|
327
|
+
onClick={() => setExpanded(false)}
|
|
342
328
|
aria-label="Close preview"
|
|
343
329
|
>
|
|
344
|
-
<img src={
|
|
330
|
+
<img src={sourceUrl} alt={title ?? ''} className="block w-full" />
|
|
345
331
|
</button>
|
|
346
|
-
<CloseButton onClose={
|
|
332
|
+
<CloseButton onClose={() => setExpanded(false)} />
|
|
347
333
|
</div>
|
|
348
334
|
)
|
|
349
335
|
}
|
|
350
336
|
|
|
351
337
|
return (
|
|
352
338
|
<CollapsedThumbnail
|
|
353
|
-
|
|
339
|
+
thumbnailUrl={thumbnailUrl}
|
|
354
340
|
mimeType={mimeType}
|
|
355
|
-
overlayIcon={
|
|
356
|
-
onClick={
|
|
341
|
+
overlayIcon={sourceUrl ? EyeSlashIcon : undefined}
|
|
342
|
+
onClick={sourceUrl ? () => setExpanded(true) : undefined}
|
|
357
343
|
/>
|
|
358
344
|
)
|
|
359
345
|
}
|
|
@@ -363,8 +349,8 @@ const CreatorCard: React.FC<CreatorCardProps> = (props) => {
|
|
|
363
349
|
const {
|
|
364
350
|
title,
|
|
365
351
|
mimeType = 'application/octet-stream',
|
|
366
|
-
|
|
367
|
-
|
|
352
|
+
thumbnailUrl,
|
|
353
|
+
sourceUrl,
|
|
368
354
|
detail,
|
|
369
355
|
amountText,
|
|
370
356
|
placeholderTitle = 'Attachment title',
|
|
@@ -380,17 +366,18 @@ const CreatorCard: React.FC<CreatorCardProps> = (props) => {
|
|
|
380
366
|
let mediaPreview: React.ReactNode
|
|
381
367
|
if (isPreview && sourceType === 'audio') {
|
|
382
368
|
mediaPreview = (
|
|
383
|
-
<AudioPreview
|
|
369
|
+
<AudioPreview key={sourceUrl} sourceUrl={sourceUrl} thumbnailUrl={thumbnailUrl} mimeType={mimeType} />
|
|
384
370
|
)
|
|
385
371
|
} else if (isPreview && sourceType === 'video') {
|
|
386
372
|
mediaPreview = (
|
|
387
|
-
<VideoPreview
|
|
373
|
+
<VideoPreview key={sourceUrl} sourceUrl={sourceUrl} thumbnailUrl={thumbnailUrl} mimeType={mimeType} />
|
|
388
374
|
)
|
|
389
375
|
} else if (isPreview && sourceType === 'image') {
|
|
390
376
|
mediaPreview = (
|
|
391
377
|
<ImagePreview
|
|
392
|
-
|
|
393
|
-
|
|
378
|
+
key={sourceUrl}
|
|
379
|
+
sourceUrl={sourceUrl}
|
|
380
|
+
thumbnailUrl={thumbnailUrl}
|
|
394
381
|
mimeType={mimeType}
|
|
395
382
|
title={title}
|
|
396
383
|
/>
|
|
@@ -403,7 +390,7 @@ const CreatorCard: React.FC<CreatorCardProps> = (props) => {
|
|
|
403
390
|
: LockIcon
|
|
404
391
|
mediaPreview = (
|
|
405
392
|
<CollapsedThumbnail
|
|
406
|
-
|
|
393
|
+
thumbnailUrl={thumbnailUrl}
|
|
407
394
|
mimeType={mimeType}
|
|
408
395
|
overlayIcon={lockedOverlayIcon}
|
|
409
396
|
darkOverlay
|
|
@@ -412,7 +399,7 @@ const CreatorCard: React.FC<CreatorCardProps> = (props) => {
|
|
|
412
399
|
}
|
|
413
400
|
|
|
414
401
|
return (
|
|
415
|
-
<div className="relative w-[280px] select-none overflow-hidden rounded-[24px] bg-white shadow-
|
|
402
|
+
<div className="relative w-[280px] select-none overflow-hidden rounded-[24px] bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]">
|
|
416
403
|
{onDismiss && (
|
|
417
404
|
<button
|
|
418
405
|
type="button"
|
|
@@ -5,12 +5,11 @@ import { isDevBuild } from '../../../utils/isDevBuild'
|
|
|
5
5
|
import { renderTypeIcon } from '../utils/icons'
|
|
6
6
|
import { getSourceType, type AttachmentSourceType } from '../utils/mimeType'
|
|
7
7
|
|
|
8
|
-
const getPlayerBg = (sourceType: AttachmentSourceType, poster?: string) =>
|
|
9
|
-
sourceType === 'audio' && !poster ? 'bg-black/5' : 'bg-black'
|
|
8
|
+
const getPlayerBg = (sourceType: AttachmentSourceType, poster?: string) => {
|
|
9
|
+
return sourceType === 'audio' && !poster ? 'bg-black/5' : 'bg-black'
|
|
10
|
+
}
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent
|
|
13
|
-
): number {
|
|
12
|
+
const getClientXFromEvent = ( e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent ): number => {
|
|
14
13
|
if ('touches' in e) {
|
|
15
14
|
return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0
|
|
16
15
|
}
|
|
@@ -71,10 +70,6 @@ const MediaPlayer: React.FC<MediaPlayerProps> = ({
|
|
|
71
70
|
const trackRef = useRef<HTMLDivElement>(null)
|
|
72
71
|
const rafRef = useRef<number | null>(null)
|
|
73
72
|
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
setManualPlayRequired(false)
|
|
76
|
-
setInitialLoad(true)
|
|
77
|
-
}, [source])
|
|
78
73
|
|
|
79
74
|
useEffect(() => {
|
|
80
75
|
if (!playing) {
|
|
@@ -197,14 +192,15 @@ const MediaPlayer: React.FC<MediaPlayerProps> = ({
|
|
|
197
192
|
if (controls) setPlaying((p) => !p)
|
|
198
193
|
}}
|
|
199
194
|
>
|
|
200
|
-
{poster
|
|
195
|
+
{/* For audio, poster persists as a visual background. For video, hide once loaded. */}
|
|
196
|
+
{poster && (sourceType === 'audio' || initialLoad) && (
|
|
201
197
|
<img
|
|
202
198
|
src={poster}
|
|
203
199
|
alt=""
|
|
204
200
|
className="absolute inset-0 h-full w-full object-cover"
|
|
205
201
|
/>
|
|
206
202
|
)}
|
|
207
|
-
{!poster && (
|
|
203
|
+
{!poster && (sourceType === 'audio' || initialLoad) && (
|
|
208
204
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
209
205
|
{renderTypeIcon(mimeType, {
|
|
210
206
|
className: 'size-12 text-black/20',
|
|
@@ -212,11 +208,6 @@ const MediaPlayer: React.FC<MediaPlayerProps> = ({
|
|
|
212
208
|
})}
|
|
213
209
|
</div>
|
|
214
210
|
)}
|
|
215
|
-
{initialLoad && poster && (
|
|
216
|
-
<div className="absolute inset-0 z-20">
|
|
217
|
-
<img src={poster} alt="" className="h-full w-full object-cover" />
|
|
218
|
-
</div>
|
|
219
|
-
)}
|
|
220
211
|
<div className="absolute inset-0">
|
|
221
212
|
{sourceType === 'audio' ? (
|
|
222
213
|
<audio
|
|
@@ -242,7 +233,6 @@ const MediaPlayer: React.FC<MediaPlayerProps> = ({
|
|
|
242
233
|
<video
|
|
243
234
|
ref={playerRef as React.RefObject<HTMLVideoElement>}
|
|
244
235
|
src={source}
|
|
245
|
-
poster={poster}
|
|
246
236
|
loop={loop}
|
|
247
237
|
muted={muted}
|
|
248
238
|
playsInline
|