@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.30.0",
3
+ "version": "1.31.0-rc-1776677746",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -207,11 +207,9 @@ const ChannelViewInner: React.FC<{
207
207
  onReportParticipantClick?: () => void
208
208
  showStarButton?: boolean
209
209
  chatbotVotingEnabled?: boolean
210
- onAttachmentUnlock?: (
211
- message: LocalMessage,
212
- channel: ChannelType
213
- ) => Promise<LockedAttachmentSource>
214
- onAttachmentDownload?: (message: LocalMessage, channel: ChannelType) => void
210
+ onAttachmentUnlockClick?: (message: LocalMessage, channel: ChannelType) => void
211
+ onAttachmentDownloadClick?: (message: LocalMessage, channel: ChannelType) => void
212
+ onAttachmentUnlocked?: (message: LocalMessage, channel: ChannelType) => LockedAttachmentSource
215
213
  renderChannelBanner?: () => React.ReactNode
216
214
  customProfileContent?: React.ReactNode
217
215
  customChannelActions?: React.ReactNode
@@ -232,8 +230,9 @@ const ChannelViewInner: React.FC<{
232
230
  onReportParticipantClick,
233
231
  showStarButton = false,
234
232
  chatbotVotingEnabled = false,
235
- onAttachmentUnlock,
236
- onAttachmentDownload,
233
+ onAttachmentUnlockClick,
234
+ onAttachmentDownloadClick,
235
+ onAttachmentUnlocked,
237
236
  renderChannelBanner,
238
237
  customProfileContent,
239
238
  customChannelActions,
@@ -289,8 +288,9 @@ const ChannelViewInner: React.FC<{
289
288
  <CustomMessage
290
289
  {...props}
291
290
  chatbotVotingEnabled={chatbotVotingEnabled}
292
- onAttachmentUnlock={onAttachmentUnlock}
293
- onAttachmentDownload={onAttachmentDownload}
291
+ onAttachmentUnlockClick={onAttachmentUnlockClick}
292
+ onAttachmentDownloadClick={onAttachmentDownloadClick}
293
+ onAttachmentUnlocked={onAttachmentUnlocked}
294
294
  />
295
295
  )
296
296
 
@@ -378,8 +378,9 @@ export const ChannelView = React.memo<ChannelViewProps>(
378
378
  onMessageSent,
379
379
  showStarButton = false,
380
380
  chatbotVotingEnabled = false,
381
- onAttachmentUnlock,
382
- onAttachmentDownload,
381
+ onAttachmentUnlockClick,
382
+ onAttachmentDownloadClick,
383
+ onAttachmentUnlocked,
383
384
  renderChannelBanner,
384
385
  customProfileContent,
385
386
  customChannelActions,
@@ -458,8 +459,9 @@ export const ChannelView = React.memo<ChannelViewProps>(
458
459
  onReportParticipantClick={onReportParticipantClick}
459
460
  showStarButton={showStarButton}
460
461
  chatbotVotingEnabled={chatbotVotingEnabled}
461
- onAttachmentUnlock={onAttachmentUnlock}
462
- onAttachmentDownload={onAttachmentDownload}
462
+ onAttachmentUnlockClick={onAttachmentUnlockClick}
463
+ onAttachmentDownloadClick={onAttachmentDownloadClick}
464
+ onAttachmentUnlocked={onAttachmentUnlocked}
463
465
  renderChannelBanner={renderChannelBanner}
464
466
  customProfileContent={customProfileContent}
465
467
  customChannelActions={customChannelActions}
@@ -2,13 +2,8 @@ import '../../stream-custom-data'
2
2
 
3
3
  import type { Meta, StoryFn } from '@storybook/react'
4
4
  import React, { useEffect } from 'react'
5
- import {
6
- Channel as ChannelType,
7
- LocalMessage,
8
- QueryChannelAPIResponse,
9
- StreamChat,
10
- } from 'stream-chat'
11
- import { Channel, Chat, MessageList, Window } from 'stream-chat-react'
5
+ import { Channel as ChannelType, QueryChannelAPIResponse, StreamChat, } from 'stream-chat'
6
+ import { Channel, Chat, MessageList, MessageUIComponentProps, Window } from 'stream-chat-react'
12
7
 
13
8
  import {
14
9
  currentUserArgType,
@@ -140,24 +135,21 @@ const TemplateInner: React.FC<{
140
135
  const isVisitor = currentUser.id === storyUsers.visitor.id
141
136
 
142
137
  const MessageComponent = React.useMemo(() => {
143
- const handleAttachmentUnlock = async () => {
144
- await new Promise((resolve) => setTimeout(resolve, 1000))
145
- return { source: '/video-source.mp4' }
138
+ const handleAttachmentUnlockClicked = () => {
139
+ alert('Unlocking...')
146
140
  }
147
141
 
148
- const handleAttachmentDownload = (m: LocalMessage) => {
149
- alert(`Download: ${m.metadata?.attachment_title}`)
142
+ const handleAttachmentDownloadClicked = () => {
143
+ alert(`Downloading...`)
150
144
  }
151
145
 
152
- // eslint-disable-next-line react/display-name
153
- return function (props) {
146
+ return function CustomMessageComponent(props: MessageUIComponentProps) {
154
147
  return (
155
148
  <CustomMessage
156
149
  {...props}
157
- onAttachmentUnlock={isVisitor ? handleAttachmentUnlock : undefined}
158
- onAttachmentDownload={
159
- isVisitor ? handleAttachmentDownload : undefined
160
- }
150
+ onAttachmentUnlockClick={isVisitor ? () => handleAttachmentUnlockClicked() : undefined}
151
+ onAttachmentDownloadClick={isVisitor ? () => handleAttachmentDownloadClicked() : undefined}
152
+ onAttachmentUnlocked={undefined}
161
153
  />
162
154
  )
163
155
  }
@@ -311,8 +303,8 @@ MixedTags.args = {
311
303
  ],
312
304
  }
313
305
 
314
- export const PaidAttachment: StoryFn<TemplateProps> = Template.bind({})
315
- PaidAttachment.args = {
306
+ export const LockedAttachment: StoryFn<TemplateProps> = Template.bind({})
307
+ LockedAttachment.args = {
316
308
  messages: [
317
309
  {
318
310
  id: 'msg-1',
@@ -37,18 +37,24 @@ import LockedAttachment, { type LockedAttachmentSource } from '../LockedAttachme
37
37
  import { MessageTag, isAttachmentMessage, isChatbotMessage, isTipOnlyMessage } from './MessageTag'
38
38
  import { MessageVoteButtons } from './MessageVoteButtons'
39
39
 
40
- type CustomMessageWithContextProps = MessageContextValue & {
40
+ type CustomMessageProps = {
41
41
  chatbotVotingEnabled?: boolean
42
- onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<LockedAttachmentSource>
43
- onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
42
+ onAttachmentUnlockClick?: (message: LocalMessage, channel: Channel) => void
43
+ onAttachmentDownloadClick?: (message: LocalMessage, channel: Channel) => void
44
+ onAttachmentUnlocked?: (message: LocalMessage, channel: Channel) => LockedAttachmentSource
44
45
  }
45
46
 
47
+ type CustomMessageUIComponentProps = MessageUIComponentProps & CustomMessageProps
48
+
49
+ type CustomMessageWithContextProps = MessageContextValue & CustomMessageProps
50
+
46
51
  const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
47
52
  const {
48
53
  additionalMessageInputProps,
49
54
  chatbotVotingEnabled,
50
- onAttachmentUnlock,
51
- onAttachmentDownload,
55
+ onAttachmentUnlockClick,
56
+ onAttachmentDownloadClick,
57
+ onAttachmentUnlocked,
52
58
  editing,
53
59
  endOfGroup,
54
60
  firstOfGroup,
@@ -205,13 +211,14 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
205
211
  <div className={classNames("flex flex-col gap-1", isMine ? "items-end" : "items-start")}>
206
212
  <LockedAttachment
207
213
  title={message.metadata?.attachment_title}
208
- mimeType={message.metadata?.attachment_mime_type}
209
- thumbnail={message.metadata?.attachment_thumbnail}
214
+ mimeType={message.metadata?.attachment_mime_type ?? 'application/octet-stream'}
215
+ thumbnailUrl={message.metadata?.attachment_thumbnail}
210
216
  amountText={message.metadata?.amount_text}
211
217
  detail={message.metadata?.attachment_detail}
212
218
  paymentStatus={message.metadata?.payment_status}
213
- onUnlock={onAttachmentUnlock ? () => onAttachmentUnlock(message, channel) : undefined}
214
- onDownload={onAttachmentDownload ? () => onAttachmentDownload(message, channel) : undefined}
219
+ onUnlockClick={onAttachmentUnlockClick ? () => onAttachmentUnlockClick(message, channel) : undefined}
220
+ onDownloadClick={onAttachmentDownloadClick ? () => onAttachmentDownloadClick(message, channel) : undefined}
221
+ onUnlocked={onAttachmentUnlocked ? () => onAttachmentUnlocked(message, channel) : undefined}
215
222
  />
216
223
  {message.text && (
217
224
  <div className="str-chat__message-bubble-wrapper">
@@ -287,19 +294,14 @@ const MemoizedCustomMessage = React.memo(
287
294
  CustomMessageWithContext,
288
295
  (prev, next) => {
289
296
  if (prev.chatbotVotingEnabled !== next.chatbotVotingEnabled) return false
290
- if (prev.onAttachmentUnlock !== next.onAttachmentUnlock) return false
291
- if (prev.onAttachmentDownload !== next.onAttachmentDownload) return false
297
+ if (prev.onAttachmentUnlockClick !== next.onAttachmentUnlockClick) return false
298
+ if (prev.onAttachmentDownloadClick !== next.onAttachmentDownloadClick) return false
299
+ if (prev.onAttachmentUnlocked !== next.onAttachmentUnlocked) return false
292
300
  return areMessageUIPropsEqual(prev, next)
293
301
  }
294
302
  ) as typeof CustomMessageWithContext
295
303
 
296
- export const CustomMessage = (
297
- props: MessageUIComponentProps & {
298
- chatbotVotingEnabled?: boolean
299
- onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<LockedAttachmentSource>
300
- onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
301
- }
302
- ) => {
304
+ export const CustomMessage = (props: CustomMessageUIComponentProps) => {
303
305
  const messageContext = useMessageContext('CustomMessage')
304
306
  return <MemoizedCustomMessage {...messageContext} {...props} />
305
307
  }
@@ -22,82 +22,46 @@ const meta: Meta = {
22
22
  }
23
23
  export default meta
24
24
 
25
- const withDelay = <T,>(fn: () => Promise<T> | T) => async (): Promise<T> => {
26
- await new Promise((resolve) => setTimeout(resolve, 1000))
27
- return fn()
28
- }
29
-
30
25
  const VARIANTS = [
31
26
  {
32
27
  label: 'Video',
33
28
  title: "Alicia's Workout Plan",
34
29
  mimeType: 'video/mp4',
35
30
  detail: '1:20',
36
- thumbnail: VIDEO_THUMBNAIL_BLURRED,
37
- source: VIDEO_SOURCE,
31
+ thumbnailUrl: VIDEO_THUMBNAIL_BLURRED,
32
+ sourceUrl: VIDEO_SOURCE,
38
33
  },
39
34
  {
40
35
  label: 'Audio',
41
36
  title: 'Morning Meditation',
42
37
  mimeType: 'audio/mpeg',
43
38
  detail: '4:35',
44
- thumbnail: AUDIO_THUMBNAIL,
45
- source: AUDIO_SOURCE,
39
+ thumbnailUrl: AUDIO_THUMBNAIL,
40
+ sourceUrl: AUDIO_SOURCE,
46
41
  },
47
42
  {
48
43
  label: 'Image',
49
44
  title: 'Picture of my cat',
50
45
  mimeType: 'image/jpeg',
51
46
  detail: '3.2 MB',
52
- thumbnail: IMAGE_THUMBNAIL_BLURRED,
53
- source: IMAGE_SOURCE,
47
+ thumbnailUrl: IMAGE_THUMBNAIL_BLURRED,
48
+ sourceUrl: IMAGE_SOURCE,
54
49
  },
55
50
  {
56
51
  label: 'Document',
57
52
  title: 'Strength Training Guide',
58
53
  mimeType: 'application/zip',
59
54
  detail: '14 files',
60
- thumbnail: DOCUMENT_THUMBNAIL,
61
- source: DOCUMENT_SOURCE,
55
+ thumbnailUrl: DOCUMENT_THUMBNAIL,
56
+ sourceUrl: DOCUMENT_SOURCE,
62
57
  },
63
58
  {
64
59
  label: 'Unknown',
65
60
  title: 'Unknown Attachment',
66
61
  mimeType: 'application/octet-stream',
67
62
  detail: undefined,
68
- thumbnail: undefined,
69
- source: DOCUMENT_SOURCE,
70
- },
71
- ]
72
-
73
- const NO_THUMBNAIL_VARIANTS = [
74
- {
75
- label: 'Video',
76
- title: "Alicia's Workout Plan",
77
- mimeType: 'video/mp4',
78
- detail: '1:20',
79
- source: VIDEO_SOURCE,
80
- },
81
- {
82
- label: 'Audio',
83
- title: 'Morning Meditation',
84
- mimeType: 'audio/mpeg',
85
- detail: '4:35',
86
- source: AUDIO_SOURCE,
87
- },
88
- {
89
- label: 'Image',
90
- title: 'Picture of my cat',
91
- mimeType: 'image/jpeg',
92
- detail: '3.2 MB',
93
- source: IMAGE_SOURCE,
94
- },
95
- {
96
- label: 'Document',
97
- title: 'Strength Training Guide',
98
- mimeType: 'application/zip',
99
- detail: '14 files',
100
- source: DOCUMENT_SOURCE,
63
+ thumbnailUrl: undefined,
64
+ sourceUrl: DOCUMENT_SOURCE,
101
65
  },
102
66
  ]
103
67
 
@@ -107,9 +71,7 @@ const Table = ({ children }: { children: React.ReactNode }) => (
107
71
  </div>
108
72
  )
109
73
 
110
- const TableHead = ({
111
- variants,
112
- }: {
74
+ const TableHead = ({ variants, }: {
113
75
  variants: { label: string; mimeType: string }[]
114
76
  }) => (
115
77
  <thead>
@@ -132,57 +94,60 @@ export const Visitor: StoryFn = () => (
132
94
  <TableHead variants={VARIANTS} />
133
95
  <tbody>
134
96
  <tr>
135
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
97
+ <td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
136
98
  Locked
137
99
  </td>
138
- {VARIANTS.map(({ title, mimeType, detail, thumbnail, source }) => (
100
+ {VARIANTS.map(({ title, mimeType, detail, thumbnailUrl }) => (
139
101
  <td key={mimeType} className="align-top">
140
102
  <LockedAttachment
141
103
  title={title}
142
104
  amountText="AU$9.99"
143
- thumbnail={thumbnail}
105
+ thumbnailUrl={thumbnailUrl}
144
106
  mimeType={mimeType}
145
107
  detail={detail}
146
- onUnlock={withDelay(() => ({ source }))}
147
- onDownload={() => {}}
108
+ onUnlockClick={() => {}}
109
+ onDownloadClick={() => {}}
110
+ onUnlocked={undefined}
148
111
  />
149
112
  </td>
150
113
  ))}
151
114
  </tr>
152
115
  <tr>
153
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
116
+ <td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
154
117
  Purchased
155
118
  </td>
156
- {VARIANTS.map(({ title, mimeType, detail, thumbnail, source }) => (
119
+ {VARIANTS.map(({ title, mimeType, detail, thumbnailUrl }) => (
157
120
  <td key={mimeType} className="align-top">
158
121
  <LockedAttachment
159
122
  title={title}
160
123
  amountText="AU$9.99"
161
- thumbnail={thumbnail}
124
+ thumbnailUrl={thumbnailUrl}
162
125
  mimeType={mimeType}
163
126
  detail={detail}
164
127
  paymentStatus="paid"
165
- onUnlock={withDelay(() => ({ source }))}
166
- onDownload={() => {}}
128
+ onUnlockClick={() => {}}
129
+ onDownloadClick={() => {}}
130
+ onUnlocked={undefined}
167
131
  />
168
132
  </td>
169
133
  ))}
170
134
  </tr>
171
135
  <tr>
172
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
136
+ <td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
173
137
  Unlocked
174
138
  </td>
175
- {VARIANTS.map(({ title, mimeType, detail, thumbnail, source }) => (
139
+ {VARIANTS.map(({ title, mimeType, detail, thumbnailUrl, sourceUrl }) => (
176
140
  <td key={mimeType} className="align-top">
177
141
  <LockedAttachment
178
142
  title={title}
179
- thumbnail={thumbnail}
180
- source={source}
143
+ thumbnailUrl={thumbnailUrl}
181
144
  mimeType={mimeType}
182
145
  detail={detail}
183
146
  amountText="AU$9.99"
184
147
  paymentStatus="paid"
185
- onDownload={() => {}}
148
+ onUnlockClick={() => {}}
149
+ onDownloadClick={() => {}}
150
+ onUnlocked={() => ({ sourceUrl })}
186
151
  />
187
152
  </td>
188
153
  ))}
@@ -196,32 +161,33 @@ export const Creator: StoryFn = () => (
196
161
  <TableHead variants={VARIANTS} />
197
162
  <tbody>
198
163
  <tr>
199
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
164
+ <td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
200
165
  Preview
201
166
  </td>
202
- {VARIANTS.map(({ mimeType, detail, thumbnail, source }) => (
167
+ {VARIANTS.map(({ mimeType, detail, thumbnailUrl, sourceUrl }) => (
203
168
  <td key={mimeType} className="align-top">
204
169
  <LockedAttachment
205
- isPreview
206
- thumbnail={thumbnail}
207
- source={source}
170
+ isPreview={true}
171
+ thumbnailUrl={thumbnailUrl}
172
+ sourceUrl={sourceUrl}
208
173
  mimeType={mimeType}
209
174
  detail={detail}
210
175
  placeholderAmountText="A$0.00"
176
+ onDismiss={undefined}
211
177
  />
212
178
  </td>
213
179
  ))}
214
180
  </tr>
215
181
  <tr>
216
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
182
+ <td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
217
183
  Pending
218
184
  </td>
219
- {VARIANTS.map(({ title, mimeType, detail, thumbnail, source }) => (
185
+ {VARIANTS.map(({ title, mimeType, detail, thumbnailUrl, sourceUrl }) => (
220
186
  <td key={mimeType} className="align-top">
221
187
  <LockedAttachment
222
188
  title={title}
223
- thumbnail={thumbnail}
224
- source={source}
189
+ thumbnailUrl={thumbnailUrl}
190
+ sourceUrl={sourceUrl}
225
191
  mimeType={mimeType}
226
192
  detail={detail}
227
193
  amountText="AU$9.99"
@@ -231,37 +197,38 @@ export const Creator: StoryFn = () => (
231
197
  ))}
232
198
  </tr>
233
199
  <tr>
234
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
200
+ <td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
235
201
  Sent
236
202
  </td>
237
- {VARIANTS.map(({ title, mimeType, detail, thumbnail, source }) => (
203
+ {VARIANTS.map(({ title, mimeType, detail, thumbnailUrl, sourceUrl }) => (
238
204
  <td key={mimeType} className="align-top">
239
205
  <LockedAttachment
240
-
241
206
  title={title}
242
- thumbnail={thumbnail}
243
- source={source}
207
+ thumbnailUrl={thumbnailUrl}
208
+ sourceUrl={sourceUrl}
244
209
  mimeType={mimeType}
245
210
  detail={detail}
246
211
  amountText="AU$9.99"
212
+ onDismiss={undefined}
247
213
  />
248
214
  </td>
249
215
  ))}
250
216
  </tr>
251
217
  <tr>
252
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
218
+ <td className="text-xs text-right font-medium text-black/40 pr-4 align-top pt-2">
253
219
  Sold
254
220
  </td>
255
- {VARIANTS.map(({ title, mimeType, detail, thumbnail, source }) => (
221
+ {VARIANTS.map(({ title, mimeType, detail, thumbnailUrl, sourceUrl }) => (
256
222
  <td key={mimeType} className="align-top">
257
223
  <LockedAttachment
258
224
  title={title}
259
- thumbnail={thumbnail}
260
- source={source}
225
+ thumbnailUrl={thumbnailUrl}
226
+ sourceUrl={sourceUrl}
261
227
  mimeType={mimeType}
262
228
  detail={detail}
263
229
  amountText="AU$9.99"
264
230
  paymentStatus="paid"
231
+ onDismiss={undefined}
265
232
  />
266
233
  </td>
267
234
  ))}
@@ -270,61 +237,3 @@ export const Creator: StoryFn = () => (
270
237
  </Table>
271
238
  )
272
239
 
273
- export const NoThumbnail: StoryFn = () => (
274
- <Table>
275
- <TableHead variants={NO_THUMBNAIL_VARIANTS} />
276
- <tbody>
277
- <tr>
278
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
279
- Creator
280
- </td>
281
- {NO_THUMBNAIL_VARIANTS.map(({ title, mimeType, detail, source }) => (
282
- <td key={mimeType} className="align-top">
283
- <LockedAttachment
284
- title={title}
285
- source={source}
286
- mimeType={mimeType}
287
- detail={detail}
288
- amountText="AU$9.99"
289
- />
290
- </td>
291
- ))}
292
- </tr>
293
- <tr>
294
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
295
- Locked
296
- </td>
297
- {NO_THUMBNAIL_VARIANTS.map(({ title, mimeType, detail, source }) => (
298
- <td key={mimeType} className="align-top">
299
- <LockedAttachment
300
- title={title}
301
- amountText="AU$9.99"
302
- mimeType={mimeType}
303
- detail={detail}
304
- onUnlock={withDelay(() => ({ source }))}
305
- onDownload={() => {}}
306
- />
307
- </td>
308
- ))}
309
- </tr>
310
- <tr>
311
- <td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">
312
- Unlocked
313
- </td>
314
- {NO_THUMBNAIL_VARIANTS.map(({ title, mimeType, detail, source }) => (
315
- <td key={mimeType} className="align-top">
316
- <LockedAttachment
317
- title={title}
318
- source={source}
319
- mimeType={mimeType}
320
- detail={detail}
321
- amountText="AU$9.99"
322
- paymentStatus="paid"
323
- onDownload={() => {}}
324
- />
325
- </td>
326
- ))}
327
- </tr>
328
- </tbody>
329
- </Table>
330
- )