diff --git a/lib/hooks/promote-sidebar.react.js b/lib/hooks/promote-sidebar.react.js --- a/lib/hooks/promote-sidebar.react.js +++ b/lib/hooks/promote-sidebar.react.js @@ -8,7 +8,7 @@ } from '../actions/thread-actions'; import { createLoadingStatusSelector } from '../selectors/loading-selectors'; import { threadInfoSelector } from '../selectors/thread-selectors'; -import { threadHasPermission } from '../shared/thread-utils'; +import { threadHasPermission, threadIsSidebar } from '../shared/thread-utils'; import type { LoadingStatus } from '../types/loading-types'; import { threadTypes, @@ -18,6 +18,25 @@ import { useServerCall, useDispatchActionPromise } from '../utils/action-utils'; import { useSelector } from '../utils/redux-utils'; +function canPromoteSidebar( + sidebarThreadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, +): boolean { + if (!threadIsSidebar(sidebarThreadInfo)) { + return false; + } + + const canChangeThreadType = threadHasPermission( + sidebarThreadInfo, + threadPermissions.EDIT_PERMISSIONS, + ); + const canCreateSubchannelsInParent = threadHasPermission( + parentThreadInfo, + threadPermissions.CREATE_SUBCHANNELS, + ); + return canChangeThreadType && canCreateSubchannelsInParent; +} + type PromoteSidebarType = { +onPromoteSidebar: () => void, +loading: LoadingStatus, @@ -39,18 +58,8 @@ const parentThreadInfo: ?ThreadInfo = useSelector(state => parentThreadID ? threadInfoSelector(state)[parentThreadID] : null, ); - const canChangeThreadType = threadHasPermission( - threadInfo, - threadPermissions.EDIT_PERMISSIONS, - ); - const canCreateSubchannelsInParent = threadHasPermission( - parentThreadInfo, - threadPermissions.CREATE_SUBCHANNELS, - ); - const canPromoteSidebar = - threadInfo.type === threadTypes.SIDEBAR && - canChangeThreadType && - canCreateSubchannelsInParent; + + const canPromote = canPromoteSidebar(threadInfo, parentThreadInfo); const onClick = React.useCallback(() => { try { @@ -73,12 +82,12 @@ () => ({ onPromoteSidebar: onClick, loading: loadingStatus, - canPromoteSidebar, + canPromoteSidebar: canPromote, }), - [onClick, loadingStatus, canPromoteSidebar], + [onClick, loadingStatus, canPromote], ); return returnValues; } -export { usePromoteSidebar }; +export { usePromoteSidebar, canPromoteSidebar }; diff --git a/web/modals/threads/notifications/notifications-modal.css b/web/modals/threads/notifications/notifications-modal.css --- a/web/modals/threads/notifications/notifications-modal.css +++ b/web/modals/threads/notifications/notifications-modal.css @@ -3,8 +3,15 @@ flex-direction: column; color: var(--fg); margin: 24px 32px; - row-gap: 40px; + row-gap: 20px; min-width: 343px; + width: min-content; +} + +p.notice { + text-align: center; + font-size: var(--xs-font-12); + color: var(--notification-settings-option-color); } div.optionsContainer { diff --git a/web/modals/threads/notifications/notifications-modal.react.js b/web/modals/threads/notifications/notifications-modal.react.js --- a/web/modals/threads/notifications/notifications-modal.react.js +++ b/web/modals/threads/notifications/notifications-modal.react.js @@ -6,6 +6,7 @@ updateSubscription, updateSubscriptionActionTypes, } from 'lib/actions/user-actions'; +import { canPromoteSidebar } from 'lib/hooks/promote-sidebar.react'; import { threadInfoSelector } from 'lib/selectors/thread-selectors'; import { threadIsSidebar } from 'lib/shared/thread-utils'; import { @@ -91,6 +92,10 @@ const { onClose, threadID } = props; const threadInfo = useSelector(state => threadInfoSelector(state)[threadID]); const { subscription } = threadInfo.currentUser; + const { parentThreadID } = threadInfo; + const parentThreadInfo = useSelector(state => + parentThreadID ? threadInfoSelector(state)[parentThreadID] : null, + ); const isSidebar = threadIsSidebar(threadInfo); const initialThreadSetting = React.useMemo(() => { @@ -192,9 +197,53 @@ ? 'Thread notifications' : 'Channel notifications'; - return ( - -
+ let modalContent; + if (isSidebar && !parentThreadInfo?.currentUser.subscription.home) { + modalContent = ( + <> +

+ {'It’s not possible to change the notif settings for a thread ' + + 'whose parent is in Background. That’s because Comm’s design ' + + 'always shows threads underneath their parent in the Inbox, ' + + 'which means that if a thread’s parent is in Background, the ' + + 'thread must also be there.'} +

+

+ {canPromoteSidebar(threadInfo, parentThreadInfo) + ? 'If you want to change the notif settings for this thread, ' + + 'you can either change the notif settings for the parent, ' + + 'or you can promote the thread to a channel.' + : 'If you want to change the notif settings for this thread, ' + + 'you’ll have to change the notif settings for the parent.'} +

+ + ); + } else { + let noticeText = null; + if (isSidebar) { + noticeText = ( + <> +

+ {'It’s not possible to move this thread to Background. ' + + 'That’s because Comm’s design always shows threads ' + + 'underneath their parent in the Inbox, which means ' + + 'that if a thread’s parent is in Focused, the thread ' + + 'must also be there.'} +

+

+ {canPromoteSidebar(threadInfo, parentThreadInfo) + ? 'If you want to move this thread to Background, ' + + 'you can either move the parent to Background, ' + + 'or you can promote the thread to a channel.' + : 'If you want to move this thread to Background, ' + + 'you’ll have to move the parent to Background.'} +

+ + ); + } + + modalContent = ( + <>
{focusedItem} {focusedBadgeOnlyItem} @@ -207,7 +256,14 @@ > Save -
+ {noticeText} + + ); + } + + return ( + +
{modalContent}
); }