import PropTypes from 'prop-types'; import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; import classNames from 'classnames'; import { Link, withRouter } from 'react-router-dom'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { HotKeys } from 'react-hotkeys'; import EditIcon from '@/material-icons/400-24px/edit.svg?react'; import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react'; import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react'; import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react'; import ReferenceIcon from '@/material-icons/400-24px/link.svg?react'; import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react'; import PersonIcon from '@/material-icons/400-24px/person-fill.svg?react'; import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; import StarIcon from '@/material-icons/400-24px/star-fill.svg?react'; import EmojiView from 'mastodon/components/emoji_view'; import { Icon } from 'mastodon/components/icon'; import AccountContainer from 'mastodon/containers/account_container'; import StatusContainer from 'mastodon/containers/status_container'; import { me } from 'mastodon/initial_state'; import { WithRouterPropTypes } from 'mastodon/utils/react_router'; import FollowRequestContainer from '../containers/follow_request_container'; import Report from './report'; const messages = defineMessages({ favourite: { id: 'notification.favourite', defaultMessage: '{name} favorited your status' }, emojiReaction: { id: 'notification.emoji_reaction', defaultMessage: '{name} reacted your status with emoji' }, follow: { id: 'notification.follow', defaultMessage: '{name} followed you' }, ownPoll: { id: 'notification.own_poll', defaultMessage: 'Your poll has ended' }, poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' }, reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your status' }, status: { id: 'notification.status', defaultMessage: '{name} just posted' }, listStatus: { id: 'notification.list_status', defaultMessage: '{name} post is added on {listName}' }, statusReference: { id: 'notification.status_reference', defaultMessage: '{name} refered' }, update: { id: 'notification.update', defaultMessage: '{name} edited a post' }, warning: { id: 'notification.warning', defaultMessage: 'You have been warned and "{action}" has been executed. Check your mailbox' }, adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' }, adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' }, }); const notificationForScreenReader = (intl, message, timestamp) => { const output = [message]; output.push(intl.formatDate(timestamp, { hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric' })); return output.join(', '); }; class Notification extends ImmutablePureComponent { static propTypes = { notification: ImmutablePropTypes.map.isRequired, hidden: PropTypes.bool, onMoveUp: PropTypes.func.isRequired, onMoveDown: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, onFavourite: PropTypes.func.isRequired, onReblog: PropTypes.func.isRequired, onToggleHidden: PropTypes.func.isRequired, status: ImmutablePropTypes.map, intl: PropTypes.object.isRequired, getScrollPosition: PropTypes.func, updateScrollBottom: PropTypes.func, cacheMediaWidth: PropTypes.func, cachedMediaWidth: PropTypes.number, unread: PropTypes.bool, ...WithRouterPropTypes, }; handleMoveUp = () => { const { notification, onMoveUp } = this.props; onMoveUp(notification.get('id')); }; handleMoveDown = () => { const { notification, onMoveDown } = this.props; onMoveDown(notification.get('id')); }; handleOpen = () => { const { notification } = this.props; if (notification.get('status')) { this.props.history.push(`/@${notification.getIn(['status', 'account', 'acct'])}/${notification.get('status')}`); } else { this.handleOpenProfile(); } }; handleOpenProfile = () => { const { notification } = this.props; this.props.history.push(`/@${notification.getIn(['account', 'acct'])}`); }; handleMention = e => { e.preventDefault(); const { notification, onMention } = this.props; onMention(notification.get('account'), this.props.history); }; handleHotkeyFavourite = () => { const { status } = this.props; if (status) this.props.onFavourite(status); }; handleHotkeyBoost = e => { const { status } = this.props; if (status) this.props.onReblog(status, e); }; handleHotkeyToggleHidden = () => { const { status } = this.props; if (status) this.props.onToggleHidden(status); }; getHandlers () { return { reply: this.handleMention, favourite: this.handleHotkeyFavourite, boost: this.handleHotkeyBoost, mention: this.handleMention, open: this.handleOpen, openProfile: this.handleOpenProfile, moveUp: this.handleMoveUp, moveDown: this.handleMoveDown, toggleHidden: this.handleHotkeyToggleHidden, }; } renderFollow (notification, account, link) { const { intl, unread } = this.props; return ( ); } renderFollowRequest (notification, account, link) { const { intl, unread } = this.props; return ( ); } renderMention (notification) { return ( ); } renderFavourite (notification, link) { const { intl, unread } = this.props; return ( ); } renderEmojiReaction (notification, link) { const { intl, unread } = this.props; const emoji_reaction = notification.get('emoji_reaction'); return ( ); } renderReblog (notification, link) { const { intl, unread } = this.props; return ( ); } renderStatusReference (notification, link) { const { intl, unread } = this.props; return ( ); } renderStatus (notification, link) { const { intl, unread, status } = this.props; if (!status) { return null; } return ( ); } renderListStatus (notification, listLink, link) { const { intl, unread, status } = this.props; if (!status) { return null; } return ( ); } renderUpdate (notification, link) { const { intl, unread, status } = this.props; if (!status) { return null; } return ( ); } renderPoll (notification, account) { const { intl, unread, status } = this.props; const ownPoll = me === account.get('id'); const message = ownPoll ? intl.formatMessage(messages.ownPoll) : intl.formatMessage(messages.poll); if (!status) { return null; } return ( {ownPoll ? ( ) : ( )} ); } renderWarning (notification) { const { intl, unread } = this.props; return ( {notification.getIn(['account_warning', 'text'])} ); } renderAdminSignUp (notification, account, link) { const { intl, unread } = this.props; return ( ); } renderAdminReport (notification, account, link) { const { intl, unread, report } = this.props; if (!report) { return null; } const targetAccount = report.get('target_account'); const targetDisplayNameHtml = { __html: targetAccount.get('display_name_html') }; const targetLink = ; return ( ); } render () { const { notification } = this.props; const account = notification.get('account'); const displayNameHtml = { __html: account.get('display_name_html') }; const link = ; switch(notification.get('type')) { case 'follow': return this.renderFollow(notification, account, link); case 'follow_request': return this.renderFollowRequest(notification, account, link); case 'mention': return this.renderMention(notification); case 'favourite': return this.renderFavourite(notification, link); case 'emoji_reaction': return this.renderEmojiReaction(notification, link); case 'reblog': return this.renderReblog(notification, link); case 'status_reference': return this.renderStatusReference(notification, link); case 'status': return this.renderStatus(notification, link); case 'list_status': const list = notification.get('list'); const listLink = {list.get('title')}; return this.renderListStatus(notification, listLink, link); case 'update': return this.renderUpdate(notification, link); case 'poll': return this.renderPoll(notification, account); case 'warning': return this.renderWarning(notification); case 'admin.sign_up': return this.renderAdminSignUp(notification, account, link); case 'admin.report': return this.renderAdminReport(notification, account, link); } return null; } } export default withRouter(injectIntl(Notification));