2024-08-28 04:41:08 -07:00
|
|
|
import { isIntegerId } from 'pl-fe/utils/numbers';
|
2022-03-16 18:54:41 -07:00
|
|
|
|
2024-08-28 04:41:08 -07:00
|
|
|
import type { Status } from 'pl-fe/normalizers';
|
2024-08-28 05:48:35 -07:00
|
|
|
import type { IntlShape } from 'react-intl';
|
2022-04-11 12:58:48 -07:00
|
|
|
|
2022-06-07 12:26:12 -07:00
|
|
|
/** Get the initial visibility of media attachments from user settings. */
|
2024-08-18 08:50:56 -07:00
|
|
|
const defaultMediaVisibility = (
|
|
|
|
status: Pick<Status, 'sensitive'>,
|
2023-06-19 14:49:42 -07:00
|
|
|
displayMedia: string,
|
2024-08-18 08:50:56 -07:00
|
|
|
): boolean => (displayMedia !== 'hide_all' && !status.sensitive || displayMedia === 'show_all');
|
2022-06-07 12:26:12 -07:00
|
|
|
|
2022-04-24 12:28:07 -07:00
|
|
|
/** Grab the first external link from a status. */
|
2024-05-12 16:18:04 -07:00
|
|
|
const getFirstExternalLink = (status: Pick<Status, 'content'>): HTMLAnchorElement | null => {
|
2021-11-15 17:08:27 -08:00
|
|
|
try {
|
|
|
|
// Pulled from Pleroma's media parser
|
|
|
|
const selector = 'a:not(.mention,.hashtag,.attachment,[rel~="tag"])';
|
|
|
|
const element = document.createElement('div');
|
|
|
|
element.innerHTML = status.content;
|
|
|
|
return element.querySelector(selector);
|
|
|
|
} catch {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-04-24 12:28:07 -07:00
|
|
|
/** Whether the status is expected to have a Card after it loads. */
|
2024-05-12 16:18:04 -07:00
|
|
|
const shouldHaveCard = (status: Pick<Status, 'content'>): boolean =>
|
|
|
|
Boolean(getFirstExternalLink(status));
|
2022-03-16 18:54:41 -07:00
|
|
|
|
2022-04-24 12:28:07 -07:00
|
|
|
/** Whether the media IDs on this status have integer IDs (opposed to FlakeIds). */
|
2022-09-04 13:15:54 -07:00
|
|
|
// https://gitlab.com/soapbox-pub/soapbox/-/merge_requests/1087
|
2024-05-12 16:18:04 -07:00
|
|
|
const hasIntegerMediaIds = (status: Pick<Status, 'media_attachments'>): boolean =>
|
|
|
|
status.media_attachments.some(({ id }) => isIntegerId(id));
|
2022-08-08 19:42:07 -07:00
|
|
|
|
|
|
|
/** Sanitize status text for use with screen readers. */
|
2024-05-12 16:18:04 -07:00
|
|
|
const textForScreenReader = (
|
2023-06-19 14:49:42 -07:00
|
|
|
intl: IntlShape,
|
|
|
|
status: Pick<Status, 'account' | 'spoiler_text' | 'hidden' | 'search_index' | 'created_at'>,
|
|
|
|
rebloggedByText?: string,
|
|
|
|
): string => {
|
2022-08-08 19:42:07 -07:00
|
|
|
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' }),
|
2023-06-19 14:49:42 -07:00
|
|
|
account.acct,
|
2022-08-08 19:42:07 -07:00
|
|
|
];
|
|
|
|
|
|
|
|
if (rebloggedByText) {
|
|
|
|
values.push(rebloggedByText);
|
|
|
|
}
|
|
|
|
|
|
|
|
return values.join(', ');
|
|
|
|
};
|
2022-08-08 20:26:30 -07:00
|
|
|
|
2024-05-12 16:18:04 -07:00
|
|
|
const getStatusIdsFromLinksInContent = (content: string): string[] => {
|
2024-04-29 14:53:10 -07:00
|
|
|
const urls = content.match(RegExp(`${window.location.origin}/@([a-z\\d_-]+(?:@[^@\\s]+)?)/posts/[a-z0-9]+(?!\\S)`, 'gi'));
|
|
|
|
|
|
|
|
if (!urls) return [];
|
|
|
|
|
|
|
|
return Array.from(new Set(urls
|
|
|
|
.map(url => url.split('/').at(-1) as string)
|
|
|
|
.filter(url => url)));
|
|
|
|
};
|
2024-05-12 16:18:04 -07:00
|
|
|
|
|
|
|
export {
|
|
|
|
defaultMediaVisibility,
|
|
|
|
getFirstExternalLink,
|
|
|
|
shouldHaveCard,
|
|
|
|
hasIntegerMediaIds,
|
|
|
|
textForScreenReader,
|
|
|
|
getStatusIdsFromLinksInContent,
|
|
|
|
};
|