diff --git a/ts/components/conversation/AtMentionify.tsx b/ts/components/conversation/AtMentionify.tsx index b6af418671..3c3726bbb4 100644 --- a/ts/components/conversation/AtMentionify.tsx +++ b/ts/components/conversation/AtMentionify.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import React from 'react'; +import { sortBy } from 'lodash'; import { Emojify } from './Emojify'; import { BodyRangesType } from '../../types/Util'; @@ -102,7 +103,8 @@ AtMentionify.preprocessMentions = ( return text; } - return bodyRanges.reduce((str, range) => { + // Sorting by the start index to ensure that we always replace last -> first. + return sortBy(bodyRanges, 'start').reduceRight((str, range) => { const textBegin = str.substr(0, range.start); const encodedMention = `\uFFFC@${range.start}`; const textEnd = str.substr(range.start + range.length, str.length); diff --git a/ts/components/conversation/MessageBody.stories.tsx b/ts/components/conversation/MessageBody.stories.tsx index 3fc7dee9e9..43473c1113 100644 --- a/ts/components/conversation/MessageBody.stories.tsx +++ b/ts/components/conversation/MessageBody.stories.tsx @@ -115,19 +115,20 @@ story.add('@Mention', () => { story.add('Multiple @Mentions', () => { const props = createProps({ + // These are intentionally in a mixed order to test how we deal with that bodyRanges: [ - { - start: 4, - length: 1, - mentionUuid: 'abc', - replacementText: 'Professor Farnsworth', - }, { start: 2, length: 1, mentionUuid: 'def', replacementText: 'Philip J Fry', }, + { + start: 4, + length: 1, + mentionUuid: 'abc', + replacementText: 'Professor Farnsworth', + }, { start: 0, length: 1, @@ -144,18 +145,19 @@ story.add('Multiple @Mentions', () => { story.add('Complex MessageBody', () => { const props = createProps({ bodyRanges: [ - { - start: 80, - length: 1, - mentionUuid: 'xox', - replacementText: 'Cereal Killer', - }, + // These are intentionally in a mixed order to test how we deal with that { start: 78, length: 1, mentionUuid: 'wer', replacementText: 'Acid Burn', }, + { + start: 80, + length: 1, + mentionUuid: 'xox', + replacementText: 'Cereal Killer', + }, { start: 4, length: 1, diff --git a/ts/components/conversationList/MessageBodyHighlight.stories.tsx b/ts/components/conversationList/MessageBodyHighlight.stories.tsx index 73ec3fc7b5..96a74014b6 100644 --- a/ts/components/conversationList/MessageBodyHighlight.stories.tsx +++ b/ts/components/conversationList/MessageBodyHighlight.stories.tsx @@ -55,11 +55,11 @@ story.add('Two Replacements with an @mention', () => { length: 1, mentionUuid: '0ca40892-7b1a-11eb-9439-0242ac130002', replacementText: 'Jin Sakai', - start: 52, + start: 33, }, ], text: - 'Begin <>Inside #1<> \uFFFC@52 This is between the two <>Inside #2<> End.', + 'Begin <>Inside #1<> \uFFFC This is between the two <>Inside #2<> End.', }); return ; diff --git a/ts/components/conversationList/MessageSearchResult.stories.tsx b/ts/components/conversationList/MessageSearchResult.stories.tsx index 5144a5cf11..5fbde151af 100644 --- a/ts/components/conversationList/MessageSearchResult.stories.tsx +++ b/ts/components/conversationList/MessageSearchResult.stories.tsx @@ -237,3 +237,28 @@ story.add('@mention no-matches', () => { return ; }); + +story.add('Double @mention', () => { + const props = createProps({ + body: 'Hey \uFFFC \uFFFC test', + bodyRanges: [ + { + length: 1, + mentionUuid: '9eb2eb65-992a-4909-a2a5-18c56bd7648f', + replacementText: 'Alice', + start: 4, + }, + { + length: 1, + mentionUuid: '755ec61b-1590-48da-b003-3e57b2b54448', + replacementText: 'Bob', + start: 6, + }, + ], + from: someone, + to: me, + snippet: '<>Hey<> \uFFFC \uFFFC <>test<>', + }); + + return ; +});