import React from 'react'; import { HotKeys } from 'react-hotkeys'; import { FormattedMessage, useIntl } from 'react-intl'; import { useHistory } from 'react-router-dom'; import Icon from '../../../components/icon'; import Permalink from '../../../components/permalink'; import { HStack, Text } from '../../../components/ui'; import AccountContainer from '../../../containers/account_container'; import StatusContainer from '../../../containers/status_container'; import type { History } from 'history'; import type { ScrollPosition } from 'soapbox/components/status'; import type { NotificationType } from 'soapbox/normalizers/notification'; import type { Account, Status, Notification as NotificationEntity } from 'soapbox/types/entities'; const notificationForScreenReader = (intl: ReturnType, message: string, timestamp: Date) => { const output = [message]; output.push(intl.formatDate(timestamp, { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' })); return output.join(', '); }; // Workaround for dynamic messages (https://github.com/formatjs/babel-plugin-react-intl/issues/119#issuecomment-326202499) function FormattedMessageFixed(props: any) { return ; } const buildLink = (account: Account): JSX.Element => ( ); export const NOTIFICATION_TYPES = ['follow', 'mention', 'favourite', 'reblog', 'status']; const icons = { follow: require('@tabler/icons/icons/user-plus.svg'), mention: require('@tabler/icons/icons/at.svg'), favourite: require('@tabler/icons/icons/heart.svg'), reblog: require('@tabler/icons/icons/repeat.svg'), status: require('@tabler/icons/icons/home.svg'), }; // @ts-ignore const messages: Record = { follow: { id: 'notification.follow', defaultMessage: '{name} followed you', }, mention: { id: 'notification.mentioned', defaultMessage: '{name} mentioned you', }, favourite: { id: 'notification.favourite', defaultMessage: '{name} liked your post', }, reblog: { id: 'notification.reblog', defaultMessage: '{name} reposted your post', }, status: { id: 'notification.status', defaultMessage: '{name} just posted', }, }; const buildMessage = (type: NotificationType, account: Account): JSX.Element => { const link = buildLink(account); return ( ); }; interface INotificaton { hidden?: boolean, notification: NotificationEntity, onMoveUp: (notificationId: string) => void, onMoveDown: (notificationId: string) => void, onMention: (account: Account, history: History) => void, onFavourite: (status: Status) => void, onReblog: (status: Status, e?: KeyboardEvent) => void, onToggleHidden: (status: Status) => void, getScrollPosition?: () => ScrollPosition | undefined, updateScrollBottom?: (bottom: number) => void, cacheMediaWidth: () => void, cachedMediaWidth: number, siteTitle?: string, } const Notification: React.FC = (props) => { const { hidden = false, notification, onMoveUp, onMoveDown } = props; const history = useHistory(); const intl = useIntl(); const type = notification.type; const { account, status } = notification; const getHandlers = () => ({ reply: handleMention, favourite: handleHotkeyFavourite, boost: handleHotkeyBoost, mention: handleMention, open: handleOpen, openProfile: handleOpenProfile, moveUp: handleMoveUp, moveDown: handleMoveDown, toggleHidden: handleHotkeyToggleHidden, }); const handleOpen = () => { if (status && typeof status === 'object' && account && typeof account === 'object') { history.push(`/@${account.acct}/posts/${status.id}`); } else { handleOpenProfile(); } }; const handleOpenProfile = () => { if (account && typeof account === 'object') { history.push(`/@${account.acct}`); } }; const handleMention = (e?: KeyboardEvent) => { e?.preventDefault(); if (account && typeof account === 'object') { props.onMention(account, history); } }; const handleHotkeyFavourite = (e?: KeyboardEvent) => { if (status && typeof status === 'object') { props.onFavourite(status); } }; const handleHotkeyBoost = (e?: KeyboardEvent) => { if (status && typeof status === 'object') { props.onReblog(status, e); } }; const handleHotkeyToggleHidden = (e?: KeyboardEvent) => { if (status && typeof status === 'object') { props.onToggleHidden(status); } }; const handleMoveUp = () => { onMoveUp(notification.id); }; const handleMoveDown = () => { onMoveDown(notification.id); }; const renderContent = () => { switch (type) { case 'follow': return account && typeof account === 'object' ? (