Skip to content

Commit

Permalink
Segregate items as components
Browse files Browse the repository at this point in the history
  • Loading branch information
tassoevan committed Dec 10, 2024
1 parent ebf5196 commit 5615553
Show file tree
Hide file tree
Showing 24 changed files with 539 additions and 271 deletions.
2 changes: 1 addition & 1 deletion apps/meteor/app/ui-utils/client/lib/MessageAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
97 changes: 34 additions & 63 deletions apps/meteor/client/components/message/toolbar/MessageToolbar.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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) {
Expand All @@ -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<ITranslatedMessage>;
messageContext?: MessageActionContext;
Expand All @@ -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 });
Expand Down Expand Up @@ -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 (
<FuselageMessageToolbar ref={toolbarRef} {...toolbarProps} aria-label={t('Message_actions')} {...props}>
{quickReactionsEnabled &&
isReactionAllowed &&
quickReactions.slice(0, 3).map(({ emoji, image }) => {
return <EmojiElement small key={emoji} title={emoji} emoji={emoji} image={image} onClick={() => handleSetReaction(emoji)} />;
})}
{isSuccess &&
data.message.map((action) => (
<MessageToolbarItem
onClick={(e): void => 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}
/>
))}
<Items message={message} room={room} subscription={subscription} />
{starsAction.data && starsAction.data.length > 0 && (
<MessageToolbarStarsActionMenu
options={starsAction.data.map((action) => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<FuselageMessageToolbarItem
icon={icon}
title={title}
disabled={disabled}
data-qa-id={qa}
data-qa-type='message-action-menu'
onClick={onClick}
/>
);
};

export default MessageToolbarItem;
Original file line number Diff line number Diff line change
@@ -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 (
<>
<ReactionMessageAction message={message} room={room} subscription={subscription} />
<QuoteMessageAction message={message} subscription={subscription} />
<ReplyInThreadMessageAction message={message} room={room} subscription={subscription} />
<ForwardMessageAction message={message} />
</>
);
};

export default DefaultItems;
Original file line number Diff line number Diff line change
@@ -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 && <JumpToMessageAction id='jump-to-pin-message' message={message} />}</>;
};

export default DirectItems;
Original file line number Diff line number Diff line change
@@ -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 (
<>
<ReactionMessageAction message={message} room={room} subscription={subscription} />
<QuoteMessageAction message={message} subscription={subscription} />
<ReplyInThreadMessageAction message={message} room={room} subscription={subscription} />
</>
);
};

export default FederatedItems;
Original file line number Diff line number Diff line change
@@ -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 (
<>
<JumpToMessageAction id='jump-to-message' message={message} />
</>
);
};

export default MentionsItems;
Original file line number Diff line number Diff line change
@@ -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 (
<>
<ReactionMessageAction message={message} room={room} subscription={subscription} />
<QuoteMessageAction message={message} subscription={subscription} />
<ReplyInThreadMessageAction message={message} room={room} subscription={subscription} />
<ForwardMessageAction message={message} />
<JumpToMessageAction id='jump-to-message' message={message} />
</>
);
};

export default MobileItems;
Original file line number Diff line number Diff line change
@@ -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 (
<>
<JumpToMessageAction id='jump-to-pin-message' message={message} />
</>
);
};

export default PinnedItems;
Original file line number Diff line number Diff line change
@@ -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 (
<>
<JumpToMessageAction id='jump-to-message' message={message} />
</>
);
};

export default SearchItems;
Loading

0 comments on commit 5615553

Please sign in to comment.