@linktr.ee/messaging-react 1.26.1 → 1.28.0-rc-1776225927
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-D38dWn2X.js +318 -0
- package/dist/Creator-D38dWn2X.js.map +1 -0
- package/dist/MediaPlayer-DE9MC6k6.js +599 -0
- package/dist/MediaPlayer-DE9MC6k6.js.map +1 -0
- package/dist/Preview-DqAv16NS.js +87 -0
- package/dist/Preview-DqAv16NS.js.map +1 -0
- package/dist/Visitor-BG-9-3HU.js +199 -0
- package/dist/Visitor-BG-9-3HU.js.map +1 -0
- package/dist/dash.all.min-Duv4lvGS.js +18858 -0
- package/dist/dash.all.min-Duv4lvGS.js.map +1 -0
- package/dist/hls-Bogc7CBn.js +21710 -0
- package/dist/hls-Bogc7CBn.js.map +1 -0
- package/dist/index-Da-xN4Yq.js +16142 -0
- package/dist/index-Da-xN4Yq.js.map +1 -0
- package/dist/index-Dj9rqWcU.js +69 -0
- package/dist/index-Dj9rqWcU.js.map +1 -0
- package/dist/index.d.ts +74 -10
- package/dist/index.js +979 -934
- package/dist/index.js.map +1 -1
- package/dist/mixin-B6jYfIcp.js +808 -0
- package/dist/mixin-B6jYfIcp.js.map +1 -0
- package/dist/react-BxlQMOfz.js +419 -0
- package/dist/react-BxlQMOfz.js.map +1 -0
- package/dist/react-COAP-MIW.js +377 -0
- package/dist/react-COAP-MIW.js.map +1 -0
- package/dist/react-Cn4WlMcl.js +3108 -0
- package/dist/react-Cn4WlMcl.js.map +1 -0
- package/dist/react-CwTJArKY.js +459 -0
- package/dist/react-CwTJArKY.js.map +1 -0
- package/dist/react-DkfS_atT.js +373 -0
- package/dist/react-DkfS_atT.js.map +1 -0
- package/dist/react-Pea5fum1.js +286 -0
- package/dist/react-Pea5fum1.js.map +1 -0
- package/dist/react-RiBbsUDd.js +534 -0
- package/dist/react-RiBbsUDd.js.map +1 -0
- package/dist/react-dS1WBxxz.js +238 -0
- package/dist/react-dS1WBxxz.js.map +1 -0
- package/package.json +2 -1
- package/src/components/ChannelView.tsx +12 -2
- package/src/components/CustomMessage/CustomMessage.stories.tsx +173 -41
- package/src/components/CustomMessage/MessageTag.tsx +5 -0
- package/src/components/CustomMessage/index.tsx +43 -4
- package/src/components/LockedAttachment/LockedAttachment.stories.tsx +343 -0
- package/src/components/LockedAttachment/components/Creator.tsx +469 -0
- package/src/components/LockedAttachment/components/MediaPlayer.tsx +359 -0
- package/src/components/LockedAttachment/components/Visitor.tsx +356 -0
- package/src/components/LockedAttachment/index.tsx +39 -0
- package/src/components/LockedAttachment/types.ts +17 -0
- package/src/components/LockedAttachment/utils/icons.ts +53 -0
- package/src/components/LockedAttachment/utils/mimeType.test.ts +119 -0
- package/src/components/LockedAttachment/utils/mimeType.ts +37 -0
- package/src/components/ParticipantPicker/index.tsx +8 -1
- package/src/hooks/useParticipants.ts +3 -2
- package/src/index.ts +4 -0
- package/src/stories/decorators/storyUser.tsx +37 -0
- package/src/stream-custom-data.ts +9 -3
- package/src/types.ts +20 -1
- package/src/utils/isDevBuild.ts +10 -0
|
@@ -1,37 +1,38 @@
|
|
|
1
|
+
import '../../stream-custom-data'
|
|
2
|
+
|
|
1
3
|
import type { Meta, StoryFn } from '@storybook/react'
|
|
2
4
|
import React, { useEffect } from 'react'
|
|
3
5
|
import {
|
|
4
6
|
Channel as ChannelType,
|
|
7
|
+
LocalMessage,
|
|
5
8
|
QueryChannelAPIResponse,
|
|
6
9
|
StreamChat,
|
|
7
10
|
} from 'stream-chat'
|
|
8
11
|
import { Channel, Chat, MessageList, Window } from 'stream-chat-react'
|
|
9
12
|
|
|
10
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
currentUserArgType,
|
|
15
|
+
StoryUser,
|
|
16
|
+
storyUsers,
|
|
17
|
+
} from '../../stories/decorators/storyUser'
|
|
11
18
|
|
|
12
19
|
import { CustomMessage } from './index'
|
|
13
20
|
|
|
14
21
|
const meta: Meta = {
|
|
15
22
|
title: 'Components/CustomMessage',
|
|
16
23
|
component: CustomMessage,
|
|
24
|
+
argTypes: currentUserArgType,
|
|
25
|
+
args: { currentUser: storyUsers.creator },
|
|
17
26
|
parameters: {
|
|
18
27
|
layout: 'fullscreen',
|
|
19
28
|
},
|
|
20
29
|
}
|
|
21
30
|
export default meta
|
|
22
31
|
|
|
23
|
-
const mockUser = {
|
|
24
|
-
id: 'storybook-user',
|
|
25
|
-
name: 'Storybook User',
|
|
26
|
-
image: 'https://i.pravatar.cc/150?img=1',
|
|
27
|
-
}
|
|
28
|
-
|
|
29
32
|
const createMockChannel = async (
|
|
30
33
|
client: StreamChat,
|
|
31
34
|
messages: TemplateProps['messages']
|
|
32
35
|
) => {
|
|
33
|
-
const participant = mockParticipants[0]
|
|
34
|
-
|
|
35
36
|
const mockMessages = messages.map((msg, index) => ({
|
|
36
37
|
...msg,
|
|
37
38
|
type: msg.type ?? ('regular' as const),
|
|
@@ -50,7 +51,7 @@ const createMockChannel = async (
|
|
|
50
51
|
}))
|
|
51
52
|
|
|
52
53
|
const channelData = {
|
|
53
|
-
members: [
|
|
54
|
+
members: [storyUsers.creator.id, storyUsers.visitor.id],
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
const channel = client.channel(
|
|
@@ -63,8 +64,14 @@ const createMockChannel = async (
|
|
|
63
64
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
64
65
|
channel.state.messages = mockMessages as unknown as any[]
|
|
65
66
|
channel.state.members = {
|
|
66
|
-
[
|
|
67
|
-
|
|
67
|
+
[storyUsers.creator.id]: {
|
|
68
|
+
user: storyUsers.creator,
|
|
69
|
+
user_id: storyUsers.creator.id,
|
|
70
|
+
},
|
|
71
|
+
[storyUsers.visitor.id]: {
|
|
72
|
+
user: storyUsers.visitor,
|
|
73
|
+
user_id: storyUsers.visitor.id,
|
|
74
|
+
},
|
|
68
75
|
}
|
|
69
76
|
return {
|
|
70
77
|
channel: channelData,
|
|
@@ -86,24 +93,36 @@ const createMockChannel = async (
|
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
interface TemplateProps {
|
|
96
|
+
currentUser: StoryUser
|
|
89
97
|
messages: Array<{
|
|
90
98
|
id: string
|
|
91
99
|
text: string
|
|
92
|
-
user:
|
|
100
|
+
user: StoryUser
|
|
93
101
|
type?: 'regular' | 'system'
|
|
94
102
|
attachments?: Array<Record<string, unknown>>
|
|
95
103
|
metadata?: {
|
|
96
|
-
custom_type?:
|
|
104
|
+
custom_type?:
|
|
105
|
+
| 'MESSAGE_TIP'
|
|
106
|
+
| 'MESSAGE_PAID'
|
|
107
|
+
| 'MESSAGE_CHATBOT'
|
|
108
|
+
| 'MESSAGE_ATTACHMENT'
|
|
97
109
|
amount_text?: string
|
|
110
|
+
attachment_title?: string
|
|
111
|
+
attachment_mime_type?: string
|
|
112
|
+
attachment_thumbnail?: string
|
|
113
|
+
attachment_detail?: string
|
|
98
114
|
}
|
|
99
115
|
}>
|
|
100
116
|
}
|
|
101
117
|
|
|
102
|
-
const
|
|
118
|
+
const TemplateInner: React.FC<{
|
|
119
|
+
currentUser: StoryUser
|
|
120
|
+
messages: TemplateProps['messages']
|
|
121
|
+
}> = ({ currentUser, messages }) => {
|
|
103
122
|
const [client] = React.useState(() => {
|
|
104
123
|
const c = new StreamChat('mock-api-key', { allowServerSideConnect: true })
|
|
105
|
-
c.userID =
|
|
106
|
-
c.user =
|
|
124
|
+
c.userID = currentUser.id
|
|
125
|
+
c.user = currentUser
|
|
107
126
|
return c
|
|
108
127
|
})
|
|
109
128
|
|
|
@@ -113,6 +132,32 @@ const Template: StoryFn<TemplateProps> = ({ messages }) => {
|
|
|
113
132
|
createMockChannel(client, messages).then(setChannel)
|
|
114
133
|
}, [client, messages])
|
|
115
134
|
|
|
135
|
+
const isVisitor = currentUser.id === storyUsers.visitor.id
|
|
136
|
+
|
|
137
|
+
const MessageComponent = React.useMemo(() => {
|
|
138
|
+
const handleAttachmentUnlock = async () => {
|
|
139
|
+
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
140
|
+
return { source: '/video-source.mp4' }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const handleAttachmentDownload = (m: LocalMessage) => {
|
|
144
|
+
alert(`Download: ${m.metadata?.attachment_title}`)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// eslint-disable-next-line react/display-name
|
|
148
|
+
return function (props) {
|
|
149
|
+
return (
|
|
150
|
+
<CustomMessage
|
|
151
|
+
{...props}
|
|
152
|
+
onAttachmentUnlock={isVisitor ? handleAttachmentUnlock : undefined}
|
|
153
|
+
onAttachmentDownload={
|
|
154
|
+
isVisitor ? handleAttachmentDownload : undefined
|
|
155
|
+
}
|
|
156
|
+
/>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
}, [isVisitor])
|
|
160
|
+
|
|
116
161
|
if (!channel) {
|
|
117
162
|
return <div className="p-4">Loading...</div>
|
|
118
163
|
}
|
|
@@ -120,7 +165,7 @@ const Template: StoryFn<TemplateProps> = ({ messages }) => {
|
|
|
120
165
|
return (
|
|
121
166
|
<Chat client={client}>
|
|
122
167
|
<div className="h-screen w-full bg-white">
|
|
123
|
-
<Channel channel={channel} Message={
|
|
168
|
+
<Channel channel={channel} Message={MessageComponent}>
|
|
124
169
|
<Window>
|
|
125
170
|
<MessageList />
|
|
126
171
|
</Window>
|
|
@@ -130,81 +175,168 @@ const Template: StoryFn<TemplateProps> = ({ messages }) => {
|
|
|
130
175
|
)
|
|
131
176
|
}
|
|
132
177
|
|
|
133
|
-
const
|
|
178
|
+
const Template: StoryFn<TemplateProps> = ({
|
|
179
|
+
currentUser = storyUsers.creator,
|
|
180
|
+
messages,
|
|
181
|
+
}) => (
|
|
182
|
+
<TemplateInner
|
|
183
|
+
key={currentUser.id}
|
|
184
|
+
currentUser={currentUser}
|
|
185
|
+
messages={messages}
|
|
186
|
+
/>
|
|
187
|
+
)
|
|
134
188
|
|
|
135
189
|
export const Default: StoryFn<TemplateProps> = Template.bind({})
|
|
136
190
|
Default.args = {
|
|
137
191
|
messages: [
|
|
138
|
-
{
|
|
139
|
-
|
|
140
|
-
|
|
192
|
+
{
|
|
193
|
+
id: 'msg-1',
|
|
194
|
+
text: 'Hey, how are you?',
|
|
195
|
+
user: storyUsers.visitor,
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: 'msg-2',
|
|
199
|
+
text: "I'm doing great, thanks!",
|
|
200
|
+
user: storyUsers.creator,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
id: 'msg-3',
|
|
204
|
+
text: 'Awesome! Have a good day.',
|
|
205
|
+
user: storyUsers.visitor,
|
|
206
|
+
},
|
|
141
207
|
],
|
|
142
208
|
}
|
|
143
209
|
|
|
144
210
|
export const WithTipTag: StoryFn<TemplateProps> = Template.bind({})
|
|
145
211
|
WithTipTag.args = {
|
|
146
212
|
messages: [
|
|
147
|
-
{
|
|
213
|
+
{
|
|
214
|
+
id: 'msg-1',
|
|
215
|
+
text: 'Love your content!',
|
|
216
|
+
user: storyUsers.visitor,
|
|
217
|
+
},
|
|
148
218
|
{
|
|
149
219
|
id: 'msg-2',
|
|
150
220
|
text: "Here's a tip for you! Keep up the great work.",
|
|
151
|
-
user:
|
|
221
|
+
user: storyUsers.visitor,
|
|
152
222
|
metadata: { custom_type: 'MESSAGE_TIP', amount_text: '$5.50' },
|
|
153
223
|
},
|
|
154
|
-
{
|
|
224
|
+
{
|
|
225
|
+
id: 'msg-3',
|
|
226
|
+
text: 'Thank you so much! 🙏',
|
|
227
|
+
user: storyUsers.creator,
|
|
228
|
+
},
|
|
155
229
|
],
|
|
156
230
|
}
|
|
157
231
|
|
|
158
232
|
export const TipOnly: StoryFn<TemplateProps> = Template.bind({})
|
|
159
233
|
TipOnly.args = {
|
|
160
234
|
messages: [
|
|
161
|
-
{
|
|
235
|
+
{
|
|
236
|
+
id: 'msg-1',
|
|
237
|
+
text: 'Hello!',
|
|
238
|
+
user: storyUsers.visitor,
|
|
239
|
+
},
|
|
162
240
|
{
|
|
163
241
|
id: 'msg-2',
|
|
164
242
|
text: '',
|
|
165
|
-
user:
|
|
243
|
+
user: storyUsers.visitor,
|
|
166
244
|
metadata: { custom_type: 'MESSAGE_TIP', amount_text: '$50.00' },
|
|
167
245
|
},
|
|
168
|
-
{
|
|
246
|
+
{
|
|
247
|
+
id: 'msg-3',
|
|
248
|
+
text: 'Wow, thank you for the tip!',
|
|
249
|
+
user: storyUsers.creator,
|
|
250
|
+
},
|
|
169
251
|
],
|
|
170
252
|
}
|
|
171
253
|
|
|
172
254
|
export const MixedTags: StoryFn<TemplateProps> = Template.bind({})
|
|
173
255
|
MixedTags.args = {
|
|
174
256
|
messages: [
|
|
175
|
-
{
|
|
257
|
+
{
|
|
258
|
+
id: 'msg-1',
|
|
259
|
+
text: 'Regular message from a fan',
|
|
260
|
+
user: storyUsers.visitor,
|
|
261
|
+
},
|
|
176
262
|
{
|
|
177
263
|
id: 'msg-2',
|
|
178
264
|
text: 'I wanted to tip you for your amazing work!',
|
|
179
|
-
user:
|
|
265
|
+
user: storyUsers.visitor,
|
|
180
266
|
metadata: { custom_type: 'MESSAGE_TIP', amount_text: '$5.50' },
|
|
181
267
|
},
|
|
182
|
-
{
|
|
268
|
+
{
|
|
269
|
+
id: 'msg-3',
|
|
270
|
+
text: 'Thank you!',
|
|
271
|
+
user: storyUsers.creator,
|
|
272
|
+
},
|
|
183
273
|
{
|
|
184
274
|
id: 'msg-4',
|
|
185
275
|
text: '',
|
|
186
|
-
user:
|
|
276
|
+
user: storyUsers.visitor,
|
|
187
277
|
metadata: { custom_type: 'MESSAGE_TIP', amount_text: '$25.00' },
|
|
188
278
|
},
|
|
189
279
|
{
|
|
190
280
|
id: 'msg-5',
|
|
191
281
|
text: 'Wow, a tip with no message! Thanks!',
|
|
192
|
-
user:
|
|
282
|
+
user: storyUsers.creator,
|
|
193
283
|
},
|
|
194
284
|
{
|
|
195
285
|
id: 'msg-6',
|
|
196
286
|
text: 'This is a paid message!',
|
|
197
|
-
user:
|
|
287
|
+
user: storyUsers.visitor,
|
|
198
288
|
metadata: { custom_type: 'MESSAGE_PAID', amount_text: '$10.00' },
|
|
199
289
|
},
|
|
200
|
-
{
|
|
290
|
+
{
|
|
291
|
+
id: 'msg-7',
|
|
292
|
+
text: 'Got it, thanks!',
|
|
293
|
+
user: storyUsers.creator,
|
|
294
|
+
},
|
|
201
295
|
{
|
|
202
296
|
id: 'msg-8',
|
|
203
297
|
text: 'This is from a chatbot!',
|
|
204
|
-
user:
|
|
298
|
+
user: storyUsers.creator,
|
|
205
299
|
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
206
300
|
},
|
|
207
|
-
{
|
|
301
|
+
{
|
|
302
|
+
id: 'msg-9',
|
|
303
|
+
text: 'Thanks for letting me know.',
|
|
304
|
+
user: storyUsers.creator,
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export const PaidAttachment: StoryFn<TemplateProps> = Template.bind({})
|
|
310
|
+
PaidAttachment.args = {
|
|
311
|
+
messages: [
|
|
312
|
+
{
|
|
313
|
+
id: 'msg-1',
|
|
314
|
+
text: 'Can I have your workout plan?',
|
|
315
|
+
user: storyUsers.visitor,
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
id: 'msg-2',
|
|
319
|
+
text: 'yes here it is',
|
|
320
|
+
user: storyUsers.creator,
|
|
321
|
+
metadata: {
|
|
322
|
+
custom_type: 'MESSAGE_ATTACHMENT',
|
|
323
|
+
amount_text: 'AU$9.99',
|
|
324
|
+
attachment_title: "Alicia's Workout Plan",
|
|
325
|
+
attachment_mime_type: 'video/mp4',
|
|
326
|
+
attachment_thumbnail: '/video-thumbnail-blurred.jpg',
|
|
327
|
+
attachment_detail: '1:20',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
id: 'msg-3',
|
|
332
|
+
text: 'let me know if you have any questions!',
|
|
333
|
+
user: storyUsers.creator,
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
id: 'msg-4',
|
|
337
|
+
text: 'Looks amazing, unlocking now!',
|
|
338
|
+
user: storyUsers.visitor,
|
|
339
|
+
},
|
|
208
340
|
],
|
|
209
341
|
}
|
|
210
342
|
|
|
@@ -214,19 +346,19 @@ ChatbotVariants.args = {
|
|
|
214
346
|
{
|
|
215
347
|
id: 'msg-1',
|
|
216
348
|
text: 'Would you like to share some details that I can relay to Rupi Kaur?',
|
|
217
|
-
user:
|
|
349
|
+
user: storyUsers.creator,
|
|
218
350
|
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
219
351
|
},
|
|
220
352
|
{
|
|
221
353
|
id: 'msg-2',
|
|
222
|
-
text: '
|
|
223
|
-
user:
|
|
354
|
+
text: "I'm sorry to hear that. Are you referring to the course you've recently purchased?",
|
|
355
|
+
user: storyUsers.creator,
|
|
224
356
|
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
225
357
|
},
|
|
226
358
|
{
|
|
227
359
|
id: 'msg-3',
|
|
228
360
|
text: '',
|
|
229
|
-
user:
|
|
361
|
+
user: storyUsers.creator,
|
|
230
362
|
metadata: { custom_type: 'MESSAGE_CHATBOT' },
|
|
231
363
|
attachments: [
|
|
232
364
|
{
|
|
@@ -42,6 +42,11 @@ export const isChatbotMessage = (message: LocalMessage): boolean => {
|
|
|
42
42
|
return message.metadata?.custom_type === 'MESSAGE_CHATBOT'
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/** Check if a message is a locked attachment */
|
|
46
|
+
export const isAttachmentMessage = (message: LocalMessage): boolean => {
|
|
47
|
+
return message.metadata?.custom_type === 'MESSAGE_ATTACHMENT'
|
|
48
|
+
}
|
|
49
|
+
|
|
45
50
|
/** Check if a message has a tip/paid tag (both render the same) */
|
|
46
51
|
export const isTipOrPaidMessage = (message: LocalMessage): boolean => {
|
|
47
52
|
return isTipMessage(message) || isPaidMessage(message)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import React, { useMemo, useState } from 'react'
|
|
3
|
+
import { type Channel, type LocalMessage } from 'stream-chat'
|
|
3
4
|
import {
|
|
4
5
|
Attachment as DefaultAttachment,
|
|
5
6
|
EditMessageModal as DefaultEditMessageModal,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
isMessageBounced,
|
|
21
22
|
messageHasAttachments,
|
|
22
23
|
messageHasReactions,
|
|
24
|
+
useChannelStateContext,
|
|
23
25
|
useComponentContext,
|
|
24
26
|
useChatContext,
|
|
25
27
|
useMessageContext,
|
|
@@ -30,18 +32,23 @@ import {
|
|
|
30
32
|
|
|
31
33
|
import { useMessageVote } from '../../hooks/useMessageVote'
|
|
32
34
|
import { Avatar } from '../Avatar'
|
|
35
|
+
import LockedAttachment, { type LockedAttachmentSource } from '../LockedAttachment'
|
|
33
36
|
|
|
34
|
-
import { MessageTag, isChatbotMessage, isTipOnlyMessage } from './MessageTag'
|
|
37
|
+
import { MessageTag, isAttachmentMessage, isChatbotMessage, isTipOnlyMessage } from './MessageTag'
|
|
35
38
|
import { MessageVoteButtons } from './MessageVoteButtons'
|
|
36
39
|
|
|
37
40
|
type CustomMessageWithContextProps = MessageContextValue & {
|
|
38
41
|
chatbotVotingEnabled?: boolean
|
|
42
|
+
onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<LockedAttachmentSource>
|
|
43
|
+
onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
42
47
|
const {
|
|
43
48
|
additionalMessageInputProps,
|
|
44
49
|
chatbotVotingEnabled,
|
|
50
|
+
onAttachmentUnlock,
|
|
51
|
+
onAttachmentDownload,
|
|
45
52
|
editing,
|
|
46
53
|
endOfGroup,
|
|
47
54
|
firstOfGroup,
|
|
@@ -58,6 +65,7 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
58
65
|
} = props
|
|
59
66
|
|
|
60
67
|
const { client } = useChatContext('CustomMessage')
|
|
68
|
+
const { channel } = useChannelStateContext('CustomMessage')
|
|
61
69
|
const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false)
|
|
62
70
|
const reminder = useMessageReminder(message.id)
|
|
63
71
|
const { selected: voteState, voteUp, voteDown } = useMessageVote(message)
|
|
@@ -144,6 +152,7 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
144
152
|
const poll = message.poll_id && client.polls.fromState(message.poll_id)
|
|
145
153
|
const isTipOnly = isTipOnlyMessage(message)
|
|
146
154
|
const isChatbot = isChatbotMessage(message)
|
|
155
|
+
const isAttachment = isAttachmentMessage(message)
|
|
147
156
|
const hasRenderableAttachments = !!(
|
|
148
157
|
finalAttachments?.length && !message.quoted_message
|
|
149
158
|
)
|
|
@@ -192,7 +201,28 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
192
201
|
marginInlineStart: 0,
|
|
193
202
|
}}
|
|
194
203
|
>
|
|
195
|
-
{
|
|
204
|
+
{isAttachment ? (
|
|
205
|
+
<div className="flex flex-col gap-2">
|
|
206
|
+
<LockedAttachment
|
|
207
|
+
isCreator={isMine}
|
|
208
|
+
title={message.metadata?.attachment_title}
|
|
209
|
+
mimeType={message.metadata?.attachment_mime_type}
|
|
210
|
+
thumbnail={message.metadata?.attachment_thumbnail}
|
|
211
|
+
amountText={message.metadata?.amount_text}
|
|
212
|
+
detail={message.metadata?.attachment_detail}
|
|
213
|
+
paymentStatus={message.metadata?.payment_status}
|
|
214
|
+
onUnlock={onAttachmentUnlock ? () => onAttachmentUnlock(message, channel) : undefined}
|
|
215
|
+
onDownload={onAttachmentDownload ? () => onAttachmentDownload(message, channel) : undefined}
|
|
216
|
+
/>
|
|
217
|
+
{message.text && (
|
|
218
|
+
<div className="str-chat__message-bubble-wrapper">
|
|
219
|
+
<div className="str-chat__message-bubble">
|
|
220
|
+
<MessageText message={message} renderText={renderText} />
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
)}
|
|
224
|
+
</div>
|
|
225
|
+
) : isTipOnly ? (
|
|
196
226
|
/* Tip-only messages render as a standalone bubble */
|
|
197
227
|
<MessageTag message={message} standalone />
|
|
198
228
|
) : (
|
|
@@ -256,11 +286,20 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
256
286
|
|
|
257
287
|
const MemoizedCustomMessage = React.memo(
|
|
258
288
|
CustomMessageWithContext,
|
|
259
|
-
|
|
289
|
+
(prev, next) => {
|
|
290
|
+
if (prev.chatbotVotingEnabled !== next.chatbotVotingEnabled) return false
|
|
291
|
+
if (prev.onAttachmentUnlock !== next.onAttachmentUnlock) return false
|
|
292
|
+
if (prev.onAttachmentDownload !== next.onAttachmentDownload) return false
|
|
293
|
+
return areMessageUIPropsEqual(prev, next)
|
|
294
|
+
}
|
|
260
295
|
) as typeof CustomMessageWithContext
|
|
261
296
|
|
|
262
297
|
export const CustomMessage = (
|
|
263
|
-
props: MessageUIComponentProps & {
|
|
298
|
+
props: MessageUIComponentProps & {
|
|
299
|
+
chatbotVotingEnabled?: boolean
|
|
300
|
+
onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<LockedAttachmentSource>
|
|
301
|
+
onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
|
|
302
|
+
}
|
|
264
303
|
) => {
|
|
265
304
|
const messageContext = useMessageContext('CustomMessage')
|
|
266
305
|
return <MemoizedCustomMessage {...messageContext} {...props} />
|