Skip to content

Commit a6b93a6

Browse files
authored
Merge branch 'develop' into feat/openapi-webdav
2 parents b5abb9a + eb3d03f commit a6b93a6

File tree

13 files changed

+120
-54
lines changed

13 files changed

+120
-54
lines changed

.changeset/hungry-games-smoke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@rocket.chat/meteor': patch
3+
---
4+
5+
Blocks edit message action for Off-The-Record (OTR) messages.

apps/meteor/app/ui/client/lib/ChatMessages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export class ChatMessages implements ChatAPI {
6464
}
6565

6666
if (!this.currentEditing) {
67-
let lastMessage = await this.data.findLastOwnMessage();
67+
let lastMessage = await this.data.findPreviousOwnMessage();
6868

6969
// Videoconf messages should not be edited
7070
if (lastMessage && isVideoConfMessage(lastMessage)) {

apps/meteor/client/components/message/toolbar/useEditMessageAction.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isRoomFederated } from '@rocket.chat/core-typings';
1+
import { isOTRAckMessage, isOTRMessage, isRoomFederated } from '@rocket.chat/core-typings';
22
import type { IRoom, IMessage, ISubscription } from '@rocket.chat/core-typings';
33
import { usePermission, useSetting, useUser } from '@rocket.chat/ui-contexts';
44
import moment from 'moment';
@@ -26,6 +26,10 @@ export const useEditMessageAction = (
2626
return message.u._id === user?._id;
2727
}
2828

29+
if (isOTRMessage(message) || isOTRAckMessage(message)) {
30+
return false;
31+
}
32+
2933
const editOwn = message.u && message.u._id === user?._id;
3034
if (!canEditMessage && (!isEditAllowed || !editOwn)) {
3135
return false;

apps/meteor/client/components/message/variants/RoomMessage.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { IMessage } from '@rocket.chat/core-typings';
1+
import { type IMessage, isOTRAckMessage, isOTRMessage } from '@rocket.chat/core-typings';
22
import { Message, MessageLeftContainer, MessageContainer, CheckBox } from '@rocket.chat/fuselage';
33
import { useToggle } from '@rocket.chat/fuselage-hooks';
44
import { MessageAvatar } from '@rocket.chat/ui-avatar';
@@ -55,24 +55,23 @@ const RoomMessage = ({
5555
const { openUserCard, triggerProps } = useUserCard();
5656

5757
const selecting = useIsSelecting();
58-
const isOTRMessage = message.t === 'otr' || message.t === 'otr-ack';
58+
const isOTRMsg = isOTRMessage(message) || isOTRAckMessage(message);
5959

6060
const toggleSelected = useToggleSelect(message._id);
61-
const selected = useIsSelectedMessage(message._id, isOTRMessage);
61+
const selected = useIsSelectedMessage(message._id, isOTRMsg);
6262

6363
useCountSelected();
64-
6564
const messageRef = useJumpToMessage(message._id);
6665

6766
return (
6867
<Message
6968
ref={messageRef}
7069
id={message._id}
7170
role='listitem'
72-
aria-roledescription={t('message')}
71+
aria-roledescription={isOTRMsg ? t('OTR_message') : t('message')}
7372
tabIndex={0}
7473
aria-labelledby={`${message._id}-displayName ${message._id}-time ${message._id}-content ${message._id}-read-status`}
75-
onClick={selecting && !isOTRMessage ? toggleSelected : undefined}
74+
onClick={selecting && !isOTRMsg ? toggleSelected : undefined}
7675
isSelected={selected}
7776
isEditing={editing}
7877
isPending={message.temp}
@@ -101,7 +100,7 @@ const RoomMessage = ({
101100
{...triggerProps}
102101
/>
103102
)}
104-
{selecting && <CheckBox disabled={isOTRMessage} checked={selected} onChange={toggleSelected} />}
103+
{selecting && <CheckBox disabled={isOTRMsg} checked={selected} onChange={toggleSelected} />}
105104
{sequential && <StatusIndicators message={message} />}
106105
</MessageLeftContainer>
107106
<MessageContainer>

apps/meteor/client/components/message/variants/ThreadMessagePreview.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { IThreadMessage } from '@rocket.chat/core-typings';
1+
import { isOTRAckMessage, isOTRMessage, type IThreadMessage } from '@rocket.chat/core-typings';
22
import {
33
Skeleton,
44
ThreadMessage,
@@ -45,10 +45,10 @@ const ThreadMessagePreview = ({ message, showUserAvatar, sequential, ...props }:
4545
const { t } = useTranslation();
4646

4747
const isSelecting = useIsSelecting();
48-
const isOTRMessage = message.t === 'otr' || message.t === 'otr-ack';
48+
const isOTRMsg = isOTRMessage(message) || isOTRAckMessage(message);
4949

5050
const toggleSelected = useToggleSelect(message._id);
51-
const isSelected = useIsSelectedMessage(message._id, isOTRMessage);
51+
const isSelected = useIsSelectedMessage(message._id, isOTRMsg);
5252
useCountSelected();
5353

5454
const messageType = parentMessage.isSuccess ? MessageTypes.getType(parentMessage.data) : null;
@@ -67,7 +67,7 @@ const ThreadMessagePreview = ({ message, showUserAvatar, sequential, ...props }:
6767
return goToThread({ rid: message.rid, tmid: message.tmid, msg: message._id });
6868
}
6969

70-
if (isOTRMessage) {
70+
if (isOTRMsg) {
7171
return;
7272
}
7373

@@ -77,7 +77,7 @@ const ThreadMessagePreview = ({ message, showUserAvatar, sequential, ...props }:
7777
return (
7878
<ThreadMessage
7979
role='link'
80-
aria-roledescription='thread message preview'
80+
aria-roledescription={isOTRMsg ? t('OTR_thread_message_preview') : t('thread_message_preview')}
8181
tabIndex={0}
8282
onClick={handleThreadClick}
8383
onKeyDown={(e) => e.code === 'Enter' && handleThreadClick()}
@@ -123,7 +123,7 @@ const ThreadMessagePreview = ({ message, showUserAvatar, sequential, ...props }:
123123
size='x18'
124124
/>
125125
)}
126-
{isSelecting && <CheckBox disabled={isOTRMessage} checked={isSelected} onChange={toggleSelected} />}
126+
{isSelecting && <CheckBox disabled={isOTRMsg} checked={isSelected} onChange={toggleSelected} />}
127127
</ThreadMessageLeftContainer>
128128
<ThreadMessageContainer>
129129
<ThreadMessageBody>

apps/meteor/client/lib/chats/ChatAPI.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,7 @@ export type DataAPI = {
6868
getMessageByID(mid: IMessage['_id']): Promise<IMessage>;
6969
findLastMessage(): Promise<IMessage | undefined>;
7070
getLastMessage(): Promise<IMessage>;
71-
findLastOwnMessage(): Promise<IMessage | undefined>;
72-
getLastOwnMessage(): Promise<IMessage>;
73-
findPreviousOwnMessage(message: IMessage): Promise<IMessage | undefined>;
71+
findPreviousOwnMessage(message?: IMessage): Promise<IMessage | undefined>;
7472
getPreviousOwnMessage(message: IMessage): Promise<IMessage>;
7573
findNextOwnMessage(message: IMessage): Promise<IMessage | undefined>;
7674
getNextOwnMessage(message: IMessage): Promise<IMessage>;

apps/meteor/client/lib/chats/data.ts

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import type { IEditedMessage, IMessage, IRoom, ISubscription } from '@rocket.chat/core-typings';
1+
import {
2+
isOTRAckMessage,
3+
isOTRMessage,
4+
type IEditedMessage,
5+
type IMessage,
6+
type IRoom,
7+
type ISubscription,
8+
} from '@rocket.chat/core-typings';
29
import { Random } from '@rocket.chat/random';
310
import moment from 'moment';
411

@@ -57,34 +64,15 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage
5764
return message;
5865
};
5966

60-
const findLastOwnMessage = async (): Promise<IMessage | undefined> => {
61-
const uid = Meteor.userId();
62-
63-
if (!uid) {
64-
return undefined;
65-
}
66-
67-
return Messages.findOne(
68-
{ rid, 'tmid': tmid ?? { $exists: false }, 'u._id': uid, '_hidden': { $ne: true } },
69-
{ sort: { ts: -1 }, reactive: false },
70-
);
71-
};
72-
73-
const getLastOwnMessage = async (): Promise<IMessage> => {
74-
const message = await findLastOwnMessage();
75-
76-
if (!message) {
77-
throw new Error('Message not found');
78-
}
79-
80-
return message;
81-
};
82-
8367
const canUpdateMessage = async (message: IMessage): Promise<boolean> => {
8468
if (MessageTypes.isSystemMessage(message)) {
8569
return false;
8670
}
8771

72+
if (isOTRMessage(message) || isOTRAckMessage(message)) {
73+
return false;
74+
}
75+
8876
const canEditMessage = hasAtLeastOnePermission('edit-message', message.rid);
8977
const editAllowed = (settings.get('Message_AllowEditing') as boolean | undefined) ?? false;
9078
const editOwn = message?.u && message.u._id === Meteor.userId();
@@ -104,15 +92,15 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage
10492
return true;
10593
};
10694

107-
const findPreviousOwnMessage = async (message: IMessage): Promise<IMessage | undefined> => {
95+
const findPreviousOwnMessage = async (message?: IMessage): Promise<IMessage | undefined> => {
10896
const uid = Meteor.userId();
10997

11098
if (!uid) {
11199
return undefined;
112100
}
113101

114102
const msg = Messages.findOne(
115-
{ rid, 'tmid': tmid ?? { $exists: false }, 'u._id': uid, '_hidden': { $ne: true }, 'ts': { $lt: message.ts } },
103+
{ rid, 'tmid': tmid ?? { $exists: false }, 'u._id': uid, '_hidden': { $ne: true }, 'ts': { ...(message && { $lt: message.ts }) } },
116104
{ sort: { ts: -1 }, reactive: false },
117105
);
118106

@@ -308,8 +296,6 @@ export const createDataAPI = ({ rid, tmid }: { rid: IRoom['_id']; tmid: IMessage
308296
getMessageByID,
309297
findLastMessage,
310298
getLastMessage,
311-
findLastOwnMessage,
312-
getLastOwnMessage,
313299
findPreviousOwnMessage,
314300
getPreviousOwnMessage,
315301
findNextOwnMessage,

apps/meteor/client/lib/chats/flows/sendMessage.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[],
2323
return;
2424
}
2525

26-
message = (await onClientBeforeSendMessage(message)) as IMessage;
26+
message = (await onClientBeforeSendMessage({ ...message, isEditing: !!chat.currentEditing })) as IMessage & { isEditing?: boolean };
2727

2828
// e2e should be a client property only
2929
delete message.e2e;
30+
delete (message as IMessage & { isEditing?: boolean }).isEditing;
3031

3132
if (await processMessageEditing(chat, message, previewUrls)) {
3233
return;

apps/meteor/client/lib/onClientBeforeSendMessage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import type { AtLeast, IMessage } from '@rocket.chat/core-typings';
22

33
import { createAsyncTransformChain } from '../../lib/transforms';
44

5-
export const onClientBeforeSendMessage = createAsyncTransformChain<AtLeast<IMessage, '_id' | 'rid' | 'msg'>>();
5+
export const onClientBeforeSendMessage = createAsyncTransformChain<AtLeast<IMessage, '_id' | 'rid' | 'msg'> & { isEditing?: boolean }>();

apps/meteor/client/views/root/hooks/useOTRMessaging.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,18 @@ export const useOTRMessaging = (uid: string) => {
2424
};
2525

2626
const handleBeforeSendMessage = async (
27-
message: AtLeast<IMessage, '_id' | 'rid' | 'msg'>,
27+
message: AtLeast<IMessage, '_id' | 'rid' | 'msg'> & { isEditing?: boolean },
2828
): Promise<AtLeast<IMessage, '_id' | 'rid' | 'msg'>> => {
2929
if (!uid) {
3030
return message;
3131
}
3232

33-
const otrRoom = OTR.getInstanceByRoomId(uid, message.rid);
33+
if (message.isEditing) {
34+
return (({ isEditing: _isEditing, ...rest }) => rest)(message);
35+
}
3436

37+
delete message.isEditing;
38+
const otrRoom = OTR.getInstanceByRoomId(uid, message.rid);
3539
if (otrRoom && otrRoom.getState() === OtrRoomState.ESTABLISHED) {
3640
const msg = await otrRoom.encrypt(message);
3741
return { ...message, msg, t: 'otr' };

0 commit comments

Comments
 (0)