diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx index 7aa5f494fe..1a4d7ee1d7 100644 --- a/src/view/com/notifications/FeedItem.tsx +++ b/src/view/com/notifications/FeedItem.tsx @@ -1,4 +1,10 @@ -import React, {memo, useEffect, useMemo, useState} from 'react' +import React, { + memo, + type ReactElement, + useEffect, + useMemo, + useState, +} from 'react' import { Animated, Pressable, @@ -17,7 +23,7 @@ import { } from '@atproto/api' import {AtUri} from '@atproto/api' import {TID} from '@atproto/common-web' -import {msg, plural, Trans} from '@lingui/macro' +import {msg, Plural, plural, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' @@ -167,7 +173,32 @@ let FeedItem = ({ ) } - let action = '' + const niceTimestamp = niceDate(i18n, item.notification.indexedAt) + const firstAuthor = authors[0] + const firstAuthorName = sanitizeDisplayName( + firstAuthor.profile.displayName || firstAuthor.profile.handle, + ) + const firstAuthorLink = ( + + {forceLTR(firstAuthorName)} + + } + disableMismatchWarning + /> + ) + const additionalAuthorsCount = authors.length - 1 + const hasMultipleAuthors = additionalAuthorsCount > 0 + const formattedAuthorsCount = hasMultipleAuthors + ? formatCount(i18n, additionalAuthorsCount) + : '' + + let a11yLabel = '' + let notificationContent: ReactElement let icon = ( ) + if (item.type === 'post-like') { - action = _(msg`liked your post`) + a11yLabel = hasMultipleAuthors + ? _( + msg`${firstAuthorName} and ${plural(additionalAuthorsCount, { + one: `${formattedAuthorsCount} other`, + other: `${formattedAuthorsCount} others`, + })} liked your post`, + ) + : _(msg`${firstAuthorName} liked your post`) + notificationContent = hasMultipleAuthors ? ( + + {firstAuthorLink} and{' '} + + + {' '} + liked your post + + ) : ( + {firstAuthorLink} liked your post + ) } else if (item.type === 'repost') { - action = _(msg`reposted your post`) + a11yLabel = hasMultipleAuthors + ? _( + msg`${firstAuthorName} and ${plural(additionalAuthorsCount, { + one: `${formattedAuthorsCount} other`, + other: `${formattedAuthorsCount} others`, + })} reposted your post`, + ) + : _(msg`${firstAuthorName} reposted your post`) + notificationContent = hasMultipleAuthors ? ( + + {firstAuthorLink} and{' '} + + + {' '} + reposted your post + + ) : ( + {firstAuthorLink} reposted your post + ) icon = } else if (item.type === 'follow') { let isFollowBack = false @@ -204,40 +280,96 @@ let FeedItem = ({ } } - if (isFollowBack) { - action = _(msg`followed you back`) + if (isFollowBack && !hasMultipleAuthors) { + /* + * Follow-backs are ungrouped, grouped follow-backs not supported atm, + * see `src/state/queries/notifications/util.ts` + */ + a11yLabel = _(msg`${firstAuthorName} followed you back`) + notificationContent = {firstAuthorLink} followed you back } else { - action = _(msg`followed you`) + a11yLabel = hasMultipleAuthors + ? _( + msg`${firstAuthorName} and ${plural(additionalAuthorsCount, { + one: `${formattedAuthorsCount} other`, + other: `${formattedAuthorsCount} others`, + })} followed you`, + ) + : _(msg`${firstAuthorName} followed you`) + notificationContent = hasMultipleAuthors ? ( + + {firstAuthorLink} and{' '} + + + {' '} + followed you + + ) : ( + {firstAuthorLink} followed you + ) } icon = } else if (item.type === 'feedgen-like') { - action = _(msg`liked your custom feed`) + a11yLabel = hasMultipleAuthors + ? _( + msg`${firstAuthorName} and ${plural(additionalAuthorsCount, { + one: `${formattedAuthorsCount} other`, + other: `${formattedAuthorsCount} others`, + })} liked your custom feed`, + ) + : _(msg`${firstAuthorName} liked your custom feed`) + notificationContent = hasMultipleAuthors ? ( + + {firstAuthorLink} and{' '} + + + {' '} + liked your custom feed + + ) : ( + {firstAuthorLink} liked your custom feed + ) } else if (item.type === 'starterpack-joined') { + a11yLabel = hasMultipleAuthors + ? _( + msg`${firstAuthorName} and ${plural(additionalAuthorsCount, { + one: `${formattedAuthorsCount} other`, + other: `${formattedAuthorsCount} others`, + })} signed up with your starter pack`, + ) + : _(msg`${firstAuthorName} signed up with your starter pack`) + notificationContent = hasMultipleAuthors ? ( + + {firstAuthorLink} and{' '} + + + {' '} + signed up with your starter pack + + ) : ( + {firstAuthorLink} signed up with your starter pack + ) icon = ( ) - action = _(msg`signed up with your starter pack`) } else { return null } - - const formattedCount = - authors.length > 1 ? formatCount(i18n, authors.length - 1) : '' - const firstAuthorName = sanitizeDisplayName( - authors[0].profile.displayName || authors[0].profile.handle, - ) - const niceTimestamp = niceDate(i18n, item.notification.indexedAt) - const a11yLabelUsers = - authors.length > 1 - ? _(msg` and `) + - plural(authors.length - 1, { - one: `${formattedCount} other`, - other: `${formattedCount} others`, - }) - : '' - const a11yLabel = `${firstAuthorName}${a11yLabelUsers} ${action} ${niceTimestamp}` + a11yLabel += ` ยท ${niceTimestamp}` return ( 1 + hasMultipleAuthors ? [ { name: 'toggleAuthorsExpanded', @@ -288,7 +420,6 @@ let FeedItem = ({ onToggleAuthorsExpanded() } }} - onBeforePress={onBeforePress} onPointerEnter={() => { setHover(true) }} @@ -303,7 +434,7 @@ let FeedItem = ({ 1} + hasMultipleAuthors={hasMultipleAuthors} onToggleAuthorsExpanded={onToggleAuthorsExpanded}> - - {forceLTR(firstAuthorName)} - - } - disableMismatchWarning - /> - {authors.length > 1 ? ( - <> - - {' '} - and{' '} - - - {plural(authors.length - 1, { - one: `${formattedCount} other`, - other: `${formattedCount} others`, - })} - - - ) : undefined} - {action} + {notificationContent} {({timeElapsed}) => ( - - {' ' + timeElapsed} - + <> + · + + {timeElapsed} + + )}