diff --git a/src/components/views/rooms/ReadReceiptGroup.tsx b/src/components/views/rooms/ReadReceiptGroup.tsx index 31a2a59dd306..098c60af48bf 100644 --- a/src/components/views/rooms/ReadReceiptGroup.tsx +++ b/src/components/views/rooms/ReadReceiptGroup.tsx @@ -53,12 +53,10 @@ interface IAvatarPosition { } function determineAvatarPosition(index: number, count: number, max: number): IAvatarPosition { - const firstVisible = Math.max(0, count - max); - - if (index >= firstVisible) { + if (index < max) { return { hidden: false, - position: index - firstVisible, + position: Math.min(count, max) - index, }; } else { return { @@ -72,8 +70,42 @@ export function ReadReceiptGroup( { readReceipts, readReceiptMap, checkUnmounting, suppressAnimation, isTwelveHour }: Props, ) { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); + + // If we are above MAX_READ_AVATARS, we’ll have to remove a few to have space for the +n count. + const maxAvatars = readReceipts.length > MAX_READ_AVATARS + ? MAX_READ_AVATARS_PLUS_N + : MAX_READ_AVATARS; + + const tooltipMembers: string[] = readReceipts.slice(0, maxAvatars) + .map(it => it.roomMember?.name ?? it.userId); + let tooltipText: string | null; + if (readReceipts.length > MAX_READ_AVATARS) { + tooltipText = _t("%(members)s and more", { + members: tooltipMembers.join(", "), + }); + } else if (readReceipts.length) { + const last = tooltipMembers.pop(); + if (last) { + tooltipText = _t("%(members)s and %(last)s", { + members: tooltipMembers.join(", "), + last: last, + }); + } else { + tooltipText = tooltipMembers.join(", "); + } + } + const [{ showTooltip, hideTooltip }, tooltip] = useTooltip({ - label: _t("Seen by %(count)s people", { count: readReceipts.length }), + label: ( + <> +
+ { _t("Seen by %(count)s people", { count: readReceipts.length }) } +
+
+ { tooltipText } +
+ + ), alignment: Alignment.TopRight, }); @@ -97,11 +129,6 @@ export function ReadReceiptGroup( ); } - // If we are above MAX_READ_AVATARS, we’ll have to remove a few to have space for the +n count. - const maxAvatars = readReceipts.length > MAX_READ_AVATARS - ? MAX_READ_AVATARS_PLUS_N - : MAX_READ_AVATARS; - const avatars = readReceipts.map((receipt, index) => { const { hidden, position } = determineAvatarPosition(index, readReceipts.length, maxAvatars); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 17d730b4212c..31c6f3383fd2 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1766,6 +1766,8 @@ "Preview": "Preview", "View": "View", "Join": "Join", + "%(members)s and more": "%(members)s and more", + "%(members)s and %(last)s": "%(members)s and %(last)s", "Seen by %(count)s people|other": "Seen by %(count)s people", "Seen by %(count)s people|one": "Seen by %(count)s person", "Recently viewed": "Recently viewed",