@linktr.ee/messaging-react 2.6.2-rc-1780478292 → 3.0.0
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/README.md +36 -88
- package/dist/{Card-DtoXBrhV.cjs → Card-B7ePjYQ6.cjs} +2 -2
- package/dist/{Card-DtoXBrhV.cjs.map → Card-B7ePjYQ6.cjs.map} +1 -1
- package/dist/{Card-DmgAq0-y.js → Card-C-ZIQW_q.js} +2 -2
- package/dist/{Card-DmgAq0-y.js.map → Card-C-ZIQW_q.js.map} +1 -1
- package/dist/{Card-BIb2ouTi.js → Card-C46z9zz4.js} +2 -2
- package/dist/{Card-BIb2ouTi.js.map → Card-C46z9zz4.js.map} +1 -1
- package/dist/{Card-Dr3LuTAS.cjs → Card-Cq0x0bbb.cjs} +2 -2
- package/dist/{Card-Dr3LuTAS.cjs.map → Card-Cq0x0bbb.cjs.map} +1 -1
- package/dist/{Card-CafojjYc.js → Card-Cqld0-Ws.js} +3 -3
- package/dist/{Card-CafojjYc.js.map → Card-Cqld0-Ws.js.map} +1 -1
- package/dist/{Card-DrIyNSwR.cjs → Card-Drz28Q-Y.cjs} +2 -2
- package/dist/{Card-DrIyNSwR.cjs.map → Card-Drz28Q-Y.cjs.map} +1 -1
- package/dist/{LockedThumbnail-CPAHQ9jA.cjs → LockedThumbnail--h4GTH41.cjs} +2 -2
- package/dist/{LockedThumbnail-CPAHQ9jA.cjs.map → LockedThumbnail--h4GTH41.cjs.map} +1 -1
- package/dist/{LockedThumbnail-B4LMWHDV.js → LockedThumbnail-D5NHhET2.js} +2 -2
- package/dist/{LockedThumbnail-B4LMWHDV.js.map → LockedThumbnail-D5NHhET2.js.map} +1 -1
- package/dist/{index-LiNmL1ax.js → index-BUT2yBvJ.js} +1439 -1737
- package/dist/index-BUT2yBvJ.js.map +1 -0
- package/dist/index-DqNobxVj.cjs +2 -0
- package/dist/index-DqNobxVj.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +29 -63
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/ChannelList/index.test.tsx +0 -22
- package/src/components/ChannelList/index.tsx +0 -4
- package/src/components/ChannelView.test.tsx +0 -11
- package/src/components/ChannelView.tsx +3 -21
- package/src/components/MessagingShell/MessagingShell.test.tsx +171 -0
- package/src/components/MessagingShell/index.tsx +104 -329
- package/src/types.ts +23 -81
- package/src/utils/getMessageDisplayText.test.ts +0 -32
- package/src/utils/getMessageDisplayText.ts +1 -6
- package/dist/index-Degc6G3J.cjs +0 -2
- package/dist/index-Degc6G3J.cjs.map +0 -1
- package/dist/index-LiNmL1ax.js.map +0 -1
- package/src/components/CustomMessage/CustomMessage.translation.test.tsx +0 -191
- package/src/components/MessagingShell/EmptyState.stories.tsx +0 -35
- package/src/components/MessagingShell/EmptyState.tsx +0 -117
|
@@ -1,149 +1,73 @@
|
|
|
1
|
-
import
|
|
2
|
-
import React, { useState, useCallback, useRef, useEffect } from 'react'
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
3
2
|
import type { Channel } from 'stream-chat'
|
|
4
3
|
|
|
5
4
|
import { useMessaging } from '../../hooks/useMessaging'
|
|
6
5
|
import type { MessagingShellProps } from '../../types'
|
|
7
|
-
import { ChannelList } from '../ChannelList'
|
|
8
6
|
import { ChannelView } from '../ChannelView'
|
|
9
7
|
|
|
10
|
-
import { EmptyState } from './EmptyState'
|
|
11
8
|
import { ErrorState } from './ErrorState'
|
|
12
9
|
import { LoadingState } from './LoadingState'
|
|
13
10
|
|
|
14
11
|
/**
|
|
15
|
-
*
|
|
12
|
+
* Direct-conversation surface for one specific participant.
|
|
13
|
+
*
|
|
14
|
+
* Renders a single ChannelView for the channel between the connected user and
|
|
15
|
+
* `initialParticipantFilter`. If no channel exists yet and
|
|
16
|
+
* `initialParticipantData` is supplied, the configured StreamChatService
|
|
17
|
+
* channel creator is invoked to create one.
|
|
16
18
|
*/
|
|
17
19
|
export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
18
20
|
capabilities = {},
|
|
19
|
-
className,
|
|
20
21
|
renderMessageInputActions,
|
|
21
|
-
renderMessageInputFooter,
|
|
22
22
|
renderConversationFooter,
|
|
23
23
|
onChannelSelect,
|
|
24
|
+
onExitConversation,
|
|
24
25
|
initialParticipantFilter,
|
|
25
26
|
initialParticipantData,
|
|
26
27
|
CustomChannelEmptyState,
|
|
27
|
-
showChannelList = true,
|
|
28
|
-
filters,
|
|
29
|
-
channelRenderFilterFn,
|
|
30
|
-
channelListCustomEmptyStateIndicator,
|
|
31
|
-
onDeleteConversationClick,
|
|
32
28
|
onBlockParticipantClick,
|
|
33
29
|
onReportParticipantClick,
|
|
34
30
|
dmAgentEnabled,
|
|
35
|
-
messageMetadata,
|
|
36
31
|
onMessageSent,
|
|
37
|
-
showStarButton = false,
|
|
38
32
|
chatbotVotingEnabled = false,
|
|
39
33
|
viewerLanguage,
|
|
40
|
-
renderMessagePreview,
|
|
41
34
|
renderChannelBanner,
|
|
42
|
-
customProfileContent,
|
|
43
35
|
customChannelActions,
|
|
44
36
|
renderMessage,
|
|
45
37
|
onMessageLinkClick,
|
|
46
|
-
sendButton,
|
|
47
|
-
attachmentPreviewList,
|
|
48
38
|
}) => {
|
|
49
39
|
const {
|
|
50
|
-
service,
|
|
51
40
|
client,
|
|
52
41
|
isConnected,
|
|
53
42
|
isLoading,
|
|
54
43
|
error,
|
|
55
44
|
refreshConnection,
|
|
45
|
+
service,
|
|
56
46
|
debug,
|
|
57
47
|
} = useMessaging()
|
|
58
48
|
|
|
59
49
|
const [selectedChannel, setSelectedChannel] = useState<Channel | null>(null)
|
|
60
|
-
const [hasChannels, setHasChannels] = useState(false)
|
|
61
|
-
const [channelsLoaded, setChannelsLoaded] = useState(false)
|
|
62
|
-
const [directConversationMode, setDirectConversationMode] = useState(false)
|
|
63
50
|
const [directConversationError, setDirectConversationError] = useState<
|
|
64
51
|
string | null
|
|
65
52
|
>(null)
|
|
53
|
+
const [didExit, setDidExit] = useState(false)
|
|
66
54
|
|
|
67
55
|
const { showDeleteConversation = true } = capabilities
|
|
68
56
|
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
hidden: false,
|
|
80
|
-
}),
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Merge provided filters with base filters
|
|
84
|
-
// Provided filters can override base filters if needed
|
|
85
|
-
return {
|
|
86
|
-
...baseFilters,
|
|
87
|
-
...filters,
|
|
88
|
-
}
|
|
89
|
-
}, [filters, client?.userID])
|
|
90
|
-
|
|
91
|
-
// Track if we've already synced channels to prevent repeated API calls
|
|
92
|
-
const syncedRef = useRef<string | null>(null)
|
|
93
|
-
|
|
94
|
-
// Function to sync channels (extracted for reuse)
|
|
95
|
-
const syncChannels = useCallback(async () => {
|
|
96
|
-
if (!client || !isConnected) return
|
|
97
|
-
|
|
98
|
-
const userId = client.userID
|
|
99
|
-
if (!userId) return
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
if (debug) {
|
|
103
|
-
console.log('[MessagingShell] Syncing channels for user:', userId)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const channels = await client.queryChannels(
|
|
107
|
-
{
|
|
108
|
-
type: 'messaging',
|
|
109
|
-
members: { $in: [userId] },
|
|
110
|
-
},
|
|
111
|
-
{},
|
|
112
|
-
{ limit: 100 }
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
setHasChannels(channels.length > 0)
|
|
116
|
-
setChannelsLoaded(true)
|
|
117
|
-
syncedRef.current = userId // Mark as synced for this user
|
|
57
|
+
// Stash consumer props that are unstable when passed inline (object
|
|
58
|
+
// literals, arrow-function callbacks) so the load effect's deps stay
|
|
59
|
+
// identity-stable. Without this, the documented usage pattern in the
|
|
60
|
+
// README — passing `initialParticipantData={{ ... }}` and
|
|
61
|
+
// `onChannelSelect={(ch) => ...}` — re-fires the effect on every render
|
|
62
|
+
// and triggers a queryChannels call each time.
|
|
63
|
+
const initialParticipantDataRef = useRef(initialParticipantData)
|
|
64
|
+
initialParticipantDataRef.current = initialParticipantData
|
|
65
|
+
const onChannelSelectRef = useRef(onChannelSelect)
|
|
66
|
+
onChannelSelectRef.current = onChannelSelect
|
|
118
67
|
|
|
119
|
-
if (debug) {
|
|
120
|
-
console.log('[MessagingShell] Channels synced successfully:', {
|
|
121
|
-
channelCount: channels.length,
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.error('[MessagingShell] Failed to sync channels:', error)
|
|
126
|
-
// Don't mark as synced on error, allow retry
|
|
127
|
-
}
|
|
128
|
-
}, [client, isConnected, debug])
|
|
129
|
-
|
|
130
|
-
// Sync existing channels to drive empty-state behavior.
|
|
131
68
|
useEffect(() => {
|
|
132
69
|
if (!client || !isConnected) return
|
|
133
70
|
|
|
134
|
-
const userId = client.userID
|
|
135
|
-
if (!userId) return
|
|
136
|
-
|
|
137
|
-
// Prevent repeated sync for the same user
|
|
138
|
-
if (syncedRef.current === userId) return
|
|
139
|
-
|
|
140
|
-
syncChannels()
|
|
141
|
-
}, [client, isConnected, syncChannels])
|
|
142
|
-
|
|
143
|
-
// Load initial channel for direct conversation mode
|
|
144
|
-
useEffect(() => {
|
|
145
|
-
if (!initialParticipantFilter || !client || !isConnected) return
|
|
146
|
-
|
|
147
71
|
const loadInitialChannel = async () => {
|
|
148
72
|
const userId = client.userID
|
|
149
73
|
if (!userId) return
|
|
@@ -167,13 +91,8 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
167
91
|
|
|
168
92
|
if (channels.length > 0) {
|
|
169
93
|
setSelectedChannel(channels[0])
|
|
170
|
-
setDirectConversationMode(true)
|
|
171
94
|
setDirectConversationError(null)
|
|
172
|
-
|
|
173
|
-
// Notify parent component of channel selection
|
|
174
|
-
if (onChannelSelect) {
|
|
175
|
-
onChannelSelect(channels[0])
|
|
176
|
-
}
|
|
95
|
+
onChannelSelectRef.current?.(channels[0])
|
|
177
96
|
|
|
178
97
|
if (debug) {
|
|
179
98
|
console.log(
|
|
@@ -181,59 +100,43 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
181
100
|
channels[0].id
|
|
182
101
|
)
|
|
183
102
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (initialParticipantData && service) {
|
|
187
|
-
if (debug) {
|
|
188
|
-
console.log(
|
|
189
|
-
'[MessagingShell] No conversation found, creating one for:',
|
|
190
|
-
initialParticipantData
|
|
191
|
-
)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
// Use the existing service method to create the channel
|
|
196
|
-
const channel = await service.startChannelWithParticipant({
|
|
197
|
-
id: initialParticipantData.id,
|
|
198
|
-
name: initialParticipantData.name,
|
|
199
|
-
phone: initialParticipantData.phone,
|
|
200
|
-
})
|
|
103
|
+
return
|
|
104
|
+
}
|
|
201
105
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
106
|
+
const participantData = initialParticipantDataRef.current
|
|
107
|
+
if (!participantData || !service) {
|
|
108
|
+
setDirectConversationError('No conversation found with this account')
|
|
109
|
+
if (debug) {
|
|
110
|
+
console.log(
|
|
111
|
+
'[MessagingShell] No conversation found for:',
|
|
112
|
+
initialParticipantFilter
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
return
|
|
116
|
+
}
|
|
205
117
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
118
|
+
try {
|
|
119
|
+
const channel = await service.startChannelWithParticipant({
|
|
120
|
+
id: participantData.id,
|
|
121
|
+
name: participantData.name,
|
|
122
|
+
phone: participantData.phone,
|
|
123
|
+
})
|
|
124
|
+
setSelectedChannel(channel)
|
|
125
|
+
setDirectConversationError(null)
|
|
126
|
+
onChannelSelectRef.current?.(channel)
|
|
210
127
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
} catch (createErr) {
|
|
218
|
-
console.error(
|
|
219
|
-
'[MessagingShell] Failed to create conversation:',
|
|
220
|
-
createErr
|
|
221
|
-
)
|
|
222
|
-
setDirectConversationError('Failed to create conversation')
|
|
223
|
-
}
|
|
224
|
-
} else {
|
|
225
|
-
// No participant data provided, show error
|
|
226
|
-
setDirectConversationError(
|
|
227
|
-
'No conversation found with this account'
|
|
128
|
+
if (debug) {
|
|
129
|
+
console.log(
|
|
130
|
+
'[MessagingShell] Channel created and loaded:',
|
|
131
|
+
channel.id
|
|
228
132
|
)
|
|
229
|
-
|
|
230
|
-
if (debug) {
|
|
231
|
-
console.log(
|
|
232
|
-
'[MessagingShell] No conversation found for:',
|
|
233
|
-
initialParticipantFilter
|
|
234
|
-
)
|
|
235
|
-
}
|
|
236
133
|
}
|
|
134
|
+
} catch (createErr) {
|
|
135
|
+
console.error(
|
|
136
|
+
'[MessagingShell] Failed to create conversation:',
|
|
137
|
+
createErr
|
|
138
|
+
)
|
|
139
|
+
setDirectConversationError('Failed to create conversation')
|
|
237
140
|
}
|
|
238
141
|
} catch (err) {
|
|
239
142
|
console.error(
|
|
@@ -244,202 +147,74 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
|
|
|
244
147
|
}
|
|
245
148
|
}
|
|
246
149
|
|
|
247
|
-
loadInitialChannel()
|
|
248
|
-
}, [
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const handleChannelSelect = useCallback(
|
|
259
|
-
(channel: Channel) => {
|
|
260
|
-
setSelectedChannel(channel)
|
|
261
|
-
onChannelSelect?.(channel)
|
|
262
|
-
},
|
|
263
|
-
[onChannelSelect]
|
|
264
|
-
)
|
|
265
|
-
|
|
266
|
-
const handleBackToChannelList = useCallback(() => {
|
|
267
|
-
// In direct conversation mode, don't allow going back to channel list
|
|
268
|
-
// The parent component should handle navigation
|
|
269
|
-
if (directConversationMode) return
|
|
270
|
-
|
|
150
|
+
void loadInitialChannel()
|
|
151
|
+
}, [initialParticipantFilter, client, isConnected, service, debug])
|
|
152
|
+
|
|
153
|
+
// Leave / block clears the selected channel and notifies the consumer.
|
|
154
|
+
// The consumer owns what happens next — typically unmounting MessagingShell
|
|
155
|
+
// or re-rendering with new participant data. When no callback is provided,
|
|
156
|
+
// the shell renders an "ended" state rather than an indefinite spinner so
|
|
157
|
+
// the surface remains honest about why no conversation is shown.
|
|
158
|
+
const onExitConversationRef = useRef(onExitConversation)
|
|
159
|
+
onExitConversationRef.current = onExitConversation
|
|
160
|
+
const handleExitConversation = useCallback(() => {
|
|
271
161
|
setSelectedChannel(null)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
async (channel: Channel) => {
|
|
276
|
-
if (debug) {
|
|
277
|
-
console.log('[MessagingShell] Leaving conversation:', channel.id)
|
|
278
|
-
}
|
|
279
|
-
setSelectedChannel(null)
|
|
280
|
-
setDirectConversationMode(false) // Exit direct conversation mode
|
|
281
|
-
|
|
282
|
-
// Force re-sync to update the existing participants list
|
|
283
|
-
syncedRef.current = null
|
|
284
|
-
await syncChannels()
|
|
285
|
-
},
|
|
286
|
-
[syncChannels, debug]
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
const handleBlockParticipant = useCallback(
|
|
290
|
-
async (participantId?: string) => {
|
|
291
|
-
if (debug) {
|
|
292
|
-
console.log('[MessagingShell] Blocking participant:', participantId)
|
|
293
|
-
}
|
|
294
|
-
setSelectedChannel(null)
|
|
295
|
-
setDirectConversationMode(false) // Exit direct conversation mode
|
|
296
|
-
|
|
297
|
-
// Force re-sync to update the existing participants list
|
|
298
|
-
syncedRef.current = null
|
|
299
|
-
await syncChannels()
|
|
300
|
-
},
|
|
301
|
-
[syncChannels, debug]
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
const isChannelSelected = Boolean(selectedChannel)
|
|
162
|
+
setDidExit(true)
|
|
163
|
+
onExitConversationRef.current?.()
|
|
164
|
+
}, [])
|
|
305
165
|
|
|
306
|
-
// Show loading state
|
|
307
166
|
if (isLoading) {
|
|
308
|
-
return
|
|
309
|
-
<div className={classNames('h-full', className)}>
|
|
310
|
-
<LoadingState />
|
|
311
|
-
</div>
|
|
312
|
-
)
|
|
167
|
+
return <LoadingState />
|
|
313
168
|
}
|
|
314
169
|
|
|
315
|
-
// Show error state
|
|
316
170
|
if (error) {
|
|
317
|
-
return
|
|
318
|
-
<div className={classNames('h-full', className)}>
|
|
319
|
-
<ErrorState message={error} onBack={refreshConnection} />
|
|
320
|
-
</div>
|
|
321
|
-
)
|
|
171
|
+
return <ErrorState message={error} onBack={refreshConnection} />
|
|
322
172
|
}
|
|
323
173
|
|
|
324
|
-
// Show not connected state
|
|
325
174
|
if (!isConnected || !client) {
|
|
326
175
|
return (
|
|
327
|
-
<
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
/>
|
|
332
|
-
</div>
|
|
176
|
+
<ErrorState
|
|
177
|
+
message="Not connected to messaging service"
|
|
178
|
+
onBack={refreshConnection}
|
|
179
|
+
/>
|
|
333
180
|
)
|
|
334
181
|
}
|
|
335
182
|
|
|
336
|
-
// Show direct conversation error state
|
|
337
183
|
if (directConversationError) {
|
|
338
|
-
return
|
|
339
|
-
<div className={classNames('h-full', className)}>
|
|
340
|
-
<ErrorState message={directConversationError} />
|
|
341
|
-
</div>
|
|
342
|
-
)
|
|
184
|
+
return <ErrorState message={directConversationError} />
|
|
343
185
|
}
|
|
344
186
|
|
|
345
|
-
|
|
346
|
-
<
|
|
347
|
-
|
|
348
|
-
'messaging-shell h-full bg-background-primary overflow-hidden',
|
|
349
|
-
className
|
|
350
|
-
)}
|
|
351
|
-
>
|
|
352
|
-
<div className="flex h-full min-h-0">
|
|
353
|
-
{/* Channel List Sidebar */}
|
|
354
|
-
<div
|
|
355
|
-
className={classNames(
|
|
356
|
-
'messaging-channel-list-sidebar min-h-0 min-w-0 lg:flex lg:flex-col',
|
|
357
|
-
{
|
|
358
|
-
'!hidden': showChannelList === false || directConversationMode,
|
|
359
|
-
// Hide on mobile when channel selected, show on desktop with consistent wide width
|
|
360
|
-
'hidden lg:flex lg:flex-1 lg:max-w-2xl':
|
|
361
|
-
showChannelList !== false &&
|
|
362
|
-
!directConversationMode &&
|
|
363
|
-
isChannelSelected,
|
|
364
|
-
// Show on mobile when no channel selected, use same wide width on desktop
|
|
365
|
-
'flex flex-col w-full lg:flex-1 lg:max-w-2xl':
|
|
366
|
-
showChannelList !== false &&
|
|
367
|
-
!directConversationMode &&
|
|
368
|
-
!isChannelSelected,
|
|
369
|
-
}
|
|
370
|
-
)}
|
|
371
|
-
>
|
|
372
|
-
<ChannelList
|
|
373
|
-
onChannelSelect={handleChannelSelect}
|
|
374
|
-
selectedChannel={selectedChannel || undefined}
|
|
375
|
-
filters={channelFilters}
|
|
376
|
-
channelRenderFilterFn={channelRenderFilterFn}
|
|
377
|
-
customEmptyStateIndicator={channelListCustomEmptyStateIndicator}
|
|
378
|
-
renderMessagePreview={renderMessagePreview}
|
|
379
|
-
viewerLanguage={viewerLanguage}
|
|
380
|
-
/>
|
|
381
|
-
</div>
|
|
187
|
+
if (didExit && !selectedChannel) {
|
|
188
|
+
return <ErrorState message="Conversation ended" />
|
|
189
|
+
}
|
|
382
190
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
{
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
renderConversationFooter={renderConversationFooter}
|
|
411
|
-
renderChannelBanner={renderChannelBanner}
|
|
412
|
-
onLeaveConversation={handleLeaveConversation}
|
|
413
|
-
onBlockParticipant={handleBlockParticipant}
|
|
414
|
-
CustomChannelEmptyState={CustomChannelEmptyState}
|
|
415
|
-
showDeleteConversation={showDeleteConversation}
|
|
416
|
-
onDeleteConversationClick={onDeleteConversationClick}
|
|
417
|
-
onBlockParticipantClick={onBlockParticipantClick}
|
|
418
|
-
onReportParticipantClick={onReportParticipantClick}
|
|
419
|
-
dmAgentEnabled={dmAgentEnabled}
|
|
420
|
-
messageMetadata={messageMetadata}
|
|
421
|
-
onMessageSent={onMessageSent}
|
|
422
|
-
showStarButton={showStarButton}
|
|
423
|
-
chatbotVotingEnabled={chatbotVotingEnabled}
|
|
424
|
-
viewerLanguage={viewerLanguage}
|
|
425
|
-
customProfileContent={customProfileContent}
|
|
426
|
-
customChannelActions={customChannelActions}
|
|
427
|
-
renderMessage={renderMessage}
|
|
428
|
-
onMessageLinkClick={onMessageLinkClick}
|
|
429
|
-
sendButton={sendButton}
|
|
430
|
-
attachmentPreviewList={attachmentPreviewList}
|
|
431
|
-
/>
|
|
432
|
-
</div>
|
|
433
|
-
) : initialParticipantFilter ? (
|
|
434
|
-
// Show loading while creating/loading direct conversation channel
|
|
435
|
-
<LoadingState />
|
|
436
|
-
) : (
|
|
437
|
-
<EmptyState
|
|
438
|
-
hasChannels={hasChannels}
|
|
439
|
-
channelsLoaded={channelsLoaded}
|
|
440
|
-
/>
|
|
441
|
-
)}
|
|
442
|
-
</div>
|
|
191
|
+
if (!selectedChannel) {
|
|
192
|
+
return <LoadingState />
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
<div className="messaging-shell h-full bg-background-primary overflow-hidden">
|
|
197
|
+
<div className="flex h-full min-h-0 flex-col">
|
|
198
|
+
<ChannelView
|
|
199
|
+
channel={selectedChannel}
|
|
200
|
+
key={selectedChannel.id}
|
|
201
|
+
renderMessageInputActions={renderMessageInputActions}
|
|
202
|
+
renderConversationFooter={renderConversationFooter}
|
|
203
|
+
renderChannelBanner={renderChannelBanner}
|
|
204
|
+
onLeaveConversation={handleExitConversation}
|
|
205
|
+
onBlockParticipant={handleExitConversation}
|
|
206
|
+
CustomChannelEmptyState={CustomChannelEmptyState}
|
|
207
|
+
showDeleteConversation={showDeleteConversation}
|
|
208
|
+
onBlockParticipantClick={onBlockParticipantClick}
|
|
209
|
+
onReportParticipantClick={onReportParticipantClick}
|
|
210
|
+
dmAgentEnabled={dmAgentEnabled}
|
|
211
|
+
onMessageSent={onMessageSent}
|
|
212
|
+
chatbotVotingEnabled={chatbotVotingEnabled}
|
|
213
|
+
viewerLanguage={viewerLanguage}
|
|
214
|
+
customChannelActions={customChannelActions}
|
|
215
|
+
renderMessage={renderMessage}
|
|
216
|
+
onMessageLinkClick={onMessageLinkClick}
|
|
217
|
+
/>
|
|
443
218
|
</div>
|
|
444
219
|
</div>
|
|
445
220
|
)
|