@linktr.ee/messaging-react 3.2.0 → 3.3.1

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.
Files changed (37) hide show
  1. package/dist/{Card-bdnjL_4d.js → Card-BAc2cgtn.js} +3 -3
  2. package/dist/{Card-bdnjL_4d.js.map → Card-BAc2cgtn.js.map} +1 -1
  3. package/dist/{Card-CO089n1e.cjs → Card-Cn1cBVnr.cjs} +2 -2
  4. package/dist/{Card-CO089n1e.cjs.map → Card-Cn1cBVnr.cjs.map} +1 -1
  5. package/dist/{Card-B5TCecD6.cjs → Card-DAyszUxa.cjs} +2 -2
  6. package/dist/{Card-B5TCecD6.cjs.map → Card-DAyszUxa.cjs.map} +1 -1
  7. package/dist/{Card-DQYLHbDI.js → Card-D_2VQScd.js} +2 -2
  8. package/dist/{Card-DQYLHbDI.js.map → Card-D_2VQScd.js.map} +1 -1
  9. package/dist/{Card-DTaHgygz.js → Card-D_G8133I.js} +2 -2
  10. package/dist/{Card-DTaHgygz.js.map → Card-D_G8133I.js.map} +1 -1
  11. package/dist/{Card-aO1qZWDU.cjs → Card-gYxPXe_W.cjs} +2 -2
  12. package/dist/{Card-aO1qZWDU.cjs.map → Card-gYxPXe_W.cjs.map} +1 -1
  13. package/dist/{LockedThumbnail-nsFA3DjA.js → LockedThumbnail-C7tWpOQr.js} +2 -2
  14. package/dist/{LockedThumbnail-nsFA3DjA.js.map → LockedThumbnail-C7tWpOQr.js.map} +1 -1
  15. package/dist/{LockedThumbnail-CWVybsBb.cjs → LockedThumbnail-DtOTZl3l.cjs} +2 -2
  16. package/dist/{LockedThumbnail-CWVybsBb.cjs.map → LockedThumbnail-DtOTZl3l.cjs.map} +1 -1
  17. package/dist/{index-DJKFVBkP.js → index-C_NFzAB9.js} +1356 -1382
  18. package/dist/index-C_NFzAB9.js.map +1 -0
  19. package/dist/index-_Se6ovQm.cjs +2 -0
  20. package/dist/index-_Se6ovQm.cjs.map +1 -0
  21. package/dist/index.cjs +1 -1
  22. package/dist/index.d.ts +39 -15
  23. package/dist/index.js +1 -1
  24. package/package.json +3 -3
  25. package/src/components/ChannelActionsMenu/ChannelActionsMenu.test.tsx +305 -0
  26. package/src/components/ChannelActionsMenu/index.tsx +221 -0
  27. package/src/components/ChannelView.stories.tsx +3 -73
  28. package/src/components/ChannelView.test.tsx +30 -57
  29. package/src/components/ChannelView.tsx +66 -115
  30. package/src/hooks/useChannelModerationActions.ts +227 -0
  31. package/src/stream-custom-data.ts +21 -1
  32. package/src/types.ts +20 -15
  33. package/dist/index-BO2VfA-M.cjs +0 -2
  34. package/dist/index-BO2VfA-M.cjs.map +0 -1
  35. package/dist/index-DJKFVBkP.js.map +0 -1
  36. package/src/components/ChannelInfoDialog/ChannelInfoDialog.test.tsx +0 -333
  37. package/src/components/ChannelInfoDialog/index.tsx +0 -336
@@ -240,12 +240,12 @@ Default.args = {
240
240
  console.log('Leave conversation:', channel.id),
241
241
  onBlockParticipant: (participantId) =>
242
242
  console.log('Block participant:', participantId),
243
- followerStatus: true, // Shows "Subscribed to you"
243
+ followerStatus: true,
244
244
  }
245
245
  Default.parameters = {
246
246
  docs: {
247
247
  description: {
248
- story: 'Default channel view with messages and conversation header, showing subscriber status.',
248
+ story: 'Default channel view with messages and conversation header.',
249
249
  },
250
250
  },
251
251
  }
