From 56155531743d449a895e3871766ad59229069aa1 Mon Sep 17 00:00:00 2001 From: Tasso Date: Tue, 10 Dec 2024 14:44:28 -0300 Subject: [PATCH] Segregate items as components --- .../app/ui-utils/client/lib/MessageAction.ts | 2 +- .../message/toolbar/MessageToolbar.tsx | 97 +++++++------------ .../message/toolbar/MessageToolbarItem.tsx | 35 +++++++ .../message/toolbar/items/DefaultItems.tsx | 26 +++++ .../message/toolbar/items/DirectItems.tsx | 16 +++ .../message/toolbar/items/FederatedItems.tsx | 24 +++++ .../message/toolbar/items/MentionsItems.tsx | 20 ++++ .../message/toolbar/items/MobileItems.tsx | 28 ++++++ .../message/toolbar/items/PinnedItems.tsx | 20 ++++ .../message/toolbar/items/SearchItems.tsx | 20 ++++ .../message/toolbar/items/StarredItems.tsx | 20 ++++ .../message/toolbar/items/ThreadsItems.tsx | 26 +++++ .../message/toolbar/items/VideoconfItems.tsx | 22 +++++ .../toolbar/items/VideoconfThreadsItems.tsx | 22 +++++ .../items/actions/ForwardMessageAction.tsx | 43 ++++++++ .../items/actions/JumpToMessageAction.tsx | 29 ++++++ .../items/actions/QuoteMessageAction.tsx | 43 ++++++++ .../items/actions/ReactionMessageAction.tsx | 62 ++++++++++++ .../actions/ReplyInThreadMessageAction.tsx | 48 +++++++++ .../toolbar/useForwardMessageAction.tsx | 41 -------- .../toolbar/useJumpToMessageContextAction.tsx | 33 ------- .../message/toolbar/useQuoteMessageAction.ts | 43 -------- .../toolbar/useReactionMessageAction.ts | 42 -------- .../toolbar/useReplyInThreadMessageAction.ts | 48 --------- 24 files changed, 539 insertions(+), 271 deletions(-) create mode 100644 apps/meteor/client/components/message/toolbar/MessageToolbarItem.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/DefaultItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/DirectItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/FederatedItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/MentionsItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/MobileItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/PinnedItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/SearchItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/StarredItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/ThreadsItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/VideoconfItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/VideoconfThreadsItems.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/actions/ForwardMessageAction.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/actions/JumpToMessageAction.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/actions/QuoteMessageAction.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/actions/ReactionMessageAction.tsx create mode 100644 apps/meteor/client/components/message/toolbar/items/actions/ReplyInThreadMessageAction.tsx delete mode 100644 apps/meteor/client/components/message/toolbar/useForwardMessageAction.tsx delete mode 100644 apps/meteor/client/components/message/toolbar/useJumpToMessageContextAction.tsx delete mode 100644 apps/meteor/client/components/message/toolbar/useQuoteMessageAction.ts delete mode 100644 apps/meteor/client/components/message/toolbar/useReactionMessageAction.ts delete mode 100644 apps/meteor/client/components/message/toolbar/useReplyInThreadMessageAction.ts diff --git a/apps/meteor/app/ui-utils/client/lib/MessageAction.ts b/apps/meteor/app/ui-utils/client/lib/MessageAction.ts index 426caea0ecf9..c7b2836a6a3a 100644 --- a/apps/meteor/app/ui-utils/client/lib/MessageAction.ts +++ b/apps/meteor/app/ui-utils/client/lib/MessageAction.ts @@ -2,7 +2,7 @@ import type { Keys as IconName } from '@rocket.chat/icons'; import type { TranslationKey } from '@rocket.chat/ui-contexts'; import mem from 'mem'; -type MessageActionGroup = 'message' | 'menu'; +type MessageActionGroup = 'menu'; export type MessageActionContext = | 'message' diff --git a/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx b/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx index e64acfc40c5a..79c939811e6a 100644 --- a/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx +++ b/apps/meteor/client/components/message/toolbar/MessageToolbar.tsx @@ -1,30 +1,35 @@ import { useToolbar } from '@react-aria/toolbar'; import type { IMessage, IRoom, ISubscription, ITranslatedMessage } from '@rocket.chat/core-typings'; import { isThreadMessage, isRoomFederated, isVideoConfMessage, isE2EEMessage } from '@rocket.chat/core-typings'; -import { MessageToolbar as FuselageMessageToolbar, MessageToolbarItem } from '@rocket.chat/fuselage'; -import { useFeaturePreview } from '@rocket.chat/ui-client'; -import { useUser, useTranslation, useMethod, useLayoutHiddenActions, useSetting } from '@rocket.chat/ui-contexts'; +import { MessageToolbar as FuselageMessageToolbar } from '@rocket.chat/fuselage'; +import { useUser, useTranslation, useLayoutHiddenActions } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; -import type { ComponentProps, ReactElement } from 'react'; +import type { ComponentProps, ElementType, ReactElement } from 'react'; import React, { memo, useRef } from 'react'; import MessageActionMenu from './MessageActionMenu'; import MessageToolbarStarsActionMenu from './MessageToolbarStarsActionMenu'; +import DefaultItems from './items/DefaultItems'; +import DirectItems from './items/DirectItems'; +import FederatedItems from './items/FederatedItems'; +import MentionsItems from './items/MentionsItems'; +import MobileItems from './items/MobileItems'; +import PinnedItems from './items/PinnedItems'; +import SearchItems from './items/SearchItems'; +import StarredItems from './items/StarredItems'; +import ThreadsItems from './items/ThreadsItems'; +import VideoconfItems from './items/VideoconfItems'; +import VideoconfThreadsItems from './items/VideoconfThreadsItems'; import { useCopyAction } from './useCopyAction'; import { useDeleteMessageAction } from './useDeleteMessageAction'; import { useEditMessageAction } from './useEditMessageAction'; import { useFollowMessageAction } from './useFollowMessageAction'; -import { useForwardMessageAction } from './useForwardMessageAction'; -import { useJumpToMessageContextAction } from './useJumpToMessageContextAction'; import { useMarkAsUnreadMessageAction } from './useMarkAsUnreadMessageAction'; import { useNewDiscussionMessageAction } from './useNewDiscussionMessageAction'; import { usePermalinkAction } from './usePermalinkAction'; import { usePinMessageAction } from './usePinMessageAction'; -import { useQuoteMessageAction } from './useQuoteMessageAction'; -import { useReactionMessageAction } from './useReactionMessageAction'; import { useReadReceiptsDetailsAction } from './useReadReceiptsDetailsAction'; import { useReplyInDMAction } from './useReplyInDMAction'; -import { useReplyInThreadMessageAction } from './useReplyInThreadMessageAction'; import { useReportMessageAction } from './useReportMessageAction'; import { useShowMessageReactionsAction } from './useShowMessageReactionsAction'; import { useStarMessageAction } from './useStarMessageAction'; @@ -36,11 +41,9 @@ import { useViewOriginalTranslationAction } from './useViewOriginalTranslationAc import { useWebDAVMessageAction } from './useWebDAVMessageAction'; import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction'; import { MessageAction } from '../../../../app/ui-utils/client/lib/MessageAction'; -import { useEmojiPickerData } from '../../../contexts/EmojiPickerContext'; import { useMessageActionAppsActionButtons } from '../../../hooks/useAppActionButtons'; import { useEmbeddedLayout } from '../../../hooks/useEmbeddedLayout'; import { roomsQueryKeys } from '../../../lib/queryKeys'; -import EmojiElement from '../../../views/composer/EmojiPicker/EmojiElement'; const getMessageContext = (message: IMessage, room: IRoom, context?: MessageActionContext): MessageActionContext => { if (context) { @@ -62,6 +65,23 @@ const getMessageContext = (message: IMessage, room: IRoom, context?: MessageActi return 'message'; }; +const itemsByContext: Record< + MessageActionContext, + ElementType<{ message: IMessage; room: IRoom; subscription: ISubscription | undefined }> +> = { + 'message': DefaultItems, + 'message-mobile': MobileItems, + 'threads': ThreadsItems, + 'videoconf': VideoconfItems, + 'videoconf-threads': VideoconfThreadsItems, + 'pinned': PinnedItems, + 'direct': DirectItems, + 'starred': StarredItems, + 'mentions': MentionsItems, + 'federated': FederatedItems, + 'search': SearchItems, +}; + type MessageToolbarProps = { message: IMessage & Partial; messageContext?: MessageActionContext; @@ -85,41 +105,15 @@ const MessageToolbar = ({ const toolbarRef = useRef(null); const { toolbarProps } = useToolbar(props, toolbarRef); - const quickReactionsEnabled = useFeaturePreview('quickReactions'); - - const setReaction = useMethod('setReaction'); - const context = getMessageContext(message, room, messageContext); - const { quickReactions, addRecentEmoji } = useEmojiPickerData(); - const actionButtonApps = useMessageActionAppsActionButtons(message, context); const starsAction = useMessageActionAppsActionButtons(message, context, 'ai'); const hiddenActions = useLayoutHiddenActions().messageToolbox; - const allowStarring = useSetting('Message_AllowStarring', true); // TODO: move this to another place - useReactionMessageAction(message, { user, room, subscription }); - useQuoteMessageAction(message, { subscription }); - useReplyInThreadMessageAction(message, { room, subscription }); - useForwardMessageAction(message); - useJumpToMessageContextAction(message, { - id: 'jump-to-message', - context: ['mentions', 'threads', 'videoconf-threads', 'message-mobile', 'search'], - }); - useJumpToMessageContextAction(message, { - id: 'jump-to-pin-message', - hidden: !subscription, - context: ['pinned', 'direct'], - }); - useJumpToMessageContextAction(message, { - id: 'jump-to-star-message', - hidden: !allowStarring || !subscription, - context: ['starred'], - }); - useWebDAVMessageAction(message, { subscription }); useNewDiscussionMessageAction(message, { user, room, subscription }); useUnpinMessageAction(message, { room, subscription }); @@ -151,47 +145,24 @@ const MessageToolbar = ({ const { isSuccess, data } = useQuery({ queryKey: roomsQueryKeys.messageActionsWithParameters(room._id, message), queryFn: async () => { - const toolboxItems = await MessageAction.getAll(context, 'message'); const menuItems = await MessageAction.getAll(context, 'menu'); return { - message: toolboxItems.filter((action) => !hiddenActions.includes(action.id)), menu: menuItems.filter((action) => !(isLayoutEmbedded && action.id === 'reply-directly') && !hiddenActions.includes(action.id)), }; }, keepPreviousData: true, }); - if (!data?.message.length && !data?.menu.length) { + if (!data?.menu.length) { return null; } - const isReactionAllowed = data?.message.find(({ id }) => id === 'reaction-message'); - - const handleSetReaction = (emoji: string) => { - setReaction(`:${emoji}:`, message._id); - addRecentEmoji(emoji); - }; + const Items = itemsByContext[context]; return ( - {quickReactionsEnabled && - isReactionAllowed && - quickReactions.slice(0, 3).map(({ emoji, image }) => { - return handleSetReaction(emoji)} />; - })} - {isSuccess && - data.message.map((action) => ( - action.action(e)} - key={action.id} - icon={action.icon} - title={action?.disabled ? t('Action_not_available_encrypted_content', { action: t(action.label) }) : t(action.label)} - data-qa-id={action.label} - data-qa-type='message-action-menu' - disabled={action?.disabled} - /> - ))} + {starsAction.data && starsAction.data.length > 0 && ( ({ diff --git a/apps/meteor/client/components/message/toolbar/MessageToolbarItem.tsx b/apps/meteor/client/components/message/toolbar/MessageToolbarItem.tsx new file mode 100644 index 000000000000..368a3b6d6acd --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/MessageToolbarItem.tsx @@ -0,0 +1,35 @@ +import { MessageToolbarItem as FuselageMessageToolbarItem } from '@rocket.chat/fuselage'; +import type { Keys as IconName } from '@rocket.chat/icons'; +import { useLayoutHiddenActions } from '@rocket.chat/ui-contexts'; +import type { MouseEventHandler } from 'react'; +import React from 'react'; + +type MessageToolbarItemProps = { + id: string; + icon: IconName; + title: string; + disabled?: boolean; + qa: string; + onClick: MouseEventHandler; +}; + +const MessageToolbarItem = ({ id, icon, title, disabled, qa, onClick }: MessageToolbarItemProps) => { + const hiddenActions = useLayoutHiddenActions().messageToolbox; + + if (hiddenActions.includes(id)) { + return null; + } + + return ( + + ); +}; + +export default MessageToolbarItem; diff --git a/apps/meteor/client/components/message/toolbar/items/DefaultItems.tsx b/apps/meteor/client/components/message/toolbar/items/DefaultItems.tsx new file mode 100644 index 000000000000..d7c4a9f9baa2 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/DefaultItems.tsx @@ -0,0 +1,26 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import ForwardMessageAction from './actions/ForwardMessageAction'; +import QuoteMessageAction from './actions/QuoteMessageAction'; +import ReactionMessageAction from './actions/ReactionMessageAction'; +import ReplyInThreadMessageAction from './actions/ReplyInThreadMessageAction'; + +type DefaultItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const DefaultItems = ({ message, room, subscription }: DefaultItemsProps) => { + return ( + <> + + + + + + ); +}; + +export default DefaultItems; diff --git a/apps/meteor/client/components/message/toolbar/items/DirectItems.tsx b/apps/meteor/client/components/message/toolbar/items/DirectItems.tsx new file mode 100644 index 000000000000..0b729e5ac28e --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/DirectItems.tsx @@ -0,0 +1,16 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import JumpToMessageAction from './actions/JumpToMessageAction'; + +type DirectItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const DirectItems = ({ message, subscription }: DirectItemsProps) => { + return <>{!!subscription && }; +}; + +export default DirectItems; diff --git a/apps/meteor/client/components/message/toolbar/items/FederatedItems.tsx b/apps/meteor/client/components/message/toolbar/items/FederatedItems.tsx new file mode 100644 index 000000000000..536dc114b698 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/FederatedItems.tsx @@ -0,0 +1,24 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import QuoteMessageAction from './actions/QuoteMessageAction'; +import ReactionMessageAction from './actions/ReactionMessageAction'; +import ReplyInThreadMessageAction from './actions/ReplyInThreadMessageAction'; + +type FederatedItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const FederatedItems = ({ message, room, subscription }: FederatedItemsProps) => { + return ( + <> + + + + + ); +}; + +export default FederatedItems; diff --git a/apps/meteor/client/components/message/toolbar/items/MentionsItems.tsx b/apps/meteor/client/components/message/toolbar/items/MentionsItems.tsx new file mode 100644 index 000000000000..03e363787d58 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/MentionsItems.tsx @@ -0,0 +1,20 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import JumpToMessageAction from './actions/JumpToMessageAction'; + +type MentionsItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const MentionsItems = ({ message }: MentionsItemsProps) => { + return ( + <> + + + ); +}; + +export default MentionsItems; diff --git a/apps/meteor/client/components/message/toolbar/items/MobileItems.tsx b/apps/meteor/client/components/message/toolbar/items/MobileItems.tsx new file mode 100644 index 000000000000..fde71116b3b5 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/MobileItems.tsx @@ -0,0 +1,28 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import ForwardMessageAction from './actions/ForwardMessageAction'; +import JumpToMessageAction from './actions/JumpToMessageAction'; +import QuoteMessageAction from './actions/QuoteMessageAction'; +import ReactionMessageAction from './actions/ReactionMessageAction'; +import ReplyInThreadMessageAction from './actions/ReplyInThreadMessageAction'; + +type MobileItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const MobileItems = ({ message, room, subscription }: MobileItemsProps) => { + return ( + <> + + + + + + + ); +}; + +export default MobileItems; diff --git a/apps/meteor/client/components/message/toolbar/items/PinnedItems.tsx b/apps/meteor/client/components/message/toolbar/items/PinnedItems.tsx new file mode 100644 index 000000000000..f854952add04 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/PinnedItems.tsx @@ -0,0 +1,20 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import JumpToMessageAction from './actions/JumpToMessageAction'; + +type PinnedItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const PinnedItems = ({ message }: PinnedItemsProps) => { + return ( + <> + + + ); +}; + +export default PinnedItems; diff --git a/apps/meteor/client/components/message/toolbar/items/SearchItems.tsx b/apps/meteor/client/components/message/toolbar/items/SearchItems.tsx new file mode 100644 index 000000000000..d3bf6cfca4f1 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/SearchItems.tsx @@ -0,0 +1,20 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import JumpToMessageAction from './actions/JumpToMessageAction'; + +type SearchItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const SearchItems = ({ message }: SearchItemsProps) => { + return ( + <> + + + ); +}; + +export default SearchItems; diff --git a/apps/meteor/client/components/message/toolbar/items/StarredItems.tsx b/apps/meteor/client/components/message/toolbar/items/StarredItems.tsx new file mode 100644 index 000000000000..35f56aba73bc --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/StarredItems.tsx @@ -0,0 +1,20 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import JumpToMessageAction from './actions/JumpToMessageAction'; + +type StarredItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const StarredItems = ({ message }: StarredItemsProps) => { + return ( + <> + + + ); +}; + +export default StarredItems; diff --git a/apps/meteor/client/components/message/toolbar/items/ThreadsItems.tsx b/apps/meteor/client/components/message/toolbar/items/ThreadsItems.tsx new file mode 100644 index 000000000000..43dff5224a7e --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/ThreadsItems.tsx @@ -0,0 +1,26 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import ForwardMessageAction from './actions/ForwardMessageAction'; +import JumpToMessageAction from './actions/JumpToMessageAction'; +import QuoteMessageAction from './actions/QuoteMessageAction'; +import ReactionMessageAction from './actions/ReactionMessageAction'; + +type ThreadsItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const ThreadsItems = ({ message, room, subscription }: ThreadsItemsProps) => { + return ( + <> + + + + + + ); +}; + +export default ThreadsItems; diff --git a/apps/meteor/client/components/message/toolbar/items/VideoconfItems.tsx b/apps/meteor/client/components/message/toolbar/items/VideoconfItems.tsx new file mode 100644 index 000000000000..392d78820f2c --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/VideoconfItems.tsx @@ -0,0 +1,22 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import ReactionMessageAction from './actions/ReactionMessageAction'; +import ReplyInThreadMessageAction from './actions/ReplyInThreadMessageAction'; + +type VideoconfItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const VideoconfItems = ({ message, room, subscription }: VideoconfItemsProps) => { + return ( + <> + + + + ); +}; + +export default VideoconfItems; diff --git a/apps/meteor/client/components/message/toolbar/items/VideoconfThreadsItems.tsx b/apps/meteor/client/components/message/toolbar/items/VideoconfThreadsItems.tsx new file mode 100644 index 000000000000..819bc2f04705 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/VideoconfThreadsItems.tsx @@ -0,0 +1,22 @@ +import type { IRoom, ISubscription, IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; + +import JumpToMessageAction from './actions/JumpToMessageAction'; +import ReactionMessageAction from './actions/ReactionMessageAction'; + +type VideoconfThreadsItemsProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const VideoconfThreadsItems = ({ message, room, subscription }: VideoconfThreadsItemsProps) => { + return ( + <> + + + + ); +}; + +export default VideoconfThreadsItems; diff --git a/apps/meteor/client/components/message/toolbar/items/actions/ForwardMessageAction.tsx b/apps/meteor/client/components/message/toolbar/items/actions/ForwardMessageAction.tsx new file mode 100644 index 000000000000..88bb222d0641 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/actions/ForwardMessageAction.tsx @@ -0,0 +1,43 @@ +import { type IMessage, isE2EEMessage } from '@rocket.chat/core-typings'; +import { useSetModal } from '@rocket.chat/ui-contexts'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { getPermaLink } from '../../../../../lib/getPermaLink'; +import ForwardMessageModal from '../../../../../views/room/modals/ForwardMessageModal'; +import MessageToolbarItem from '../../MessageToolbarItem'; + +type ForwardMessageActionProps = { + message: IMessage; +}; + +const ForwardMessageAction = ({ message }: ForwardMessageActionProps) => { + const setModal = useSetModal(); + const { t } = useTranslation(); + + const encrypted = isE2EEMessage(message); + + return ( + { + const permalink = await getPermaLink(message._id); + setModal( + { + setModal(null); + }} + />, + ); + }} + /> + ); +}; + +export default ForwardMessageAction; diff --git a/apps/meteor/client/components/message/toolbar/items/actions/JumpToMessageAction.tsx b/apps/meteor/client/components/message/toolbar/items/actions/JumpToMessageAction.tsx new file mode 100644 index 000000000000..f8c72add56a6 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/actions/JumpToMessageAction.tsx @@ -0,0 +1,29 @@ +import type { IMessage } from '@rocket.chat/core-typings'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { setMessageJumpQueryStringParameter } from '../../../../../lib/utils/setMessageJumpQueryStringParameter'; +import MessageToolbarItem from '../../MessageToolbarItem'; + +type JumpToMessageActionProps = { + id: 'jump-to-message' | 'jump-to-pin-message' | 'jump-to-star-message'; + message: IMessage; +}; + +const JumpToMessageAction = ({ id, message }: JumpToMessageActionProps) => { + const { t } = useTranslation(); + + return ( + { + setMessageJumpQueryStringParameter(message._id); + }} + /> + ); +}; + +export default JumpToMessageAction; diff --git a/apps/meteor/client/components/message/toolbar/items/actions/QuoteMessageAction.tsx b/apps/meteor/client/components/message/toolbar/items/actions/QuoteMessageAction.tsx new file mode 100644 index 000000000000..f7a3d1d8cd99 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/actions/QuoteMessageAction.tsx @@ -0,0 +1,43 @@ +import type { ITranslatedMessage, IMessage, ISubscription } from '@rocket.chat/core-typings'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { useAutoTranslate } from '../../../../../views/room/MessageList/hooks/useAutoTranslate'; +import { useChat } from '../../../../../views/room/contexts/ChatContext'; +import MessageToolbarItem from '../../MessageToolbarItem'; + +type QuoteMessageActionProps = { + message: IMessage & Partial; + subscription: ISubscription | undefined; +}; + +const QuoteMessageAction = ({ message, subscription }: QuoteMessageActionProps) => { + const chat = useChat(); + const autoTranslateOptions = useAutoTranslate(subscription); + const { t } = useTranslation(); + + if (!chat || !subscription) { + return null; + } + + return ( + { + if (message && autoTranslateOptions?.autoTranslateEnabled && autoTranslateOptions.showAutoTranslate(message)) { + message.msg = + message.translations && autoTranslateOptions.autoTranslateLanguage + ? message.translations[autoTranslateOptions.autoTranslateLanguage] + : message.msg; + } + + chat?.composer?.quoteMessage(message); + }} + /> + ); +}; + +export default QuoteMessageAction; diff --git a/apps/meteor/client/components/message/toolbar/items/actions/ReactionMessageAction.tsx b/apps/meteor/client/components/message/toolbar/items/actions/ReactionMessageAction.tsx new file mode 100644 index 000000000000..5099cb13c969 --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/actions/ReactionMessageAction.tsx @@ -0,0 +1,62 @@ +import { isOmnichannelRoom, type IMessage, type IRoom, type ISubscription } from '@rocket.chat/core-typings'; +import { useFeaturePreview } from '@rocket.chat/ui-client'; +import { useUser, useMethod } from '@rocket.chat/ui-contexts'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { useEmojiPickerData } from '../../../../../contexts/EmojiPickerContext'; +import { roomCoordinator } from '../../../../../lib/rooms/roomCoordinator'; +import EmojiElement from '../../../../../views/composer/EmojiPicker/EmojiElement'; +import { useChat } from '../../../../../views/room/contexts/ChatContext'; +import MessageToolbarItem from '../../MessageToolbarItem'; + +type ReactionMessageActionProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const ReactionMessageAction = ({ message, room, subscription }: ReactionMessageActionProps) => { + const chat = useChat(); + const user = useUser(); + const setReaction = useMethod('setReaction'); + const quickReactionsEnabled = useFeaturePreview('quickReactions'); + const { quickReactions, addRecentEmoji } = useEmojiPickerData(); + const { t } = useTranslation(); + + if (!chat || !room || isOmnichannelRoom(room) || !subscription || message.private || !user) { + return null; + } + + if (roomCoordinator.readOnly(room._id, user) && !room.reactWhenReadOnly) { + return null; + } + + const toggleReaction = (emoji: string) => { + setReaction(`:${emoji}:`, message._id); + addRecentEmoji(emoji); + }; + + return ( + <> + {quickReactionsEnabled && + quickReactions.slice(0, 3).map(({ emoji, image }) => { + return toggleReaction(emoji)} />; + })} + { + event.stopPropagation(); + chat.emojiPicker.open(event.currentTarget, (emoji) => { + toggleReaction(emoji); + }); + }} + /> + + ); +}; + +export default ReactionMessageAction; diff --git a/apps/meteor/client/components/message/toolbar/items/actions/ReplyInThreadMessageAction.tsx b/apps/meteor/client/components/message/toolbar/items/actions/ReplyInThreadMessageAction.tsx new file mode 100644 index 000000000000..55f4967625ad --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/items/actions/ReplyInThreadMessageAction.tsx @@ -0,0 +1,48 @@ +import { type IMessage, type ISubscription, type IRoom, isOmnichannelRoom } from '@rocket.chat/core-typings'; +import { useRouter, useSetting } from '@rocket.chat/ui-contexts'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import MessageToolbarItem from '../../MessageToolbarItem'; + +type ReplyInThreadMessageActionProps = { + message: IMessage; + room: IRoom; + subscription: ISubscription | undefined; +}; + +const ReplyInThreadMessageAction = ({ message, room, subscription }: ReplyInThreadMessageActionProps) => { + const router = useRouter(); + const threadsEnabled = useSetting('Threads_enabled', true); + const { t } = useTranslation(); + + if (!threadsEnabled || isOmnichannelRoom(room) || !subscription) { + return null; + } + + return ( + { + event.stopPropagation(); + const routeName = router.getRouteName(); + + if (routeName) { + router.navigate({ + name: routeName, + params: { + ...router.getRouteParameters(), + tab: 'thread', + context: message.tmid || message._id, + }, + }); + } + }} + /> + ); +}; + +export default ReplyInThreadMessageAction; diff --git a/apps/meteor/client/components/message/toolbar/useForwardMessageAction.tsx b/apps/meteor/client/components/message/toolbar/useForwardMessageAction.tsx deleted file mode 100644 index ca7fc4a32976..000000000000 --- a/apps/meteor/client/components/message/toolbar/useForwardMessageAction.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { type IMessage, isE2EEMessage } from '@rocket.chat/core-typings'; -import { useSetModal } from '@rocket.chat/ui-contexts'; -import React, { useEffect } from 'react'; - -import { MessageAction } from '../../../../app/ui-utils/client'; -import { getPermaLink } from '../../../lib/getPermaLink'; -import ForwardMessageModal from '../../../views/room/modals/ForwardMessageModal'; - -export const useForwardMessageAction = (message: IMessage) => { - const encrypted = isE2EEMessage(message); - const setModal = useSetModal(); - - useEffect(() => { - MessageAction.addButton({ - id: 'forward-message', - icon: 'arrow-forward', - label: 'Forward_message', - context: ['message', 'message-mobile', 'threads'], - type: 'communication', - async action() { - const permalink = await getPermaLink(message._id); - setModal( - { - setModal(null); - }} - />, - ); - }, - order: 0, - group: 'message', - disabled: encrypted, - }); - - return () => { - MessageAction.removeButton('forward-message'); - }; - }, [encrypted, message, setModal]); -}; diff --git a/apps/meteor/client/components/message/toolbar/useJumpToMessageContextAction.tsx b/apps/meteor/client/components/message/toolbar/useJumpToMessageContextAction.tsx deleted file mode 100644 index d8f9dd912e48..000000000000 --- a/apps/meteor/client/components/message/toolbar/useJumpToMessageContextAction.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import type { IMessage } from '@rocket.chat/core-typings'; -import { useEffect } from 'react'; - -import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction'; -import { MessageAction } from '../../../../app/ui-utils/client/lib/MessageAction'; -import { setMessageJumpQueryStringParameter } from '../../../lib/utils/setMessageJumpQueryStringParameter'; - -export const useJumpToMessageContextAction = ( - message: IMessage, - { id, hidden, context }: { id: string; hidden?: boolean; context: MessageActionContext[] }, -) => { - useEffect(() => { - if (hidden) { - return; - } - - MessageAction.addButton({ - id, - icon: 'jump', - label: 'Jump_to_message', - context, - async action() { - setMessageJumpQueryStringParameter(message._id); - }, - order: 100, - group: 'message', - }); - - return () => { - MessageAction.removeButton(id); - }; - }, [hidden, context, id, message._id]); -}; diff --git a/apps/meteor/client/components/message/toolbar/useQuoteMessageAction.ts b/apps/meteor/client/components/message/toolbar/useQuoteMessageAction.ts deleted file mode 100644 index 8638e731dce1..000000000000 --- a/apps/meteor/client/components/message/toolbar/useQuoteMessageAction.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { IMessage, ISubscription, ITranslatedMessage } from '@rocket.chat/core-typings'; -import { useEffect } from 'react'; - -import { MessageAction } from '../../../../app/ui-utils/client'; -import { useAutoTranslate } from '../../../views/room/MessageList/hooks/useAutoTranslate'; -import { useChat } from '../../../views/room/contexts/ChatContext'; - -export const useQuoteMessageAction = ( - message: IMessage & Partial, - { subscription }: { subscription: ISubscription | undefined }, -) => { - const chat = useChat(); - const autoTranslateOptions = useAutoTranslate(subscription); - - useEffect(() => { - if (!subscription) { - return; - } - - MessageAction.addButton({ - id: 'quote-message', - icon: 'quote', - label: 'Quote', - context: ['message', 'message-mobile', 'threads', 'federated'], - async action() { - if (message && autoTranslateOptions?.autoTranslateEnabled && autoTranslateOptions.showAutoTranslate(message)) { - message.msg = - message.translations && autoTranslateOptions.autoTranslateLanguage - ? message.translations[autoTranslateOptions.autoTranslateLanguage] - : message.msg; - } - - await chat?.composer?.quoteMessage(message); - }, - order: -2, - group: 'message', - }); - - return () => { - MessageAction.removeButton('quote-message'); - }; - }, [autoTranslateOptions, chat?.composer, message, subscription]); -}; diff --git a/apps/meteor/client/components/message/toolbar/useReactionMessageAction.ts b/apps/meteor/client/components/message/toolbar/useReactionMessageAction.ts deleted file mode 100644 index 6f6c764c99ab..000000000000 --- a/apps/meteor/client/components/message/toolbar/useReactionMessageAction.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { isOmnichannelRoom } from '@rocket.chat/core-typings'; -import type { IRoom, ISubscription, IUser, IMessage } from '@rocket.chat/core-typings'; -import { useEffect } from 'react'; - -import { MessageAction } from '../../../../app/ui-utils/client'; -import { sdk } from '../../../../app/utils/client/lib/SDKClient'; -import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; -import { useChat } from '../../../views/room/contexts/ChatContext'; - -export const useReactionMessageAction = ( - message: IMessage, - { user, room, subscription }: { user: IUser | undefined; room: IRoom; subscription: ISubscription | undefined }, -) => { - const chat = useChat(); - - useEffect(() => { - if (!room || isOmnichannelRoom(room) || !subscription || message.private || !user) { - return; - } - - if (roomCoordinator.readOnly(room._id, user) && !room.reactWhenReadOnly) { - return; - } - - MessageAction.addButton({ - id: 'reaction-message', - icon: 'add-reaction', - label: 'Add_Reaction', - context: ['message', 'message-mobile', 'threads', 'federated', 'videoconf', 'videoconf-threads'], - action(event) { - event?.stopPropagation(); - chat?.emojiPicker.open(event?.currentTarget as Element, (emoji) => sdk.call('setReaction', `:${emoji}:`, message._id)); - }, - order: -3, - group: 'message', - }); - - return () => { - MessageAction.removeButton('reaction-message'); - }; - }, [chat?.emojiPicker, message._id, message.private, room, subscription, user]); -}; diff --git a/apps/meteor/client/components/message/toolbar/useReplyInThreadMessageAction.ts b/apps/meteor/client/components/message/toolbar/useReplyInThreadMessageAction.ts deleted file mode 100644 index 0fae8e99029b..000000000000 --- a/apps/meteor/client/components/message/toolbar/useReplyInThreadMessageAction.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { isOmnichannelRoom } from '@rocket.chat/core-typings'; -import type { IMessage, IRoom, ISubscription } from '@rocket.chat/core-typings'; -import { useSetting, useRouter } from '@rocket.chat/ui-contexts'; -import { useEffect } from 'react'; - -import { MessageAction } from '../../../../app/ui-utils/client'; - -export const useReplyInThreadMessageAction = ( - message: IMessage, - { room, subscription }: { room: IRoom; subscription: ISubscription | undefined }, -) => { - const threadsEnabled = useSetting('Threads_enabled'); - - const route = useRouter(); - - useEffect(() => { - if (!threadsEnabled || isOmnichannelRoom(room) || !subscription) { - return; - } - - MessageAction.addButton({ - id: 'reply-in-thread', - icon: 'thread', - label: 'Reply_in_thread', - context: ['message', 'message-mobile', 'federated', 'videoconf'], - action(e) { - e?.stopPropagation(); - const routeName = route.getRouteName(); - if (routeName) { - route.navigate({ - name: routeName, - params: { - ...route.getRouteParameters(), - tab: 'thread', - context: message.tmid || message._id, - }, - }); - } - }, - order: -1, - group: 'message', - }); - - return () => { - MessageAction.removeButton('reply-in-thread'); - }; - }, [message._id, message.tmid, room, route, subscription, threadsEnabled]); -};