diff --git a/web/chat/thread-menu.css b/web/chat/thread-menu.css --- a/web/chat/thread-menu.css +++ b/web/chat/thread-menu.css @@ -49,3 +49,9 @@ button.topBarMenuActionDangerous:hover { color: var(--thread-menu-color-dangerous-hover); } + +hr.separator { + border: 1px solid var(--thread-menu-separator-color); + margin: 10px 16px; + max-width: 130px; +} diff --git a/web/chat/thread-menu.react.js b/web/chat/thread-menu.react.js --- a/web/chat/thread-menu.react.js +++ b/web/chat/thread-menu.react.js @@ -5,13 +5,14 @@ faBell, faCog, faCommentAlt, + faSignOutAlt, faPlusCircle, faUserFriends, } from '@fortawesome/free-solid-svg-icons'; import * as React from 'react'; import { childThreadInfos } from 'lib/selectors/thread-selectors'; -import { threadHasPermission } from 'lib/shared/thread-utils'; +import { threadHasPermission, viewerIsMember } from 'lib/shared/thread-utils'; import { type ThreadInfo, threadTypes, @@ -95,6 +96,24 @@ ); }, [canCreateSubchannels]); + const leaveThreadItem = React.useMemo(() => { + const canLeaveThread = threadHasPermission( + threadInfo, + threadPermissions.LEAVE_THREAD, + ); + if (!viewerIsMember(threadInfo) || !canLeaveThread) { + return null; + } + return ( + + ); + }, [threadInfo]); + const menuItems = React.useMemo(() => { const settingsItem = ( @@ -102,6 +121,8 @@ const notificationsItem = ( ); + const separator =
; + const items = [ settingsItem, notificationsItem, @@ -109,9 +130,17 @@ sidebarItem, viewSubchannelsItem, createSubchannelsItem, + leaveThreadItem && separator, + leaveThreadItem, ]; return items.filter(Boolean); - }, [membersItem, sidebarItem, viewSubchannelsItem, createSubchannelsItem]); + }, [ + membersItem, + sidebarItem, + viewSubchannelsItem, + createSubchannelsItem, + leaveThreadItem, + ]); const closeMenuCallback = React.useCallback(() => { document.removeEventListener('click', closeMenuCallback);