diff --git a/web/CommIcon.react.js b/web/CommIcon.react.js --- a/web/CommIcon.react.js +++ b/web/CommIcon.react.js @@ -15,7 +15,9 @@ | 'reply-filled' | 'megaphone' | 'copy-filled' - | 'emote-smile-filled'; + | 'emote-smile-filled' + | 'pin' + | 'unpin'; type CommIconProps = { +icon: CommIcons, diff --git a/web/modals/chat/toggle-pin-modal.css b/web/modals/chat/toggle-pin-modal.css new file mode 100644 diff --git a/web/modals/chat/toggle-pin-modal.react.js b/web/modals/chat/toggle-pin-modal.react.js new file mode 100644 --- /dev/null +++ b/web/modals/chat/toggle-pin-modal.react.js @@ -0,0 +1,18 @@ +// @flow + +import * as React from 'react'; + +import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js'; +import type { ThreadInfo } from 'lib/types/thread-types.js'; + +type TogglePinModalProps = { + +item: ChatMessageInfoItem, + +threadInfo: ThreadInfo, +}; + +// eslint-disable-next-line no-unused-vars +function TogglePinModal(props: TogglePinModalProps): React.Node { + return <>; +} + +export default TogglePinModal; diff --git a/web/utils/tooltip-utils.js b/web/utils/tooltip-utils.js --- a/web/utils/tooltip-utils.js +++ b/web/utils/tooltip-utils.js @@ -4,6 +4,7 @@ import _debounce from 'lodash/debounce.js'; import * as React from 'react'; +import { useModalContext } from 'lib/components/modal-provider.react.js'; import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js'; import { createMessageReply } from 'lib/shared/message-utils.js'; import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js'; @@ -30,6 +31,7 @@ import { useTooltipContext } from '../chat/tooltip-provider.js'; import CommIcon from '../CommIcon.react.js'; import { InputStateContext } from '../input/input-state.js'; +import TogglePinModal from '../modals/chat/toggle-pin-modal.react.js'; import { useOnClickPendingSidebar, useOnClickThread, @@ -481,6 +483,38 @@ }, [canCreateReactionFromMessage, setShouldRenderEmojiKeyboard]); } +function useMessageTogglePinAction( + item: ChatMessageInfoItem, + threadInfo: ThreadInfo, +): ?MessageTooltipAction { + const { pushModal } = useModalContext(); + const { messageInfo, isPinned } = item; + + const canTogglePin = + isComposableMessageType(messageInfo.type) && + threadHasPermission(threadInfo, threadPermissions.MANAGE_PINS); + + return React.useMemo(() => { + if (!canTogglePin) { + return null; + } + + const iconName = isPinned ? 'unpin' : 'pin'; + + const buttonContent = ; + + const onClickTogglePin = () => { + pushModal(); + }; + + return { + actionButtonContent: buttonContent, + onClick: onClickTogglePin, + label: isPinned ? 'Unpin' : 'Pin', + }; + }, [canTogglePin, isPinned, pushModal, item, threadInfo]); +} + function useMessageTooltipActions( item: ChatMessageInfoItem, threadInfo: ThreadInfo, @@ -489,9 +523,17 @@ const replyAction = useMessageTooltipReplyAction(item, threadInfo); const copyAction = useMessageCopyAction(item); const reactAction = useMessageReactAction(item, threadInfo); + const togglePinAction = useMessageTogglePinAction(item, threadInfo); return React.useMemo( - () => [replyAction, sidebarAction, copyAction, reactAction].filter(Boolean), - [replyAction, sidebarAction, copyAction, reactAction], + () => + [ + replyAction, + sidebarAction, + copyAction, + reactAction, + togglePinAction, + ].filter(Boolean), + [replyAction, sidebarAction, copyAction, reactAction, togglePinAction], ); }