@@ -145,82 +145,9 @@ type ChannelActionItem =
145145 Component : React . ComponentType < ComponentPropsWithRef < 'button' > > ;
146146 } ;
147147
148- export const defaultChannelActionSet : ChannelActionItem [ ] = [
149- {
150- // eslint-disable-next-line react/display-name
151- Component : forwardRef < HTMLButtonElement > ( ( _ , ref ) => {
152- const { channel } = useChannelListItemContext ( ) ;
153-
154- const dialogId = ChannelListItemActionButtons . getDialogId ( {
155- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
156- channelId : channel . id ! ,
157- } ) ;
158- const { dialog, dialogManager } = useDialogOnNearestManager ( { id : dialogId } ) ;
159- const dialogIsOpen = useDialogIsOpen ( dialogId , dialogManager ?. id ) ;
160-
161- return (
162- < Button
163- appearance = 'ghost'
164- aria-expanded = { dialogIsOpen }
165- aria-pressed = { dialogIsOpen }
166- circular
167- onClick = { ( e ) => {
168- e . stopPropagation ( ) ;
169-
170- dialog . toggle ( ) ;
171- } }
172- ref = { ref }
173- size = 'sm'
174- variant = 'secondary'
175- >
176- < IconMore />
177- </ Button >
178- ) ;
179- } ) ,
180- placement : 'quick-dropdown-toggle' ,
181- } ,
182- {
183- Component ( ) {
184- const behaviorProps = useArchiveActionButtonBehavior ( ) ;
185-
186- return (
187- < Button
188- appearance = 'ghost'
189- aria-label = { behaviorProps . title }
190- circular
191- size = 'sm'
192- variant = 'secondary'
193- { ...behaviorProps }
194- >
195- < IconArchive />
196- </ Button >
197- ) ;
198- } ,
199- placement : 'quick' ,
200- type : 'archive' ,
201- } ,
202- {
203- Component ( ) {
204- const behaviorProps = useMuteActionButtonBehavior ( ) ;
205-
206- return (
207- < Button
208- appearance = 'ghost'
209- aria-label = { behaviorProps . title }
210- circular
211- size = 'sm'
212- variant = 'secondary'
213- { ...behaviorProps }
214- >
215- < IconMute />
216- </ Button >
217- ) ;
218- } ,
219- placement : 'quick' ,
220- type : 'mute' ,
221- } ,
222- {
223- Component ( ) {
148+ const defaultComponents = {
149+ dropdown : {
150+ Archive ( ) {
224151 const behaviorProps = useArchiveActionButtonBehavior ( ) ;
225152
226153 return (
@@ -233,28 +160,7 @@ export const defaultChannelActionSet: ChannelActionItem[] = [
233160 </ ContextMenuButton >
234161 ) ;
235162 } ,
236- placement : 'dropdown' ,
237- type : 'archive' ,
238- } ,
239- {
240- Component ( ) {
241- const behaviorProps = useMuteActionButtonBehavior ( ) ;
242-
243- return (
244- < ContextMenuButton
245- aria-label = { behaviorProps . title }
246- Icon = { IconMute }
247- { ...behaviorProps }
248- >
249- { behaviorProps . title }
250- </ ContextMenuButton >
251- ) ;
252- } ,
253- placement : 'dropdown' ,
254- type : 'mute' ,
255- } ,
256- {
257- Component ( ) {
163+ Ban ( ) {
258164 const { client } = useChatContext ( ) ;
259165 const { addNotification } = useNotificationApi ( ) ;
260166 const { t } = useTranslationContext ( ) ;
@@ -326,11 +232,72 @@ export const defaultChannelActionSet: ChannelActionItem[] = [
326232 </ ContextMenuButton >
327233 ) ;
328234 } ,
329- placement : 'dropdown' ,
330- type : 'ban' ,
331- } ,
332- {
333- Component ( ) {
235+ Leave ( ) {
236+ const { t } = useTranslationContext ( ) ;
237+ const { channel } = useChannelListItemContext ( ) ;
238+ const { client } = useChatContext ( ) ;
239+ const { addNotification } = useNotificationApi ( ) ;
240+ const [ inProgress , setInProgress ] = useState ( false ) ;
241+
242+ const title = t ( 'Leave Channel' ) ;
243+
244+ return (
245+ < ContextMenuButton
246+ aria-label = { title }
247+ disabled = { inProgress }
248+ Icon = { IconLeave }
249+ onClick = { async ( e ) => {
250+ e . stopPropagation ( ) ;
251+ try {
252+ setInProgress ( true ) ;
253+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
254+ await channel . removeMembers ( [ client . userID ! ] ) ;
255+ addNotification ( {
256+ context : {
257+ channel,
258+ } ,
259+ emitter : ChannelListItemActionButtons . name ,
260+ message : t ( 'Left channel' ) ,
261+ severity : 'success' ,
262+ type : 'api:channel:leave:success' ,
263+ } ) ;
264+ } catch ( error ) {
265+ addNotification ( {
266+ context : {
267+ channel,
268+ } ,
269+ emitter : ChannelListItemActionButtons . name ,
270+ error :
271+ error instanceof Error ? error : new Error ( 'An unknown error occurred' ) ,
272+ message : t ( 'Failed to leave channel' ) ,
273+ severity : 'error' ,
274+ type : 'api:channel:leave:failed' ,
275+ } ) ;
276+ } finally {
277+ setInProgress ( false ) ;
278+ }
279+ } }
280+ title = { title }
281+ variant = 'destructive'
282+ >
283+ { title }
284+ </ ContextMenuButton >
285+ ) ;
286+ } ,
287+ Mute ( ) {
288+ const behaviorProps = useMuteActionButtonBehavior ( ) ;
289+
290+ return (
291+ < ContextMenuButton
292+ aria-label = { behaviorProps . title }
293+ Icon = { IconMute }
294+ { ...behaviorProps }
295+ >
296+ { behaviorProps . title }
297+ </ ContextMenuButton >
298+ ) ;
299+ } ,
300+ Pin ( ) {
334301 const { t } = useTranslationContext ( ) ;
335302 const { addNotification } = useNotificationApi ( ) ;
336303 const { channel } = useChannelListItemContext ( ) ;
@@ -400,62 +367,101 @@ export const defaultChannelActionSet: ChannelActionItem[] = [
400367 </ ContextMenuButton >
401368 ) ;
402369 } ,
403- placement : 'dropdown' ,
404- type : 'pin' ,
405370 } ,
406- {
407- Component ( ) {
408- const { t } = useTranslationContext ( ) ;
409- const { channel } = useChannelListItemContext ( ) ;
410- const { client } = useChatContext ( ) ;
411- const { addNotification } = useNotificationApi ( ) ;
412- const [ inProgress , setInProgress ] = useState ( false ) ;
371+ quick : {
372+ Archive ( ) {
373+ const behaviorProps = useArchiveActionButtonBehavior ( ) ;
413374
414- const title = t ( 'Leave Channel' ) ;
375+ return (
376+ < Button
377+ appearance = 'ghost'
378+ aria-label = { behaviorProps . title }
379+ circular
380+ size = 'sm'
381+ variant = 'secondary'
382+ { ...behaviorProps }
383+ >
384+ < IconArchive />
385+ </ Button >
386+ ) ;
387+ } ,
388+ Mute ( ) {
389+ const behaviorProps = useMuteActionButtonBehavior ( ) ;
415390
416391 return (
417- < ContextMenuButton
418- aria-label = { title }
419- disabled = { inProgress }
420- Icon = { IconLeave }
421- onClick = { async ( e ) => {
422- e . stopPropagation ( ) ;
423- try {
424- setInProgress ( true ) ;
425- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
426- await channel . removeMembers ( [ client . userID ! ] ) ;
427- addNotification ( {
428- context : {
429- channel,
430- } ,
431- emitter : ChannelListItemActionButtons . name ,
432- message : t ( 'Left channel' ) ,
433- severity : 'success' ,
434- type : 'api:channel:leave:success' ,
435- } ) ;
436- } catch ( error ) {
437- addNotification ( {
438- context : {
439- channel,
440- } ,
441- emitter : ChannelListItemActionButtons . name ,
442- error :
443- error instanceof Error ? error : new Error ( 'An unknown error occurred' ) ,
444- message : t ( 'Failed to leave channel' ) ,
445- severity : 'error' ,
446- type : 'api:channel:leave:failed' ,
447- } ) ;
448- } finally {
449- setInProgress ( false ) ;
450- }
451- } }
452- title = { title }
453- variant = 'destructive'
392+ < Button
393+ appearance = 'ghost'
394+ aria-label = { behaviorProps . title }
395+ circular
396+ size = 'sm'
397+ variant = 'secondary'
398+ { ...behaviorProps }
454399 >
455- { title }
456- </ ContextMenuButton >
400+ < IconMute />
401+ </ Button >
457402 ) ;
458403 } ,
404+ } ,
405+ QuickDropdownToggle : forwardRef < HTMLButtonElement > ( ( _ , ref ) => {
406+ const { channel } = useChannelListItemContext ( ) ;
407+
408+ const dialogId = ChannelListItemActionButtons . getDialogId ( {
409+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
410+ channelId : channel . id ! ,
411+ } ) ;
412+ const { dialog, dialogManager } = useDialogOnNearestManager ( { id : dialogId } ) ;
413+ const dialogIsOpen = useDialogIsOpen ( dialogId , dialogManager ?. id ) ;
414+
415+ return (
416+ < Button
417+ appearance = 'ghost'
418+ aria-expanded = { dialogIsOpen }
419+ aria-pressed = { dialogIsOpen }
420+ circular
421+ onClick = { ( e ) => {
422+ e . stopPropagation ( ) ;
423+
424+ dialog . toggle ( ) ;
425+ } }
426+ ref = { ref }
427+ size = 'sm'
428+ variant = 'secondary'
429+ >
430+ < IconMore />
431+ </ Button >
432+ ) ;
433+ } ) ,
434+ } ;
435+
436+ defaultComponents . QuickDropdownToggle . displayName = 'QuickDropdownToggle' ;
437+
438+ export const defaultChannelActionSet : ChannelActionItem [ ] = [
439+ {
440+ Component : defaultComponents . QuickDropdownToggle ,
441+ placement : 'quick-dropdown-toggle' ,
442+ } ,
443+ {
444+ Component : defaultComponents . quick . Mute ,
445+ placement : 'quick' ,
446+ type : 'mute' ,
447+ } ,
448+ {
449+ Component : defaultComponents . dropdown . Archive ,
450+ placement : 'dropdown' ,
451+ type : 'archive' ,
452+ } ,
453+ {
454+ Component : defaultComponents . dropdown . Ban ,
455+ placement : 'dropdown' ,
456+ type : 'ban' ,
457+ } ,
458+ {
459+ Component : defaultComponents . dropdown . Pin ,
460+ placement : 'dropdown' ,
461+ type : 'pin' ,
462+ } ,
463+ {
464+ Component : defaultComponents . dropdown . Leave ,
459465 placement : 'dropdown' ,
460466 type : 'leave' ,
461467 } ,
@@ -464,11 +470,6 @@ export const defaultChannelActionSet: ChannelActionItem[] = [
464470export const useBaseChannelActionSetFilter = ( channelActionSet : ChannelActionItem [ ] ) => {
465471 const { channel } = useChannelListItemContext ( ) ;
466472 const membership = useChannelMembershipState ( channel ) ;
467- const isDirectMessageChannel =
468- channel . type === 'messaging' &&
469- // assuming one of the users is current user
470- channel . data ?. member_count === 2 &&
471- channel . id ?. startsWith ( '!members-' ) ;
472473 const memberCount = channel . data ?. member_count ?? 0 ;
473474 const connectedUserIsMember = typeof membership . user !== 'undefined' ;
474475
@@ -480,17 +481,9 @@ export const useBaseChannelActionSetFilter = (channelActionSet: ChannelActionIte
480481
481482 switch ( action . type ) {
482483 case 'archive' :
483- return (
484- connectedUserIsMember &&
485- ( ( action . placement === 'quick' && isDirectMessageChannel ) ||
486- ( action . placement === 'dropdown' && ! isDirectMessageChannel ) )
487- ) ;
484+ return connectedUserIsMember ;
488485 case 'mute' :
489- return (
490- ownCapabilities ?. includes ( 'mute-channel' ) &&
491- ( ( action . placement === 'dropdown' && isDirectMessageChannel ) ||
492- ( action . placement === 'quick' && ! isDirectMessageChannel ) )
493- ) ;
486+ return ownCapabilities ?. includes ( 'mute-channel' ) ;
494487 case 'ban' :
495488 return (
496489 memberCount > 0 &&
@@ -507,11 +500,5 @@ export const useBaseChannelActionSetFilter = (channelActionSet: ChannelActionIte
507500 } ) ;
508501
509502 return filtered ;
510- } , [
511- channelActionSet ,
512- isDirectMessageChannel ,
513- memberCount ,
514- ownCapabilities ,
515- connectedUserIsMember ,
516- ] ) ;
503+ } , [ channelActionSet , memberCount , ownCapabilities , connectedUserIsMember ] ) ;
517504} ;
0 commit comments