Skip to content

Commit 2365e5b

Browse files
committed
fix: quoted message edited update bug
1 parent 66dc1ca commit 2365e5b

File tree

7 files changed

+109
-70
lines changed

7 files changed

+109
-70
lines changed

package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ export const useLatestMessagePreview = (
256256
const translatedLastMessage = useTranslatedMessage(lastMessage);
257257

258258
const channelLastMessageString = translatedLastMessage
259-
? stringifyMessage(translatedLastMessage)
259+
? stringifyMessage({ message: translatedLastMessage })
260260
: '';
261261

262262
const readEvents = useMemo(() => {

package/src/components/Message/Message.tsx

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { useStableCallback } from '../../hooks';
3636
import { isVideoPlayerAvailable, NativeHandlers } from '../../native';
3737
import { FileTypes } from '../../types/types';
3838
import {
39+
checkMessageEquality,
3940
hasOnlyEmojis,
4041
isBlockedMessage,
4142
isBouncedMessage,
@@ -822,28 +823,16 @@ const areEqual = (prevProps: MessagePropsWithContext, nextProps: MessagePropsWit
822823
return false;
823824
}
824825

825-
const isPrevMessageTypeDeleted = prevMessage.type === 'deleted';
826-
const isNextMessageTypeDeleted = nextMessage.type === 'deleted';
827-
828-
const messageEqual =
829-
isPrevMessageTypeDeleted === isNextMessageTypeDeleted &&
830-
prevMessage.status === nextMessage.status &&
831-
prevMessage.type === nextMessage.type &&
832-
prevMessage.text === nextMessage.text &&
833-
prevMessage.pinned === nextMessage.pinned &&
834-
`${prevMessage?.updated_at}` === `${nextMessage?.updated_at}` &&
835-
prevMessage.i18n === nextMessage.i18n;
826+
const messageEqual = checkMessageEquality(prevMessage, nextMessage);
836827

837828
if (!messageEqual) {
838829
return false;
839830
}
840831

841-
const isPrevQuotedMessageTypeDeleted = prevMessage.quoted_message?.type === 'deleted';
842-
const isNextQuotedMessageTypeDeleted = nextMessage.quoted_message?.type === 'deleted';
843-
844-
const quotedMessageEqual =
845-
prevMessage.quoted_message?.id === nextMessage.quoted_message?.id &&
846-
isPrevQuotedMessageTypeDeleted === isNextQuotedMessageTypeDeleted;
832+
const quotedMessageEqual = checkMessageEquality(
833+
prevMessage.quoted_message,
834+
nextMessage.quoted_message,
835+
);
847836

848837
if (!quotedMessageEqual) {
849838
return false;

package/src/components/Message/MessageSimple/MessageContent.tsx

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828

2929
import { useViewport } from '../../../hooks/useViewport';
3030

31+
import { checkMessageEquality, checkQuotedMessageEquality } from '../../../utils/utils';
3132
import { Poll } from '../../Poll/Poll';
3233
import { useMessageData } from '../hooks/useMessageData';
3334

@@ -412,27 +413,16 @@ const areEqual = (
412413
return false;
413414
}
414415

415-
const isPrevMessageTypeDeleted = prevMessage.type === 'deleted';
416-
const isNextMessageTypeDeleted = nextMessage.type === 'deleted';
417-
418-
const messageEqual =
419-
isPrevMessageTypeDeleted === isNextMessageTypeDeleted &&
420-
prevMessage.reply_count === nextMessage.reply_count &&
421-
prevMessage.status === nextMessage.status &&
422-
prevMessage.type === nextMessage.type &&
423-
prevMessage.text === nextMessage.text &&
424-
prevMessage.pinned === nextMessage.pinned &&
425-
prevMessage.i18n === nextMessage.i18n;
416+
const messageEqual = checkMessageEquality(prevMessage, nextMessage);
426417
if (!messageEqual) {
427418
return false;
428419
}
429420

430-
const isPrevQuotedMessageTypeDeleted = prevMessage.quoted_message?.type === 'deleted';
431-
const isNextQuotedMessageTypeDeleted = nextMessage.quoted_message?.type === 'deleted';
421+
const quotedMessageEqual = checkQuotedMessageEquality(
422+
prevMessage.quoted_message,
423+
nextMessage.quoted_message,
424+
);
432425

433-
const quotedMessageEqual =
434-
prevMessage.quoted_message?.id === nextMessage.quoted_message?.id &&
435-
isPrevQuotedMessageTypeDeleted === isNextQuotedMessageTypeDeleted;
436426
if (!quotedMessageEqual) {
437427
return false;
438428
}

package/src/components/Message/MessageSimple/MessageSimple.tsx

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { useTheme } from '../../../contexts/themeContext/ThemeContext';
2626

2727
import { NativeHandlers } from '../../../native';
2828

29+
import { checkMessageEquality, checkQuotedMessageEquality } from '../../../utils/utils';
2930
import { useMessageData } from '../hooks/useMessageData';
3031

3132
const styles = StyleSheet.create({
@@ -476,11 +477,6 @@ const areEqual = (
476477
otherAttachments: nextOtherAttachments,
477478
} = nextProps;
478479

479-
const repliesEqual = prevMessage.reply_count === nextMessage.reply_count;
480-
if (!repliesEqual) {
481-
return false;
482-
}
483-
484480
const hasReactionsEqual = prevHasReactions === nextHasReactions;
485481
if (!hasReactionsEqual) {
486482
return false;
@@ -491,9 +487,6 @@ const areEqual = (
491487
return false;
492488
}
493489

494-
const isPrevMessageTypeDeleted = prevMessage.type === 'deleted';
495-
const isNextMessageTypeDeleted = nextMessage.type === 'deleted';
496-
497490
const lastGroupMessageEqual = prevLastGroupMessage === nextLastGroupMessage;
498491
if (!lastGroupMessageEqual) {
499492
return false;
@@ -504,24 +497,15 @@ const areEqual = (
504497
return false;
505498
}
506499

507-
const messageEqual =
508-
isPrevMessageTypeDeleted === isNextMessageTypeDeleted &&
509-
prevMessage.reply_count === nextMessage.reply_count &&
510-
prevMessage.status === nextMessage.status &&
511-
prevMessage.type === nextMessage.type &&
512-
prevMessage.text === nextMessage.text &&
513-
prevMessage.i18n === nextMessage.i18n &&
514-
prevMessage.pinned === nextMessage.pinned;
500+
const messageEqual = checkMessageEquality(prevMessage, nextMessage);
515501
if (!messageEqual) {
516502
return false;
517503
}
518504

519-
const isPrevQuotedMessageTypeDeleted = prevMessage.quoted_message?.type === 'deleted';
520-
const isNextQuotedMessageTypeDeleted = nextMessage.quoted_message?.type === 'deleted';
521-
522-
const quotedMessageEqual =
523-
prevMessage.quoted_message?.id === nextMessage.quoted_message?.id &&
524-
isPrevQuotedMessageTypeDeleted === isNextQuotedMessageTypeDeleted;
505+
const quotedMessageEqual = checkQuotedMessageEquality(
506+
prevMessage.quoted_message,
507+
nextMessage.quoted_message,
508+
);
525509

526510
if (!quotedMessageEqual) {
527511
return false;

package/src/components/Message/hooks/useCreateMessageContext.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ export const useCreateMessageContext = ({
4545
}: MessageContextValue) => {
4646
const groupStylesLength = groupStyles.length;
4747
const reactionsValue = reactions.map(({ count, own, type }) => `${own}${type}${count}`).join();
48-
const stringifiedMessage = stringifyMessage(message);
48+
const stringifiedMessage = stringifyMessage({ message });
4949

5050
const membersValue = JSON.stringify(members);
5151
const myMessageThemeString = useMemo(() => JSON.stringify(myMessageTheme), [myMessageTheme]);
5252

53-
const quotedMessageDeletedValue = message.quoted_message?.deleted_at;
53+
const stringifiedQuotedMessage = message.quoted_message
54+
? stringifyMessage({ includeReactions: false, message: message.quoted_message })
55+
: '';
5456

5557
const messageContext: MessageContextValue = useMemo(
5658
() => ({
@@ -95,7 +97,6 @@ export const useCreateMessageContext = ({
9597
// eslint-disable-next-line react-hooks/exhaustive-deps
9698
[
9799
actionsEnabled,
98-
quotedMessageDeletedValue,
99100
alignment,
100101
goToMessage,
101102
groupStylesLength,
@@ -104,9 +105,10 @@ export const useCreateMessageContext = ({
104105
lastGroupMessage,
105106
lastReceivedId,
106107
membersValue,
107-
stringifiedMessage,
108108
myMessageThemeString,
109109
reactionsValue,
110+
stringifiedMessage,
111+
stringifiedQuotedMessage,
110112
readBy,
111113
showAvatar,
112114
showMessageStatus,

package/src/components/Reply/Reply.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { useStateStore } from '../../hooks';
2424
import { FileTypes } from '../../types/types';
2525
import { getResizedImageUrl } from '../../utils/getResizedImageUrl';
2626
import { getTrimmedAttachmentTitle } from '../../utils/getTrimmedAttachmentTitle';
27-
import { hasOnlyEmojis } from '../../utils/utils';
27+
import { checkQuotedMessageEquality, hasOnlyEmojis } from '../../utils/utils';
2828

2929
import { FileIcon as FileIconDefault } from '../Attachment/FileIcon';
3030
import { VideoThumbnail } from '../Attachment/VideoThumbnail';
@@ -351,12 +351,14 @@ const areEqual = (prevProps: ReplyPropsWithContext, nextProps: ReplyPropsWithCon
351351
const quotedMessageEqual =
352352
!!prevQuotedMessage &&
353353
!!nextQuotedMessage &&
354-
typeof prevQuotedMessage !== 'boolean' &&
355-
typeof nextQuotedMessage !== 'boolean'
356-
? prevQuotedMessage.id === nextQuotedMessage.id &&
357-
prevQuotedMessage.deleted_at === nextQuotedMessage.deleted_at &&
358-
prevQuotedMessage.type === nextQuotedMessage.type
359-
: !!prevQuotedMessage === !!nextQuotedMessage;
354+
checkQuotedMessageEquality(prevQuotedMessage, nextQuotedMessage);
355+
356+
const quotedMessageAttachmentsEqual =
357+
prevQuotedMessage?.attachments?.length === nextQuotedMessage?.attachments?.length;
358+
359+
if (!quotedMessageAttachmentsEqual) {
360+
return false;
361+
}
360362

361363
if (!quotedMessageEqual) {
362364
return false;

package/src/utils/utils.ts

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,13 @@ export const hasOnlyEmojis = (text: string) => {
143143
* @param {LocalMessage} message - the message object to be stringified
144144
* @returns {string} The stringified message
145145
*/
146-
export const stringifyMessage = (message: MessageResponse | LocalMessage): string => {
146+
export const stringifyMessage = ({
147+
message,
148+
includeReactions = true,
149+
}: {
150+
message: MessageResponse | LocalMessage;
151+
includeReactions?: boolean;
152+
}): string => {
147153
const {
148154
deleted_at,
149155
i18n,
@@ -155,6 +161,10 @@ export const stringifyMessage = (message: MessageResponse | LocalMessage): strin
155161
type,
156162
updated_at,
157163
} = message;
164+
const baseFieldsString = `${type}${deleted_at}${text}${reply_count}${status}${updated_at}${JSON.stringify(i18n)}`;
165+
if (!includeReactions) {
166+
return baseFieldsString;
167+
}
158168
return `${
159169
latest_reactions ? latest_reactions.map(({ type, user }) => `${type}${user?.id}`).join() : ''
160170
}${
@@ -166,7 +176,7 @@ export const stringifyMessage = (message: MessageResponse | LocalMessage): strin
166176
)
167177
.join()
168178
: ''
169-
}${type}${deleted_at}${text}${reply_count}${status}${updated_at}${JSON.stringify(i18n)}`;
179+
}${baseFieldsString}`;
170180
};
171181

172182
/**
@@ -175,7 +185,13 @@ export const stringifyMessage = (message: MessageResponse | LocalMessage): strin
175185
* @returns {string} The mapped message string
176186
*/
177187
export const reduceMessagesToString = (messages: LocalMessage[]): string =>
178-
messages.map(stringifyMessage).join();
188+
messages
189+
.map((message) =>
190+
message?.quoted_message
191+
? `${stringifyMessage({ message })}_${message.quoted_message.type}_${message.quoted_message.deleted_at}_${message.quoted_message.text}_${message.quoted_message.updated_at}`
192+
: stringifyMessage({ message }),
193+
)
194+
.join();
179195

180196
/**
181197
* Utility to get the file name from the path using regex.
@@ -275,3 +291,59 @@ export const findInMessagesByDate = (
275291

276292
return { index: -1 };
277293
};
294+
295+
/**
296+
* The purpose of this function is to compare two messages and determine if they are equal.
297+
* It checks various properties of the messages, such as status, type, text, pinned state, updated_at timestamp, i18n data, and reply count.
298+
* If all these properties match, it returns true, indicating that the messages are considered equal.
299+
* If any of the properties differ, it returns false, indicating that the messages are not equal.
300+
* Useful for the `areEqual` logic in the React.memo of the Message component/sub-components.
301+
*/
302+
export const checkMessageEquality = (
303+
prevMessage?: LocalMessage,
304+
nextMessage?: LocalMessage,
305+
): boolean => {
306+
if (!prevMessage || !nextMessage) {
307+
return false;
308+
}
309+
const isPrevMessageTypeDeleted = prevMessage.type === 'deleted';
310+
const isNextMessageTypeDeleted = nextMessage.type === 'deleted';
311+
const messageEqual =
312+
isPrevMessageTypeDeleted === isNextMessageTypeDeleted &&
313+
prevMessage.status === nextMessage.status &&
314+
prevMessage.type === nextMessage.type &&
315+
prevMessage.text === nextMessage.text &&
316+
prevMessage.pinned === nextMessage.pinned &&
317+
prevMessage.i18n === nextMessage.i18n &&
318+
prevMessage.reply_count === nextMessage.reply_count &&
319+
`${prevMessage?.updated_at}` === `${nextMessage?.updated_at}` &&
320+
`${prevMessage?.deleted_at}` === `${nextMessage?.deleted_at}`;
321+
322+
return messageEqual;
323+
};
324+
325+
/**
326+
* The purpose of this function is to compare two quoted messages and determine if they are equal.
327+
* It checks various properties of the messages, such as status, type, text, updated_at timestamp, and deleted_at.
328+
* If all these properties match, it returns true, indicating that the messages are considered equal.
329+
* If any of the properties differ, it returns false, indicating that the messages are not equal.
330+
* Useful for the `areEqual` logic in the React.memo of the Message component/sub-components.
331+
*/
332+
export const checkQuotedMessageEquality = (
333+
prevQuotedMessage?: LocalMessage,
334+
nextQuotedMessage?: LocalMessage,
335+
): boolean => {
336+
if (!prevQuotedMessage || !nextQuotedMessage) {
337+
return false;
338+
}
339+
const isPrevQuotedMessageTypeDeleted = prevQuotedMessage.type === 'deleted';
340+
const isNextQuotedMessageTypeDeleted = nextQuotedMessage.type === 'deleted';
341+
const quotedMessageEqual =
342+
isPrevQuotedMessageTypeDeleted === isNextQuotedMessageTypeDeleted &&
343+
prevQuotedMessage.type === nextQuotedMessage.type &&
344+
prevQuotedMessage.text === nextQuotedMessage.text &&
345+
`${prevQuotedMessage?.updated_at}` === `${nextQuotedMessage?.updated_at}` &&
346+
`${prevQuotedMessage?.deleted_at}` === `${nextQuotedMessage?.deleted_at}`;
347+
348+
return quotedMessageEqual;
349+
};

0 commit comments

Comments
 (0)