Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .changeset/easy-laws-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes non-deterministic comparator in team's channel desertion table
1 change: 1 addition & 0 deletions apps/meteor/app/api/server/v1/invites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ const invites = API.v1
},
async function action() {
const { token } = this.bodyParams;
// eslint-disable-next-line react-hooks/rules-of-hooks
return API.v1.success(await useInviteToken(this.userId, token));
},
)
Expand Down
10 changes: 10 additions & 0 deletions apps/meteor/app/autotranslate/client/lib/autotranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ export const AutoTranslate = {
}
}

if (attachment.description && attachment.translations && attachment.translations[language]) {
attachment.translations.original = attachment.description;

if (autoTranslateShowInverse) {
attachment.description = attachment.translations.original;
} else {
attachment.description = attachment.translations[language];
}
}

if (attachment.attachments && attachment.attachments.length > 0) {
// @ts-expect-error - not sure what to do with this
attachment.attachments = this.translateAttachments(attachment.attachments, language);
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/autotranslate/server/autotranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ export abstract class AutoTranslate {
if (message.attachments && message.attachments.length > 0) {
setImmediate(async () => {
for (const [index, attachment] of message.attachments?.entries() ?? []) {
if (attachment.text) {
if (attachment.description || attachment.text) {
// Removes the initial link `[ ](quoterl)` from quote message before translation
const translatedText = attachment?.text?.replace(/\[(.*?)\]\(.*?\)/g, '$1') || attachment?.text;
const attachmentMessage = { ...attachment, text: translatedText };
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/autotranslate/server/deeplTranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class DeeplAutoTranslate extends AutoTranslate {
params: {
auth_key: this.apiKey,
target_lang: language,
text: attachment.text || '',
text: attachment.description || attachment.text || '',
},
});
if (!result.ok) {
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/autotranslate/server/googleTranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class GoogleAutoTranslate extends AutoTranslate {
key: this.apiKey,
target: language,
format: 'text',
q: attachment.text || '',
q: attachment.description || attachment.text || '',
},
});
if (!result.ok) {
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/autotranslate/server/msTranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ class MsAutoTranslate extends AutoTranslate {
return this._translate(
[
{
Text: attachment.text || '',
Text: attachment.description || attachment.text || '',
},
],
targetLanguages,
Expand Down
9 changes: 7 additions & 2 deletions apps/meteor/app/lib/server/functions/notifications/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,13 @@ export async function getEmailContent({ message, user, room }) {
}

if (hasFiles) {
const fileParts = files.map((file) => {
return escapeHTML(file.name);
const attachments = message.attachments || [];
const fileParts = files.map((file, index) => {
let part = escapeHTML(file.name);
if (attachments[index]?.description) {
part += `<br/><br/>${escapeHTML(attachments[index].description)}`;
}
return part;
});
contentParts.push(fileParts.join('<br/><br/>'));
}
Expand Down
2 changes: 2 additions & 0 deletions apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ export const sendNotification = async ({
const firstAttachment = message.attachments?.length && message.attachments.shift();

if (firstAttachment) {
firstAttachment.description =
typeof firstAttachment.description === 'string' ? emojione.shortnameToUnicode(firstAttachment.description) : undefined;
firstAttachment.text = typeof firstAttachment.text === 'string' ? emojione.shortnameToUnicode(firstAttachment.text) : undefined;
}

Expand Down
9 changes: 8 additions & 1 deletion apps/meteor/app/lib/server/methods/updateMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export async function executeUpdateMessage(
// IF the message has custom fields, always update
// Ideally, we'll compare the custom fields to check for change, but since we don't know the shape of
// custom fields, as it's user defined, we're gonna update
const msgText = originalMessage.msg;
const msgText = originalMessage?.attachments?.[0]?.description ?? originalMessage.msg;
if (msgText === message.msg && !previewUrls && !message.customFields) {
return;
}
Expand Down Expand Up @@ -86,6 +86,13 @@ export async function executeUpdateMessage(
}
await canSendMessageAsync(message.rid, { uid: user._id, username: user.username ?? undefined, ...user });

// It is possible to have an empty array as the attachments property, so ensure both things exist
if (originalMessage.attachments && originalMessage.attachments.length > 0 && originalMessage.attachments[0].description !== undefined) {
originalMessage.attachments[0].description = message.msg;
message.attachments = originalMessage.attachments;
message.msg = originalMessage.msg;
}

message.u = originalMessage.u;

return updateMessage(message, user, originalMessage, previewUrls);
Expand Down
5 changes: 4 additions & 1 deletion apps/meteor/app/livechat/server/lib/sendTranscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,17 @@ export async function sendTranscript({

const messageType = MessageTypes.getType(message);

const messageContent = messageType?.system
let messageContent = messageType?.system
? DOMPurify.sanitize(`
<i>${messageType.text(i18n.cloneInstance({ interpolation: { escapeValue: false } }).t, message)}}</i>`)
: escapeHtml(message.msg);

let filesHTML = '';

if (message.attachments && message.attachments?.length > 0) {
messageContent = message.attachments[0].description || '';
escapeHtml(messageContent);

for await (const attachment of message.attachments) {
if (!isFileAttachment(attachment)) {
continue;
Expand Down
5 changes: 4 additions & 1 deletion apps/meteor/app/slackbridge/server/RocketAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,14 @@ export default class RocketAdapter {

if (rocketMessage.file.name) {
let fileName = rocketMessage.file.name;
const text = rocketMessage.msg;
let text = rocketMessage.msg;

const attachment = this.getMessageAttachment(rocketMessage);
if (attachment) {
fileName = Meteor.absoluteUrl(attachment.title_link);
if (!text) {
text = attachment.description;
}
}

await slack.postMessage(slack.getSlackChannel(rocketMessage.rid), { ...rocketMessage, msg: `${text} ${fileName}` });
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/ui/client/lib/ChatMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class ChatMessages implements ChatAPI {
},
editMessage: async (message: IMessage, { cursorAtStart = false }: { cursorAtStart?: boolean } = {}) => {
this.composer?.uploads.clear();
const text = (await this.data.getDraft(message._id)) || message.msg;
const text = (await this.data.getDraft(message._id)) || message.attachments?.[0]?.description || message.msg;

await this.currentEditingMessage.stop();

Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/client/apps/gameCenter/GameCenter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { IExternalComponent } from '@rocket.chat/apps-engine/definition/externalComponent';
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { useRoomToolbox } from '@rocket.chat/ui-contexts';
import { useState } from 'react';
import type { MouseEvent } from 'react';
Expand All @@ -18,9 +18,9 @@ const GameCenter = () => {

const result = useExternalComponentsQuery();

const handleClose = useEffectEvent(() => closeTab());
const handleClose = useStableCallback(() => closeTab());

const handleBack = useEffectEvent((e: MouseEvent) => {
const handleBack = useStableCallback((e: MouseEvent) => {
setOpenedGame(undefined);
preventSyntheticEvent(e);
});
Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/client/components/ConfirmOwnerChangeModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box } from '@rocket.chat/fuselage';
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { GenericModal } from '@rocket.chat/ui-client';
import type { ComponentPropsWithoutRef } from 'react';
import { Trans } from 'react-i18next';
Expand All @@ -18,7 +18,7 @@ const ConfirmOwnerChangeModal = ({
onConfirm,
onCancel,
}: ConfirmOwnerChangeModalProps) => {
const getChangeOwnerRooms = useEffectEvent(() => {
const getChangeOwnerRooms = useStableCallback(() => {
if (shouldChangeOwner.length === 0) {
return '';
}
Expand Down Expand Up @@ -50,7 +50,7 @@ const ConfirmOwnerChangeModal = ({
);
});

const getRemovedRooms = useEffectEvent(() => {
const getRemovedRooms = useStableCallback(() => {
if (shouldBeRemoved.length === 0) {
return '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
FieldRow,
FieldError,
} from '@rocket.chat/fuselage-forms';
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { GenericModal } from '@rocket.chat/ui-client';
import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts';
import { useMutation } from '@tanstack/react-query';
Expand Down Expand Up @@ -69,7 +69,7 @@ const CreateDiscussion = ({
},
});

const onParentRoomChange = useEffectEvent((room: IRoom | undefined) => {
const onParentRoomChange = useStableCallback((room: IRoom | undefined) => {
if (!room) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { useEmbeddedLayout } from '@rocket.chat/ui-client';
import { useLayout, useSession } from '@rocket.chat/ui-contexts';
import { memo } from 'react';
Expand All @@ -10,7 +10,7 @@ const SideBarToggler = () => {
const isLayoutEmbedded = useEmbeddedLayout();
const unreadMessagesBadge = useSession('unread') as number | string | undefined;

const toggleSidebar = useEffectEvent(() => sidebar.toggle());
const toggleSidebar = useStableCallback(() => sidebar.toggle());

return (
<SidebarTogglerButton
Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/client/components/avatar/RoomAvatarEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isRoomFederated } from '@rocket.chat/core-typings';
import type { IRoom, RoomAdminFieldsType } from '@rocket.chat/core-typings';
import { css } from '@rocket.chat/css-in-js';
import { Box, Button, ButtonGroup } from '@rocket.chat/fuselage';
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import { RoomAvatar } from '@rocket.chat/ui-avatar';
import { useToastMessageDispatch } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
Expand All @@ -24,7 +24,7 @@ const RoomAvatarEditor = ({ disabled = false, room, roomAvatar, onChangeAvatar }
const { t } = useTranslation();
const dispatchToastMessage = useToastMessageDispatch();

const handleChangeAvatar = useEffectEvent(async (file: File) => {
const handleChangeAvatar = useStableCallback(async (file: File) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = async (): Promise<void> => {
Expand All @@ -38,7 +38,7 @@ const RoomAvatarEditor = ({ disabled = false, room, roomAvatar, onChangeAvatar }
});

const [clickUpload, reset] = useSingleFileInput(handleChangeAvatar);
const clickReset = useEffectEvent(() => {
const clickReset = useStableCallback(() => {
reset();
onChangeAvatar(null);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { Box, ButtonGroup } from '@rocket.chat/fuselage';
import { useEffectEvent } from '@rocket.chat/fuselage-hooks';
import { useStableCallback } from '@rocket.chat/fuselage-hooks';
import type { Keys as IconName } from '@rocket.chat/icons';
import type { TranslationKey } from '@rocket.chat/ui-contexts';

Expand All @@ -22,7 +22,7 @@ type MessageActionsProps = {
};

const MessageActions = ({ message, actions }: MessageActionsProps) => {
const runAction = useEffectEvent((action: string) => () => {
const runAction = useStableCallback((action: string) => () => {
actionLinks.run(action, message);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { useMediaUrl } from '@rocket.chat/ui-contexts';
import { useMemo } from 'react';

import { useReloadOnError } from './hooks/useReloadOnError';
import MarkdownText from '../../../../MarkdownText';
import MessageCollapsible from '../../../MessageCollapsible';
import MessageContentBody from '../../../MessageContentBody';

const AudioAttachment = ({
title,
audio_url: url,
audio_type: type,
audio_size: size,
description,
descriptionMd,
title_link: link,
title_link_download: hasDownload,
collapsed,
Expand All @@ -21,6 +25,7 @@ const AudioAttachment = ({

return (
<>
{descriptionMd ? <MessageContentBody md={descriptionMd} /> : <MarkdownText parseEmoji content={description} />}
<MessageCollapsible title={title} hasDownload={hasDownload} link={getURL(link || url)} size={size} isCollapsed={collapsed}>
<AudioPlayer src={src} type={type} ref={mediaRef} />
</MessageCollapsible>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import { useTranslation } from 'react-i18next';

import { getFileExtension } from '../../../../../../lib/utils/getFileExtension';
import { forAttachmentDownload, registerDownloadForUid } from '../../../../../hooks/useDownloadFromServiceWorker';
import MarkdownText from '../../../../MarkdownText';
import MessageCollapsible from '../../../MessageCollapsible';
import MessageContentBody from '../../../MessageContentBody';
import AttachmentSize from '../structure/AttachmentSize';
import { useOpenEncryptedPdf } from './hooks/useOpenEncryptedPdf';

Expand All @@ -23,6 +25,8 @@ type GenericFileAttachmentProps = MessageAttachmentBase;

const GenericFileAttachment = ({
title,
description,
descriptionMd,
title_link: link,
title_link_download: hasDownload,
size,
Expand Down Expand Up @@ -81,6 +85,7 @@ const GenericFileAttachment = ({

return (
<>
{descriptionMd ? <MessageContentBody md={descriptionMd} /> : <MarkdownText parseEmoji content={description} />}
<MessageCollapsible title={title} hasDownload={hasDownload} link={link} isCollapsed={collapsed}>
<MessageGenericPreview style={{ maxWidth: 368, width: '100%' }}>
<MessageGenericPreviewContent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import type { ImageAttachmentProps } from '@rocket.chat/core-typings';
import { useMediaUrl } from '@rocket.chat/ui-contexts';

import { useLoadImage } from './hooks/useLoadImage';
import MarkdownText from '../../../../MarkdownText';
import MessageCollapsible from '../../../MessageCollapsible';
import MessageContentBody from '../../../MessageContentBody';
import AttachmentImage from '../structure/AttachmentImage';

const ImageAttachment = ({
Expand All @@ -16,6 +18,7 @@ const ImageAttachment = ({
height: 368,
},
description,
descriptionMd,
title_link: link,
title_link_download: hasDownload,
collapsed,
Expand All @@ -25,6 +28,7 @@ const ImageAttachment = ({

return (
<>
{descriptionMd ? <MessageContentBody md={descriptionMd} /> : <MarkdownText parseEmoji content={description} />}
<MessageCollapsible title={title} hasDownload={hasDownload} link={getURL(link || url)} size={size} isCollapsed={collapsed}>
<AttachmentImage
{...imageDimensions}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import { useMemo } from 'react';

import { useReloadOnError } from './hooks/useReloadOnError';
import { userAgentMIMETypeFallback } from '../../../../../lib/utils/userAgentMIMETypeFallback';
import MarkdownText from '../../../../MarkdownText';
import MessageCollapsible from '../../../MessageCollapsible';
import MessageContentBody from '../../../MessageContentBody';

const VideoAttachment = ({
title,
video_url: url,
video_type: type,
video_size: size,
description,
descriptionMd,
title_link: link,
title_link_download: hasDownload,
collapsed,
Expand All @@ -22,6 +26,7 @@ const VideoAttachment = ({

return (
<>
{descriptionMd ? <MessageContentBody md={descriptionMd} /> : <MarkdownText parseEmoji content={description} />}
<MessageCollapsible title={title} hasDownload={hasDownload} link={getURL(link || url)} size={size} isCollapsed={collapsed}>
<MessageGenericPreview style={{ maxWidth: 368, width: '100%' }}>
<Box is='video' controls preload='metadata' ref={mediaRef}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffectEvent, useSafeRefCallback } from '@rocket.chat/fuselage-hooks';
import { useStableCallback, useSafeRefCallback } from '@rocket.chat/fuselage-hooks';
import { useCallback, useRef, useState } from 'react';

const events = ['error', 'stalled', 'play'];
Expand Down Expand Up @@ -52,7 +52,7 @@ export const useReloadOnError = (url: string, type: 'video' | 'audio') => {
const isRecovering = useRef(false);
const firstRecoveryAttempted = useRef(false);

const handleMediaURLRecovery = useEffectEvent(async (event: Event) => {
const handleMediaURLRecovery = useStableCallback(async (event: Event) => {
if (isRecovering.current) {
console.debug(`Media URL recovery already in progress, skipping ${event.type} event`);
return;
Expand Down
Loading
Loading