@@ -277,10 +277,8 @@ RestrictedOfficialChannel.args = {
277
277
  // Restricted surface for the Linktree official channel:
278
278
  showBlockParticipant: false,
279
279
  showReportParticipant: false,
280
- showFollowerStatus: false,
281
280
  composerDisabled: true,
282
281
  composerDisabledReason: 'Only Linktree can send messages on this thread',
283
- followerStatus: true, // would normally render "Subscribed to you" — suppressed here
284
282
  onLeaveConversation: (channel) =>
285
283
  console.log('Leave conversation:', channel.id),
286
284
  }
@@ -288,7 +286,7 @@ RestrictedOfficialChannel.parameters = {
288
286
  docs: {
289
287
  description: {
290
288
  story:
291
- 'Restricted action surface used by the Linktree official channel: block, report, and the subscription-status label are hidden, and the composer is replaced by a locked panel explaining the linker cannot send messages on this thread. Delete conversation, favorite, and chat info remain available. Open the chat info dialog (3-dot / name click) to see block & report removed.',
289
+ 'Restricted action surface used by the Linktree official channel: block and report are hidden, and the composer is replaced by a locked panel explaining the linker cannot send messages on this thread. Delete conversation and favorite remain available in the "..." actions popover.',
292
290
  },
293
291
  },
294
292
  }
@@ -543,74 +541,6 @@ EmptyChannel.parameters = {
543
541
  },
544
542
  }
545
543
 
546
- export const SubscriberStatus: StoryFn<TemplateProps> = Template.bind({})
547
- SubscriberStatus.args = {
548
- showBackButton: false,
549
- followerStatus: true, // Shows "Subscribed to you" in green
550
- onLeaveConversation: (channel) =>
551
- console.log('Leave conversation:', channel.id),
552
- onBlockParticipant: (participantId) =>
553
- console.log('Block participant:', participantId),
554
- }
555
- SubscriberStatus.parameters = {
556
- docs: {
557
- description: {
558
- story: 'Channel view showing "Subscribed to you" badge in green when isFollower is true.',
559
- },
560
- },
561
- }
562
-
563
- export const NotSubscribedStatus: StoryFn<TemplateProps> = Template.bind({})
564
- NotSubscribedStatus.args = {
565
- showBackButton: false,
566
- followerStatus: false, // Shows "Not subscribed" in gray
567
- onLeaveConversation: (channel) =>
568
- console.log('Leave conversation:', channel.id),
569
- onBlockParticipant: (participantId) =>
570
- console.log('Block participant:', participantId),
571
- }
572
- NotSubscribedStatus.parameters = {
573
- docs: {
574
- description: {
575
- story: 'Channel view showing "Not subscribed" badge in gray when isFollower is false.',
576
- },
577
- },
578
- }
579
-
580
- export const CustomFollowerStatus: StoryFn<TemplateProps> = Template.bind({})
581
- CustomFollowerStatus.args = {
582
- showBackButton: false,
583
- followerStatus: 'Mutual subscribers', // Custom status text in gray
584
- onLeaveConversation: (channel) =>
585
- console.log('Leave conversation:', channel.id),
586
- onBlockParticipant: (participantId) =>
587
- console.log('Block participant:', participantId),
588
- }
589
- CustomFollowerStatus.parameters = {
590
- docs: {
591
- description: {
592
- story: 'Channel view with a custom follower status text (shows in gray unless text is "Subscribed to you").',
593
- },
594
- },
595
- }
596
-
597
- export const NoFollowerStatus: StoryFn<TemplateProps> = Template.bind({})
598
- NoFollowerStatus.args = {
599
- showBackButton: false,
600
- followerStatus: undefined, // No badge shown
601
- onLeaveConversation: (channel) =>
602
- console.log('Leave conversation:', channel.id),
603
- onBlockParticipant: (participantId) =>
604
- console.log('Block participant:', participantId),
605
- }
606
- NoFollowerStatus.parameters = {
607
- docs: {
608
- description: {
609
- story: 'Channel view with no follower status badge displayed.',
610
- },
611
- },
612
- }
613
-
614
544
  export const FrozenChannel: StoryFn<TemplateProps> = Template.bind({})
