diff --git a/app/soapbox/components/status.tsx b/app/soapbox/components/status.tsx index 2e2f68a1c..94e5033f9 100644 --- a/app/soapbox/components/status.tsx +++ b/app/soapbox/components/status.tsx @@ -1,13 +1,13 @@ import classNames from 'classnames'; import React, { useEffect, useRef, useState } from 'react'; import { HotKeys } from 'react-hotkeys'; -import { useIntl, FormattedMessage, IntlShape, defineMessages } from 'react-intl'; +import { useIntl, FormattedMessage, defineMessages } from 'react-intl'; import { NavLink, useHistory } from 'react-router-dom'; import Icon from 'soapbox/components/icon'; import AccountContainer from 'soapbox/containers/account_container'; import QuotedStatus from 'soapbox/features/status/containers/quoted_status_container'; -import { defaultMediaVisibility } from 'soapbox/utils/status'; +import { defaultMediaVisibility, textForScreenReader } from 'soapbox/utils/status'; import StatusMedia from './status-media'; import StatusReplyMentions from './status-reply-mentions'; @@ -29,26 +29,6 @@ const messages = defineMessages({ reblogged_by: { id: 'status.reblogged_by', defaultMessage: '{name} reposted' }, }); -export const textForScreenReader = (intl: IntlShape, status: StatusEntity, rebloggedByText?: string): string => { - const { account } = status; - if (!account || typeof account !== 'object') return ''; - - const displayName = account.display_name; - - const values = [ - displayName.length === 0 ? account.acct.split('@')[0] : displayName, - status.spoiler_text && status.hidden ? status.spoiler_text : status.search_index.slice(status.spoiler_text.length), - intl.formatDate(status.created_at, { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' }), - status.getIn(['account', 'acct']), - ]; - - if (rebloggedByText) { - values.push(rebloggedByText); - } - - return values.join(', '); -}; - interface IStatus { id?: string, contextType?: string, diff --git a/app/soapbox/features/status/index.tsx b/app/soapbox/features/status/index.tsx index 9ab57ec1f..5d00bce07 100644 --- a/app/soapbox/features/status/index.tsx +++ b/app/soapbox/features/status/index.tsx @@ -49,7 +49,6 @@ import { import MissingIndicator from 'soapbox/components/missing_indicator'; import PullToRefresh from 'soapbox/components/pull-to-refresh'; import ScrollableList from 'soapbox/components/scrollable_list'; -import { textForScreenReader } from 'soapbox/components/status'; import SubNavigation from 'soapbox/components/sub_navigation'; import Tombstone from 'soapbox/components/tombstone'; import { Column, Stack } from 'soapbox/components/ui'; @@ -57,7 +56,7 @@ import PlaceholderStatus from 'soapbox/features/placeholder/components/placehold import PendingStatus from 'soapbox/features/ui/components/pending_status'; import { useAppDispatch, useAppSelector, useSettings, useSoapboxConfig } from 'soapbox/hooks'; import { makeGetStatus } from 'soapbox/selectors'; -import { defaultMediaVisibility } from 'soapbox/utils/status'; +import { defaultMediaVisibility, textForScreenReader } from 'soapbox/utils/status'; import ActionBar from './components/action-bar'; import DetailedStatus from './components/detailed-status'; diff --git a/app/soapbox/utils/status.ts b/app/soapbox/utils/status.ts index 5c4590066..b0890fb20 100644 --- a/app/soapbox/utils/status.ts +++ b/app/soapbox/utils/status.ts @@ -1,5 +1,6 @@ import { isIntegerId } from 'soapbox/utils/numbers'; +import type { IntlShape } from 'react-intl'; import type { Status as StatusEntity } from 'soapbox/types/entities'; /** Get the initial visibility of media attachments from user settings. */ @@ -36,3 +37,24 @@ export const shouldHaveCard = (status: StatusEntity): boolean => { export const hasIntegerMediaIds = (status: StatusEntity): boolean => { return status.media_attachments.some(({ id }) => isIntegerId(id)); }; + +/** Sanitize status text for use with screen readers. */ +export const textForScreenReader = (intl: IntlShape, status: StatusEntity, rebloggedByText?: string): string => { + const { account } = status; + if (!account || typeof account !== 'object') return ''; + + const displayName = account.display_name; + + const values = [ + displayName.length === 0 ? account.acct.split('@')[0] : displayName, + status.spoiler_text && status.hidden ? status.spoiler_text : status.search_index.slice(status.spoiler_text.length), + intl.formatDate(status.created_at, { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' }), + status.getIn(['account', 'acct']), + ]; + + if (rebloggedByText) { + values.push(rebloggedByText); + } + + return values.join(', '); +};