Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: update quoted message references on message.updated and message.deleted events #1310

Merged
merged 2 commits into from
Jun 3, 2024
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,7 @@ export class Channel<StreamChatGenerics extends ExtendableGenerics = DefaultGene
if (event.message) {
this._extendEventWithOwnReactions(event);
channelState.addMessageSorted(event.message, false, false);
channelState._updateQuotedMessageReferences({ message: event.message });
if (event.message.pinned) {
channelState.addPinnedMessage(event.message);
} else {
Expand Down
49 changes: 33 additions & 16 deletions src/channel_state.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Channel } from './channel';
import {
ChannelMemberResponse,
FormatMessageResponse,
DefaultGenerics,
Event,
ExtendableGenerics,
DefaultGenerics,
MessageSetType,
FormatMessageResponse,
MessageResponse,
ReactionResponse,
UserResponse,
MessageSetType,
PendingMessageResponse,
PollVote,
PollResponse,
PollVote,
ReactionResponse,
UserResponse,
} from './types';
import { addToMessageList } from './utils';

Expand Down Expand Up @@ -242,14 +242,13 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
*/
if (parentID && !initializing) {
const thread = this.threads[parentID] || [];
const threadMessages = this._addToMessageList(
this.threads[parentID] = this._addToMessageList(
thread,
message,
timestampChanged,
'created_at',
addIfDoesNotExist,
);
this.threads[parentID] = threadMessages;
}
}

Expand Down Expand Up @@ -349,7 +348,13 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
return messageWithReaction;
}

removeQuotedMessageReferences(message: MessageResponse<StreamChatGenerics>) {
_updateQuotedMessageReferences({
message,
remove,
}: {
message: MessageResponse<StreamChatGenerics>;
remove?: boolean;
}) {
const parseMessage = (m: ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>) =>
(({
...m,
Expand All @@ -358,14 +363,26 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
updated_at: m.updated_at?.toISOString(),
} as unknown) as MessageResponse<StreamChatGenerics>);

this.messageSets.forEach((set) => {
const updatedMessages = set.messages
.filter((msg) => msg.quoted_message_id === message.id)
.map(parseMessage)
.map((msg) => ({ ...msg, quoted_message: { ...message, attachments: [] } }));

const update = (messages: FormatMessageResponse<StreamChatGenerics>[]) => {
const updatedMessages = messages.reduce<MessageResponse<StreamChatGenerics>[]>((acc, msg) => {
if (msg.quoted_message_id === message.id) {
acc.push({ ...parseMessage(msg), quoted_message: remove ? { ...message, attachments: [] } : message });
}
return acc;
}, []);
this.addMessagesSorted(updatedMessages, true);
});
};

if (!message.parent_id) {
this.messageSets.forEach((set) => update(set.messages));
} else if (message.parent_id && this.threads[message.parent_id]) {
// prevent going through all the threads even though it is possible to quote a message from another thread
update(this.threads[message.parent_id]);
}
}

removeQuotedMessageReferences(message: MessageResponse<StreamChatGenerics>) {
this._updateQuotedMessageReferences({ message, remove: true });
}

/**
Expand Down
39 changes: 39 additions & 0 deletions test/unit/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,45 @@ describe('Channel _handleChannelEvent', function () {
});
});

it('should update quoted_message references on "message.updated" and "message.deleted" event', () => {
const originalText = 'XX';
const updatedText = 'YY';
const parent_id = '0';
const parentMesssage = generateMsg({ date: new Date(0).toISOString(), id: parent_id });
const quoted_message = generateMsg({
date: new Date(2).toISOString(),
id: 'quoted-message',
text: originalText,
});
const quotingMessage = generateMsg({
date: new Date(3).toISOString(),
id: 'quoting-message',
quoted_message,
quoted_message_id: quoted_message.id,
});
const updatedQuotedMessage = { ...quoted_message, text: updatedText };
const updatedQuotedThreadReply = { ...quoted_message, parent_id, text: updatedText };
[
[quoted_message, quotingMessage], // channel message
[parentMesssage, { ...quoted_message, parent_id }, { ...quotingMessage, parent_id }], // thread message
].forEach((messages) => {
['message.updated', 'message.deleted'].forEach((eventType) => {
channel.state.addMessagesSorted(messages);
const isThread = messages.length === 3;
const quotingMessage = messages[messages.length - 1];
const event = {
type: eventType,
message: isThread ? updatedQuotedThreadReply : updatedQuotedMessage,
};
channel._handleChannelEvent(event);
expect(
channel.state.findMessage(quotingMessage.id, quotingMessage.parent_id).quoted_message.text,
).to.equal(updatedQuotedMessage.text);
channel.state.clearMessages();
});
});
});

it('should mark channel visible on channel.visible event', () => {
const channelVisibleEvent = {
type: 'channel.visible',
Expand Down
Loading