615
545
  FrozenChannel.args = {
616
546
  showBackButton: false,
@@ -68,11 +68,11 @@ vi.mock('./CustomDateSeparator', () => ({
68
68
  CustomDateSeparator: () => <div data-testid="custom-date-separator" />,
69
69
  }))
70
70
 
71
- const channelInfoDialogProps: Array<Record<string, unknown>> = []
72
- vi.mock('./ChannelInfoDialog', () => ({
73
- ChannelInfoDialog: (props: Record<string, unknown>) => {
74
- channelInfoDialogProps.push({ ...props })
75
- return <div data-testid="channel-info-dialog" />
71
+ const channelActionsMenuProps: Array<Record<string, unknown>> = []
72
+ vi.mock('./ChannelActionsMenu', () => ({
73
+ ChannelActionsMenu: (props: Record<string, unknown>) => {
74
+ channelActionsMenuProps.push({ ...props })
75
+ return <div data-testid="channel-actions-menu" />
76
76
  },
77
77
  }))
78
78
 
@@ -151,24 +151,24 @@ describe('ChannelView', () => {
151
151
  activeChannel = undefined
152
152
  activeChannelProps = {}
153
153
  avatarRenderCalls.length = 0
154
- channelInfoDialogProps.length = 0
154
+ channelActionsMenuProps.length = 0
155
155
  messageInputProps.length = 0
156
156
  mockIsStarred = false
157
157
  })
158
158
 
159
- const lastDialogProps = () =>
160
- channelInfoDialogProps[channelInfoDialogProps.length - 1]
159
+ const lastActionsMenuProps = () =>
160
+ channelActionsMenuProps[channelActionsMenuProps.length - 1]
161
161
  const lastInputProps = () =>
162
162
  messageInputProps[messageInputProps.length - 1]
163
163
 
164
- it('keeps block and report visible by default in the info dialog', () => {
164
+ it('keeps block and report visible by default in the actions menu', () => {
165
165
  renderWithProviders(<ChannelView channel={createChannel()} />)
166
166
 
167
- expect(lastDialogProps().showBlockParticipant).not.toBe(false)
168
- expect(lastDialogProps().showReportParticipant).not.toBe(false)
167
+ expect(lastActionsMenuProps().showBlockParticipant).not.toBe(false)
168
+ expect(lastActionsMenuProps().showReportParticipant).not.toBe(false)
169
169
  })
170
170
 
171
- it('hides block and report in the info dialog when restricted', () => {
171
+ it('hides block and report in the actions menu when restricted', () => {
172
172
  renderWithProviders(
173
173
  <ChannelView
174
174
  channel={createChannel()}
@@ -177,63 +177,36 @@ describe('ChannelView', () => {
177
177
  />
178
178
  )
179
179
 
180
- expect(lastDialogProps().showBlockParticipant).toBe(false)
181
- expect(lastDialogProps().showReportParticipant).toBe(false)
180
+ expect(lastActionsMenuProps().showBlockParticipant).toBe(false)
181
+ expect(lastActionsMenuProps().showReportParticipant).toBe(false)
182
182
  })
183
183
 
184
- it('passes the follower status label to the info dialog by default', () => {
185
- const channel = createChannel()
186
- ;(channel as unknown as { data: Record<string, unknown> }).data = {
187
- isFollower: true,
188
- }
189
-
190
- renderWithProviders(<ChannelView channel={channel} />)
191
-
192
- expect(lastDialogProps().followerStatusLabel).toBe('Subscribed to you')
193
- })
194
-
195
- it('suppresses the follower status label when showFollowerStatus is false', () => {
196
- const channel = createChannel()
197
- ;(channel as unknown as { data: Record<string, unknown> }).data = {
198
- isFollower: true,
199
- }
200
-
201
- renderWithProviders(
202
- <ChannelView channel={channel} showFollowerStatus={false} />
203
- )
204
-
205
- expect(lastDialogProps().followerStatusLabel).toBeUndefined()
206
- })
207
-
208
- it('renders the channel info trigger by default', () => {
209
- const { container } = renderWithProviders(
210
- <ChannelView channel={createChannel()} />
211
- )
184
+ it('renders the participant name without an info trigger', () => {
185
+ renderWithProviders(<ChannelView channel={createChannel()} />)
212
186
 
213
- const infoTriggers = container.querySelectorAll(
214
- 'button[aria-label="Show info"]'
215
- )
216
- expect(infoTriggers.length).toBeGreaterThan(0)
217
- expect(channelInfoDialogProps.length).toBeGreaterThan(0)
187
+ // The info sidebar was removed, so the participant name is plain text on
188
+ // both headers — there is no clickable affordance to open a profile
189
+ // dialog anymore.
190
+ expect(
191
+ screen.queryByRole('button', { name: /view info for/i })
192
+ ).not.toBeInTheDocument()
193
+ expect(screen.getAllByText('Linker').length).toBeGreaterThanOrEqual(1)
218
194
  })
219
195
 
220
- it('hides the channel info trigger (both desktop and mobile) when showChannelInfo is false', () => {
221
- const { container } = renderWithProviders(
222
- <ChannelView channel={createChannel()} showChannelInfo={false} />
223
- )
196
+ it('renders the actions menu by default', () => {
197
+ renderWithProviders(<ChannelView channel={createChannel()} />)
224
198
 
225
- const infoTriggers = container.querySelectorAll(
226
- 'button[aria-label="Show info"]'
227
- )
228
- expect(infoTriggers.length).toBe(0)
199
+ expect(
200
+ screen.queryAllByTestId('channel-actions-menu').length
201
+ ).toBeGreaterThan(0)
229
202
  })
230
203
 
231
- it('does not mount ChannelInfoDialog when showChannelInfo is false', () => {
204
+ it('hides the actions menu (both desktop and mobile) when showChannelInfo is false', () => {
232
205
  renderWithProviders(
233
206
  <ChannelView channel={createChannel()} showChannelInfo={false} />
234
207
  )
235
208
 
236
- expect(channelInfoDialogProps.length).toBe(0)
209
+ expect(screen.queryAllByTestId('channel-actions-menu')).toHaveLength(0)
237
210
  })
238
211
 
239
212
  it('passes composer disabled state and reason to the message input', () => {
@@ -1,9 +1,4 @@
1
- import {
2
- ArrowLeftIcon,
3
- DotsThreeIcon,
4
- SparkleIcon,
5
- StarIcon,
6
- } from '@phosphor-icons/react'
1
+ import { ArrowLeftIcon, SparkleIcon, StarIcon } from '@phosphor-icons/react'
7
2
  import classNames from 'classnames'
8
3
  import React, { useCallback, useEffect, useRef } from 'react'
9
4
  import { Channel as ChannelType } from 'stream-chat'
@@ -22,7 +17,7 @@ import type { ChannelViewProps } from '../types'
22
17
  import { resolveParticipantDisplayName } from '../utils/resolveParticipantDisplayName'
23
18
 
24
19
  import { Avatar } from './Avatar'
25
- import { ChannelInfoDialog } from './ChannelInfoDialog'
20
+ import { ChannelActionsMenu } from './ChannelActionsMenu'
26
21
  import { CustomDateSeparator } from './CustomDateSeparator'
27
22
  import { CustomMessage } from './CustomMessage'
28
23
  import { CustomMessageActions } from './CustomMessage/CustomMessageActions'
@@ -44,17 +39,33 @@ const DM_AGENT_HEADER_HELPER_TEXT = 'Replies instantly with AI assistant'
44
39
  const CustomChannelHeader: React.FC<{
45
40
  onBack?: () => void
46
41
  showBackButton: boolean
47
- onShowInfo: () => void
48
- canShowInfo: boolean
49
42
  showStarButton?: boolean
50
43
  dmAgentEnabled?: boolean
44
+ onLeaveConversation?: (channel: ChannelType) => void
45
+ onBlockParticipant?: (participantId?: string) => void
46
+ showDeleteConversation?: boolean
47
+ showBlockParticipant?: boolean
48
+ showReportParticipant?: boolean
49
+ onDeleteConversationClick?: () => void
50
+ onBlockParticipantClick?: () => void
51
+ onReportParticipantClick?: () => void
52
+ customChannelActions?: React.ReactNode
53
+ showActionsMenu?: boolean
51
54
  }> = ({
52
55
  onBack,
53
56
  showBackButton,
54
- onShowInfo,
55
- canShowInfo,
56
57
  showStarButton = false,
57
58
  dmAgentEnabled = false,
59
+ onLeaveConversation,
60
+ onBlockParticipant,
61
+ showDeleteConversation = true,
62
+ showBlockParticipant = true,
63
+ showReportParticipant = true,
64
+ onDeleteConversationClick,
65
+ onBlockParticipantClick,
66
+ onReportParticipantClick,
67
+ customChannelActions,
68
+ showActionsMenu = true,
58
69
  }) => {
59
70
  const { channel } = useChannelStateContext()
60
71
 
@@ -143,15 +154,21 @@ const CustomChannelHeader: React.FC<{
143
154
  />
144
155
  </button>
145
156
  )}
146
- {canShowInfo && (
147
- <button
148
- className={classNames(ICON_BTN_CLASS, 'bg-[#F1F0EE]')}
149
- onClick={onShowInfo}
150
- type="button"
151
- aria-label="Show info"
152
- >
153
- <DotsThreeIcon className="size-5 text-black/90" />
154
- </button>
157
+ {showActionsMenu && (
158
+ <ChannelActionsMenu
159
+ channel={channel}
160
+ participant={participant}
161
+ showDeleteConversation={showDeleteConversation}
162
+ showBlockParticipant={showBlockParticipant}
163
+ showReportParticipant={showReportParticipant}
164
+ onLeaveConversation={onLeaveConversation}
165
+ onBlockParticipant={onBlockParticipant}
166
+ onDeleteConversationClick={onDeleteConversationClick}
167
+ onBlockParticipantClick={onBlockParticipantClick}
168
+ onReportParticipantClick={onReportParticipantClick}
169
+ customChannelActions={customChannelActions}
170
+ triggerClassName={classNames(ICON_BTN_CLASS, 'bg-[#F1F0EE]')}
171
+ />
155
172
  )}
156
173
  </div>
157
174
  </div>
@@ -180,20 +197,9 @@ const CustomChannelHeader: React.FC<{
180
197
  size={48}
181
198
  />
182
199
  <div className="min-w-0">
183
- {canShowInfo ? (
184
- <button
185
- type="button"
186
- onClick={onShowInfo}
187
- className="flex items-center gap-1 font-medium text-black/90 truncate hover:text-black/70 transition-colors"
188
- aria-label={`View info for ${participantName}`}
189
- >
190
- <span className="truncate">{participantName}</span>
191
- </button>
192
- ) : (
193
- <h1 className="font-medium text-black/90 truncate">
194
- {participantName}
195
- </h1>
196
- )}
200
+ <h1 className="font-medium text-black/90 truncate">
201
+ {participantName}
202
+ </h1>
197
203
  {dmAgentEnabled && (
198
204
  <div className="mt-0.5 flex items-center gap-1 text-[10px] leading-3 text-black/55">
199
205
  <SparkleIcon className="size-3 shrink-0 text-black/55" />
@@ -221,15 +227,21 @@ const CustomChannelHeader: React.FC<{
221
227
  />
222
228
  </button>
223
229
  )}
224
- {canShowInfo && onShowInfo && (
225
- <button
226
- className={ICON_BTN_CLASS}
227
- onClick={onShowInfo}
228
- type="button"
229
- aria-label="Show info"
230
- >
231
- <DotsThreeIcon className="size-6 text-black/90" />
232
- </button>
230
+ {showActionsMenu && (
231
+ <ChannelActionsMenu
232
+ channel={channel}
233
+ participant={participant}
234
+ showDeleteConversation={showDeleteConversation}
235
+ showBlockParticipant={showBlockParticipant}
236
+ showReportParticipant={showReportParticipant}
237
+ onLeaveConversation={onLeaveConversation}
238
+ onBlockParticipant={onBlockParticipant}
239
+ onDeleteConversationClick={onDeleteConversationClick}
240
+ onBlockParticipantClick={onBlockParticipantClick}
241
+ onReportParticipantClick={onReportParticipantClick}
242
+ customChannelActions={customChannelActions}
243
+ triggerClassName={ICON_BTN_CLASS}
244
+ />
233
245
  )}
234
246
  </div>
235
247
  </div>
@@ -255,13 +267,11 @@ const ChannelViewInner: React.FC<{
255
267
  onReportParticipantClick?: () => void
256
268
  showBlockParticipant?: boolean
257
269
  showReportParticipant?: boolean
258
- showFollowerStatus?: boolean
259
270
  composerDisabled?: boolean
260
271
  composerDisabledReason?: string
261
272
  showStarButton?: boolean
262
273
  chatbotVotingEnabled?: boolean
263
274
  renderChannelBanner?: () => React.ReactNode
264
- customProfileContent?: React.ReactNode
265
275
  customChannelActions?: React.ReactNode
266
276
  renderMessage?: (
267
277
  messageNode: React.ReactElement,
@@ -284,13 +294,11 @@ const ChannelViewInner: React.FC<{
284
294
  onReportParticipantClick,
285
295
  showBlockParticipant = true,
286
296
  showReportParticipant = true,
287
- showFollowerStatus = true,
288
297
  composerDisabled = false,
289
298
  composerDisabledReason,
290
299
  showStarButton = false,
291
300
  chatbotVotingEnabled = false,
292
301
  renderChannelBanner,
293
- customProfileContent,
294
302
  customChannelActions,
295
303
  renderMessage,
296
304
  dmAgentEnabled = false,
@@ -298,9 +306,8 @@ const ChannelViewInner: React.FC<{
298
306
  showChannelInfo = true,
299
307
  }) => {
300
308
  const { channel } = useChannelStateContext()
301
- const infoDialogRef = useRef<HTMLDialogElement>(null)
302
309
 
303
- // Get participant info for info dialog
310
+ // Get participant info (the other channel member)
304
311
  const participant = React.useMemo(() => {
305
312
  const myUserId = channel._client?.userID
306
313
  if (!myUserId) return undefined
@@ -329,39 +336,6 @@ const ChannelViewInner: React.FC<{
329
336
  currentUserIsAccount === false &&
330
337
  participantIsAccount === true
331
338
 
332
- // Get follower status label from channel data.
333
- // Suppressed entirely when showFollowerStatus is false (e.g. the Linktree
334
- // official channel hides subscription status).
335
- const followerStatusLabel = React.useMemo(() => {
336
- if (!showFollowerStatus) return undefined
337
-
338
- const channelExtraData = (channel.data ?? {}) as {
339
- followerStatus?: string
340
- isFollower?: boolean
341
- }
342
-
343
- // If explicit followerStatus is provided, use it
344
- if (channelExtraData.followerStatus) {
345
- return String(channelExtraData.followerStatus)
346
- }
347
- // If isFollower is explicitly defined, use it to determine status
348
- if (channelExtraData.isFollower !== undefined) {
349
- return channelExtraData.isFollower
350
- ? 'Subscribed to you'
351
- : 'Not subscribed'
352
- }
353
- // Otherwise, don't show any status
354
- return undefined
355
- }, [channel.data, showFollowerStatus])
356
-
357
- const handleShowInfo = useCallback(() => {
358
- infoDialogRef.current?.showModal()
359
- }, [])
360
-
361
- const handleCloseInfo = useCallback(() => {
362
- infoDialogRef.current?.close()
363
- }, [])
364
-
365
339
  // Prevents all message instances from unmounting when ChannelViewInner re-renders
366
340
  const MessageOverride = useCallback(
367
341
  (props: MessageUIComponentProps) => {
@@ -398,10 +372,18 @@ const ChannelViewInner: React.FC<{
398
372
  <CustomChannelHeader
399
373
  onBack={onBack}
400
374
  showBackButton={showBackButton}
401
- onShowInfo={handleShowInfo}
402
- canShowInfo={showChannelInfo && Boolean(participant)}
375
+ showActionsMenu={showChannelInfo}
403
376
  showStarButton={showStarButton}
404
377
  dmAgentEnabled={showDmAgentHeader}
378
+ onLeaveConversation={onLeaveConversation}
379
+ onBlockParticipant={onBlockParticipant}
380
+ showDeleteConversation={showDeleteConversation}
381
+ showBlockParticipant={showBlockParticipant}
382
+ showReportParticipant={showReportParticipant}
383
+ onDeleteConversationClick={onDeleteConversationClick}
384
+ onBlockParticipantClick={onBlockParticipantClick}
385
+ onReportParticipantClick={onReportParticipantClick}
386
+ customChannelActions={customChannelActions}
405
387
  />
406
388
  </div>
407
389
 
@@ -438,33 +420,6 @@ const ChannelViewInner: React.FC<{
438
420
  />
439
421
  </Window>
440
422
  </WithComponents>
441
-
442
- {/* Channel Info Dialog — suppressed entirely when showChannelInfo is
443
- false so restricted surfaces (e.g. anonymous visitor chat) cannot
444
- surface the participant profile or block/report/delete actions even
445
- if the dialog were opened programmatically. */}
446
- {showChannelInfo && (
447
- <ChannelInfoDialog
448
- dialogRef={infoDialogRef}
449
- onClose={handleCloseInfo}
450
- participant={participant}
451
- participantDisplayName={resolveParticipantDisplayName(
452
- participant?.user
453
- )}
454
- channel={channel}
455
- followerStatusLabel={followerStatusLabel}
456
- onLeaveConversation={onLeaveConversation}
457
- onBlockParticipant={onBlockParticipant}
458
- showDeleteConversation={showDeleteConversation}
459
- showBlockParticipant={showBlockParticipant}
460
- showReportParticipant={showReportParticipant}
461
- onDeleteConversationClick={onDeleteConversationClick}
462
- onBlockParticipantClick={onBlockParticipantClick}
463
- onReportParticipantClick={onReportParticipantClick}
464
- customProfileContent={customProfileContent}
465
- customChannelActions={customChannelActions}
466
- />
467
- )}
468
423
  </>
469
424
  )
470
425
  }
@@ -490,7 +445,6 @@ export const ChannelView = React.memo<ChannelViewProps>(
490
445
  onReportParticipantClick,
491
446
  showBlockParticipant = true,
492
447
  showReportParticipant = true,
493
- showFollowerStatus = true,
494
448
  composerDisabled = false,
495
449
  composerDisabledReason,
496
450
  dmAgentEnabled,
@@ -499,7 +453,6 @@ export const ChannelView = React.memo<ChannelViewProps>(
499
453
  showStarButton = false,
500
454
  chatbotVotingEnabled = false,
501
455
  renderChannelBanner,
502
- customProfileContent,
503
456
  customChannelActions,
504
457
  renderMessage,
505
458
  onMessageLinkClick,
@@ -610,14 +563,12 @@ export const ChannelView = React.memo<ChannelViewProps>(
610
563
  onReportParticipantClick={onReportParticipantClick}
611
564
  showBlockParticipant={showBlockParticipant}
612
565
  showReportParticipant={showReportParticipant}
613
- showFollowerStatus={showFollowerStatus}
614
566
  composerDisabled={composerDisabled}
615
567
  composerDisabledReason={composerDisabledReason}
616
568
  showStarButton={showStarButton}
617
569
  dmAgentEnabled={dmAgentEnabled}
618
570
  chatbotVotingEnabled={chatbotVotingEnabled}
619
571
  renderChannelBanner={renderChannelBanner}
620
- customProfileContent={customProfileContent}
621
572
  customChannelActions={customChannelActions}
622
573
  renderMessage={renderMessage}
623
574
  viewerLanguage={viewerLanguage}