Skip to content

Commit

Permalink
Rename MessageAction to MessageToolboxActions
Browse files Browse the repository at this point in the history
  • Loading branch information
tassoevan committed Mar 14, 2023
1 parent eda33c8 commit 8c3094b
Show file tree
Hide file tree
Showing 43 changed files with 162 additions and 198 deletions.
2 changes: 1 addition & 1 deletion apps/meteor/.eslintcache

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { IUIActionButton } from '@rocket.chat/apps-engine/definition/ui';

import { Utilities } from '../../../../ee/lib/misc/Utilities';
import { MessageAction } from '../../../ui-utils/client';
import { messageToolboxActions } from '../../../ui-utils/client';
import { messageArgs } from '../../../../client/lib/utils/messageArgs';
import { t } from '../../../utils/client';
import { triggerActionButtonAction } from '../ActionManager';
Expand All @@ -11,7 +11,7 @@ const getIdForActionButton = ({ appId, actionId }: IUIActionButton): string => `

// eslint-disable-next-line no-void
export const onAdded = (button: IUIActionButton): void =>
MessageAction.addButton({
messageToolboxActions.add({
id: getIdForActionButton(button),
icon: '' as any,
label: t(Utilities.getI18nKeyForApp(button.labelI18n, button.appId)) as any,
Expand All @@ -31,4 +31,4 @@ export const onAdded = (button: IUIActionButton): void =>
},
});

export const onRemoved = (button: IUIActionButton): void => MessageAction.removeButton(getIdForActionButton(button));
export const onRemoved = (button: IUIActionButton): void => messageToolboxActions.remove(getIdForActionButton(button));
2 changes: 1 addition & 1 deletion apps/meteor/app/ui-utils/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { AccountBox } from './lib/AccountBox';
export { MessageAction } from './lib/MessageAction';
export { messageToolboxActions } from './lib/MessageToolboxActions';
export { messageBox } from './lib/messageBox';
export { readMessage } from './lib/readMessages';
export { RoomManager } from './lib/RoomManager';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type { ChatContext } from '../../../../client/views/room/contexts/ChatCon
import { APIClient } from '../../../utils/client';
import type { AutoTranslateOptions } from '../../../../client/views/room/MessageList/hooks/useAutoTranslate';

const getMessage = async (msgId: string): Promise<Serialized<IMessage> | null> => {
const findMessage = async (msgId: string): Promise<Serialized<IMessage> | null> => {
try {
const { message } = await APIClient.get('/v1/chat.getMessage', { msgId });
return message;
Expand All @@ -23,8 +23,9 @@ const getMessage = async (msgId: string): Promise<Serialized<IMessage> | null> =
}
};

type MessageActionGroup = 'message' | 'menu';
export type MessageActionContext =
type MessageToolboxActionGroup = 'message' | 'menu';

export type MessageToolboxActionContext =
| 'message'
| 'threads'
| 'message-mobile'
Expand All @@ -36,26 +37,24 @@ export type MessageActionContext =
| 'videoconf'
| 'search';

type MessageActionConditionProps = {
type MessageToolboxActionConditionParams = {
message: IMessage;
user: IUser | undefined;
room: IRoom;
subscription?: ISubscription;
context?: MessageActionContext;
context?: MessageToolboxActionContext;
settings: { [key: string]: SettingValue };
chat: ContextType<typeof ChatContext>;
};

export type MessageActionConfig = {
export type MessageToolboxActionConfig = {
id: string;
icon: ComponentProps<typeof Icon>['name'];
variant?: 'danger' | 'success' | 'warning';
label: TranslationKey;
order?: number;
/* @deprecated */
color?: string;
group?: MessageActionGroup | MessageActionGroup[];
context?: MessageActionContext[];
group?: MessageToolboxActionGroup | MessageToolboxActionGroup[];
context?: MessageToolboxActionContext[];
action: (
e: UIEvent<Element>,
{
Expand All @@ -72,26 +71,15 @@ export type MessageActionConfig = {
autoTranslateOptions?: AutoTranslateOptions;
},
) => any;
condition?: (props: MessageActionConditionProps) => Promise<boolean> | boolean;
condition?: (props: MessageToolboxActionConditionParams) => Promise<boolean> | boolean;
};

type MessageActionConfigList = MessageActionConfig[];

export const MessageAction = new (class {
/*
config expects the following keys (only id is mandatory):
id (mandatory)
icon: string
label: string
action: function(event, instance)
condition: function(message)
order: integer
group: string (message or menu)
*/
type MessageToolboxActionConfigList = MessageToolboxActionConfig[];

buttons = new ReactiveVar<Record<string, MessageActionConfig>>({});
class MessageToolboxActions {
private buttons = new ReactiveVar<Record<string, MessageToolboxActionConfig>>({});

addButton(config: MessageActionConfig): void {
public add(config: MessageToolboxActionConfig): void {
if (!config?.id) {
return;
}
Expand All @@ -104,46 +92,34 @@ export const MessageAction = new (class {
config.condition = mem(config.condition, { maxAge: 1000, cacheKey: JSON.stringify });
}

return Tracker.nonreactive(() => {
Tracker.nonreactive(() => {
const btns = this.buttons.get();
btns[config.id] = config;
mem.clear(this._getButtons);
mem.clear(this.getButtonsByGroup);
return this.buttons.set(btns);
this.buttons.set(btns);
});
}

removeButton(id: MessageActionConfig['id']): void {
return Tracker.nonreactive(() => {
public remove(id: MessageToolboxActionConfig['id']): void {
Tracker.nonreactive(() => {
const btns = this.buttons.get();
delete btns[id];
return this.buttons.set(btns);
});
}

updateButton(id: MessageActionConfig['id'], config: MessageActionConfig): void {
return Tracker.nonreactive(() => {
const btns = this.buttons.get();
if (btns[id]) {
btns[id] = Object.assign(btns[id], config);
return this.buttons.set(btns);
}
this.buttons.set(btns);
});
}

getButtonById(id: MessageActionConfig['id']): MessageActionConfig | undefined {
const allButtons = this.buttons.get();
return allButtons[id];
}

_getButtons = mem((): MessageActionConfigList => Object.values(this.buttons.get()).sort((a, b) => (a.order ?? 0) - (b.order ?? 0)), {
maxAge: 1000,
});
private _getButtons = mem(
(): MessageToolboxActionConfigList => Object.values(this.buttons.get()).sort((a, b) => (a.order ?? 0) - (b.order ?? 0)),
{
maxAge: 1000,
},
);

async getButtonsByCondition(
prop: MessageActionConditionProps,
arr: MessageActionConfigList = MessageAction._getButtons(),
): Promise<MessageActionConfigList> {
private async getButtonsByCondition(
prop: MessageToolboxActionConditionParams,
arr: MessageToolboxActionConfigList = messageToolboxActions._getButtons(),
): Promise<MessageToolboxActionConfigList> {
return (
await Promise.all(
arr.map(async (button) => {
Expand All @@ -155,55 +131,52 @@ export const MessageAction = new (class {
.map(([button]) => button);
}

getButtonsByGroup = mem(
function (group: MessageActionGroup, arr: MessageActionConfigList = MessageAction._getButtons()): MessageActionConfigList {
private getButtonsByGroup = mem(
function (
group: MessageToolboxActionGroup,
arr: MessageToolboxActionConfigList = messageToolboxActions._getButtons(),
): MessageToolboxActionConfigList {
return arr.filter((button) => !button.group || (Array.isArray(button.group) ? button.group.includes(group) : button.group === group));
},
{ maxAge: 1000 },
);

getButtonsByContext(context: MessageActionContext, arr: MessageActionConfigList): MessageActionConfigList {
private getButtonsByContext(context: MessageToolboxActionContext, arr: MessageToolboxActionConfigList): MessageToolboxActionConfigList {
return !context ? arr : arr.filter((button) => !button.context || button.context.includes(context));
}

async getButtons(
props: MessageActionConditionProps,
context: MessageActionContext,
group: MessageActionGroup,
): Promise<MessageActionConfigList> {
const allButtons = group ? this.getButtonsByGroup(group) : MessageAction._getButtons();
public async get(
props: MessageToolboxActionConditionParams,
context: MessageToolboxActionContext,
group: MessageToolboxActionGroup,
): Promise<MessageToolboxActionConfigList> {
const allButtons = group ? this.getButtonsByGroup(group) : messageToolboxActions._getButtons();

if (props.message) {
return this.getButtonsByCondition({ ...props, context }, this.getButtonsByContext(context, allButtons));
}
return allButtons;
}

resetButtons(): void {
mem.clear(this._getButtons);
mem.clear(this.getButtonsByGroup);
return this.buttons.set({});
}

async getPermaLink(msgId: string): Promise<string> {
if (!msgId) {
public async getPermaLink(mid: IMessage['_id']): Promise<string> {
if (!mid) {
throw new Error('invalid-parameter');
}

const msg = Messages.findOne(msgId) || (await getMessage(msgId));
const msg = Messages.findOne(mid) || (await findMessage(mid));
if (!msg) {
throw new Error('message-not-found');
}
const roomData = Rooms.findOne({
_id: msg.rid,
});
const roomData = Rooms.findOne({ _id: msg.rid });

if (!roomData) {
throw new Error('room-not-found');
}

const subData = Subscriptions.findOne({ 'rid': roomData._id, 'u._id': Meteor.userId() });
const roomURL = roomCoordinator.getURL(roomData.t, subData || roomData);
return `${roomURL}?msg=${msgId}`;
return `${roomURL}?msg=${mid}`;
}
})();
}

export const messageToolboxActions = new MessageToolboxActions();
4 changes: 2 additions & 2 deletions apps/meteor/client/components/message/ToolboxHolder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { useQuery } from '@tanstack/react-query';
import type { ReactElement } from 'react';
import React, { memo, useRef } from 'react';

import type { MessageActionContext } from '../../../app/ui-utils/client/lib/MessageAction';
import type { MessageToolboxActionContext } from '../../../app/ui-utils/client/lib/MessageToolboxActions';
import { useChat } from '../../views/room/contexts/ChatContext';
import { useIsVisible } from '../../views/room/hooks/useIsVisible';
import Toolbox from './toolbox/Toolbox';

type ToolboxHolderProps = {
message: IMessage;
context?: MessageActionContext;
context?: MessageToolboxActionContext;
};

export const ToolboxHolder = ({ message, context }: ToolboxHolderProps): ReactElement => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ComponentProps, UIEvent, ReactElement } from 'react';
import React, { useState, Fragment, useRef } from 'react';

import type { MessageActionConfig } from '../../../../app/ui-utils/client/lib/MessageAction';
import type { MessageToolboxActionConfig } from '../../../../app/ui-utils/client/lib/MessageToolboxActions';
import { useEmbeddedLayout } from '../../../hooks/useEmbeddedLayout';
import ToolboxDropdown from './ToolboxDropdown';

type MessageActionConfigOption = Omit<MessageActionConfig, 'condition' | 'context' | 'order' | 'action'> & {
type MessageActionConfigOption = Omit<MessageToolboxActionConfig, 'condition' | 'context' | 'order' | 'action'> & {
action: (event: UIEvent) => void;
};

Expand All @@ -22,18 +22,13 @@ export const MessageActionMenu = ({ options, ...props }: MessageActionMenuProps)
const [visible, setVisible] = useState(false);
const isLayoutEmbedded = useEmbeddedLayout();

const groupOptions = options
.map(({ color, ...option }) => ({
...option,
...(color === 'alert' && { variant: 'danger' as const }),
}))
.reduce((acc, option) => {
const group = option.variant ? option.variant : '';
acc[group] = acc[group] || [];
if (!(isLayoutEmbedded && option.id === 'reply-directly')) acc[group].push(option);
const groupOptions = options.reduce((acc, option) => {
const group = option.variant ? option.variant : '';
acc[group] = acc[group] || [];
if (!(isLayoutEmbedded && option.id === 'reply-directly')) acc[group].push(option);

return acc;
}, {} as { [key: string]: MessageActionConfigOption[] }) as {
return acc;
}, {} as { [key: string]: MessageActionConfigOption[] }) as {
[key: string]: MessageActionConfigOption[];
};

Expand Down
12 changes: 6 additions & 6 deletions apps/meteor/client/components/message/toolbox/Toolbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { useQuery } from '@tanstack/react-query';
import type { ReactElement } from 'react';
import React, { memo, useMemo } from 'react';

import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction';
import { MessageAction } from '../../../../app/ui-utils/client/lib/MessageAction';
import type { MessageToolboxActionContext } from '../../../../app/ui-utils/client/lib/MessageToolboxActions';
import { messageToolboxActions } from '../../../../app/ui-utils/client/lib/MessageToolboxActions';
import { useIsSelecting } from '../../../views/room/MessageList/contexts/SelectedMessagesContext';
import { useAutoTranslate } from '../../../views/room/MessageList/hooks/useAutoTranslate';
import { useChat } from '../../../views/room/contexts/ChatContext';
import { useToolboxContext } from '../../../views/room/contexts/ToolboxContext';
import MessageActionMenu from './MessageActionMenu';

const getMessageContext = (message: IMessage, room: IRoom, context?: MessageActionContext): MessageActionContext => {
const getMessageContext = (message: IMessage, room: IRoom, context?: MessageToolboxActionContext): MessageToolboxActionContext => {
if (context) {
return context;
}
Expand All @@ -36,7 +36,7 @@ const getMessageContext = (message: IMessage, room: IRoom, context?: MessageActi

type ToolboxProps = {
message: IMessage & Partial<ITranslatedMessage>;
messageContext?: MessageActionContext;
messageContext?: MessageToolboxActionContext;
room: IRoom;
subscription?: ISubscription;
};
Expand All @@ -54,12 +54,12 @@ const Toolbox = ({ message, messageContext, room, subscription }: ToolboxProps):
const chat = useChat();

const actionsQueryResult = useQuery(['rooms', room._id, 'messages', message._id, 'actions'] as const, async () => {
const messageActions = await MessageAction.getButtons(
const messageActions = await messageToolboxActions.get(
{ message, room, user: user ?? undefined, subscription, settings: mapSettings, chat },
context,
'message',
);
const menuActions = await MessageAction.getButtons(
const menuActions = await messageToolboxActions.get(
{ message, room, user: user ?? undefined, subscription, settings: mapSettings, chat },
context,
'menu',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useUserId } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React, { useRef, memo } from 'react';

import type { MessageActionContext } from '../../../../app/ui-utils/client/lib/MessageAction';
import type { MessageToolboxActionContext } from '../../../../app/ui-utils/client/lib/MessageToolboxActions';
import { useIsMessageHighlight } from '../../../views/room/MessageList/contexts/MessageHighlightContext';
import {
useIsSelecting,
Expand All @@ -28,7 +28,7 @@ type RoomMessageProps = {
unread: boolean;
mention: boolean;
all: boolean;
context?: MessageActionContext;
context?: MessageToolboxActionContext;
ignoredUser?: boolean;
searchText?: string;
};
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/client/lib/chats/ChatAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type DataAPI = {
getSubscription(): Promise<ISubscription>;
findSubscriptionFromMessage(message: IMessage): Promise<ISubscription | undefined>;
getSubscriptionFromMessage(message: IMessage): Promise<ISubscription>;
prependReplies(msg: string, replies?: IMessage[]): Promise<string>;
};

export type UploadsAPI = {
Expand Down
Loading

0 comments on commit 8c3094b

Please sign in to comment.