Skip to content

Commit 6c4e29a

Browse files
authored
fix: update quoted message references on message.updated and message.deleted events (#1310)
1 parent a361ee7 commit 6c4e29a

File tree

3 files changed

+73
-16
lines changed

3 files changed

+73
-16
lines changed

src/channel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,7 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
13521352
if (event.message) {
13531353
this._extendEventWithOwnReactions(event);
13541354
channelState.addMessageSorted(event.message, false, false);
1355+
channelState._updateQuotedMessageReferences({ message: event.message });
13551356
if (event.message.pinned) {
13561357
channelState.addPinnedMessage(event.message);
13571358
} else {

src/channel_state.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { Channel } from './channel';
22
import {
33
ChannelMemberResponse,
4-
FormatMessageResponse,
4+
DefaultGenerics,
55
Event,
66
ExtendableGenerics,
7-
DefaultGenerics,
8-
MessageSetType,
7+
FormatMessageResponse,
98
MessageResponse,
10-
ReactionResponse,
11-
UserResponse,
9+
MessageSetType,
1210
PendingMessageResponse,
13-
PollVote,
1411
PollResponse,
12+
PollVote,
13+
ReactionResponse,
14+
UserResponse,
1515
} from './types';
1616
import { addToMessageList } from './utils';
1717

@@ -242,14 +242,13 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
242242
*/
243243
if (parentID && !initializing) {
244244
const thread = this.threads[parentID] || [];
245-
const threadMessages = this._addToMessageList(
245+
this.threads[parentID] = this._addToMessageList(
246246
thread,
247247
message,
248248
timestampChanged,
249249
'created_at',
250250
addIfDoesNotExist,
251251
);
252-
this.threads[parentID] = threadMessages;
253252
}
254253
}
255254

@@ -349,7 +348,13 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
349348
return messageWithReaction;
350349
}
351350

352-
removeQuotedMessageReferences(message: MessageResponse<StreamChatGenerics>) {
351+
_updateQuotedMessageReferences({
352+
message,
353+
remove,
354+
}: {
355+
message: MessageResponse<StreamChatGenerics>;
356+
remove?: boolean;
357+
}) {
353358
const parseMessage = (m: ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>) =>
354359
(({
355360
...m,
@@ -358,14 +363,26 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
358363
updated_at: m.updated_at?.toISOString(),
359364
} as unknown) as MessageResponse<StreamChatGenerics>);
360365

361-
this.messageSets.forEach((set) => {
362-
const updatedMessages = set.messages
363-
.filter((msg) => msg.quoted_message_id === message.id)
364-
.map(parseMessage)
365-
.map((msg) => ({ ...msg, quoted_message: { ...message, attachments: [] } }));
366-
366+
const update = (messages: FormatMessageResponse<StreamChatGenerics>[]) => {
367+
const updatedMessages = messages.reduce<MessageResponse<StreamChatGenerics>[]>((acc, msg) => {
368+
if (msg.quoted_message_id === message.id) {
369+
acc.push({ ...parseMessage(msg), quoted_message: remove ? { ...message, attachments: [] } : message });
370+
}
371+
return acc;
372+
}, []);
367373
this.addMessagesSorted(updatedMessages, true);
368-
});
374+
};
375+
376+
if (!message.parent_id) {
377+
this.messageSets.forEach((set) => update(set.messages));
378+
} else if (message.parent_id && this.threads[message.parent_id]) {
379+
// prevent going through all the threads even though it is possible to quote a message from another thread
380+
update(this.threads[message.parent_id]);
381+
}
382+
}
383+
384+
removeQuotedMessageReferences(message: MessageResponse<StreamChatGenerics>) {
385+
this._updateQuotedMessageReferences({ message, remove: true });
369386
}
370387

371388
/**

test/unit/channel.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,45 @@ describe('Channel _handleChannelEvent', function () {
542542
});
543543
});
544544

545+
it('should update quoted_message references on "message.updated" and "message.deleted" event', () => {
546+
const originalText = 'XX';
547+
const updatedText = 'YY';
548+
const parent_id = '0';
549+
const parentMesssage = generateMsg({ date: new Date(0).toISOString(), id: parent_id });
550+
const quoted_message = generateMsg({
551+
date: new Date(2).toISOString(),
552+
id: 'quoted-message',
553+
text: originalText,
554+
});
555+
const quotingMessage = generateMsg({
556+
date: new Date(3).toISOString(),
557+
id: 'quoting-message',
558+
quoted_message,
559+
quoted_message_id: quoted_message.id,
560+
});
561+
const updatedQuotedMessage = { ...quoted_message, text: updatedText };
562+
const updatedQuotedThreadReply = { ...quoted_message, parent_id, text: updatedText };
563+
[
564+
[quoted_message, quotingMessage], // channel message
565+
[parentMesssage, { ...quoted_message, parent_id }, { ...quotingMessage, parent_id }], // thread message
566+
].forEach((messages) => {
567+
['message.updated', 'message.deleted'].forEach((eventType) => {
568+
channel.state.addMessagesSorted(messages);
569+
const isThread = messages.length === 3;
570+
const quotingMessage = messages[messages.length - 1];
571+
const event = {
572+
type: eventType,
573+
message: isThread ? updatedQuotedThreadReply : updatedQuotedMessage,
574+
};
575+
channel._handleChannelEvent(event);
576+
expect(
577+
channel.state.findMessage(quotingMessage.id, quotingMessage.parent_id).quoted_message.text,
578+
).to.equal(updatedQuotedMessage.text);
579+
channel.state.clearMessages();
580+
});
581+
});
582+
});
583+
545584
it('should mark channel visible on channel.visible event', () => {
546585
const channelVisibleEvent = {
547586
type: 'channel.visible',

0 commit comments

Comments
 (0)