diff options
Diffstat (limited to 'app/javascript/flavours/glitch/components/status_icons.jsx')
-rw-r--r-- | app/javascript/flavours/glitch/components/status_icons.jsx | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/components/status_icons.jsx b/app/javascript/flavours/glitch/components/status_icons.jsx new file mode 100644 index 000000000..3baff2206 --- /dev/null +++ b/app/javascript/flavours/glitch/components/status_icons.jsx @@ -0,0 +1,146 @@ +// Package imports. +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { defineMessages, injectIntl } from 'react-intl'; + +// Mastodon imports. +import IconButton from './icon_button'; +import VisibilityIcon from './status_visibility_icon'; +import Icon from 'flavours/glitch/components/icon'; +import { languages } from 'flavours/glitch/initial_state'; + +// Messages for use with internationalization stuff. +const messages = defineMessages({ + collapse: { id: 'status.collapse', defaultMessage: 'Collapse' }, + uncollapse: { id: 'status.uncollapse', defaultMessage: 'Uncollapse' }, + inReplyTo: { id: 'status.in_reply_to', defaultMessage: 'This toot is a reply' }, + previewCard: { id: 'status.has_preview_card', defaultMessage: 'Features an attached preview card' }, + pictures: { id: 'status.has_pictures', defaultMessage: 'Features attached pictures' }, + poll: { id: 'status.is_poll', defaultMessage: 'This toot is a poll' }, + video: { id: 'status.has_video', defaultMessage: 'Features attached videos' }, + audio: { id: 'status.has_audio', defaultMessage: 'Features attached audio files' }, + localOnly: { id: 'status.local_only', defaultMessage: 'Only visible from your instance' }, +}); + +const LanguageIcon = ({ language }) => { + if (!languages) return null; + + const lang = languages.find((lang) => lang[0] === language); + if (!lang) return null; + + return ( + <span className='text-icon' title={`${lang[2]} (${lang[1]})`} aria-hidden='true'> + {lang[0].toUpperCase()} + </span> + ); +}; + +LanguageIcon.propTypes = { + language: PropTypes.string.isRequired, +}; + +class StatusIcons extends React.PureComponent { + + static propTypes = { + status: ImmutablePropTypes.map.isRequired, + mediaIcons: PropTypes.arrayOf(PropTypes.string), + collapsible: PropTypes.bool, + collapsed: PropTypes.bool, + setCollapsed: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + settings: ImmutablePropTypes.map.isRequired, + }; + + // Handles clicks on collapsed button + handleCollapsedClick = (e) => { + const { collapsed, setCollapsed } = this.props; + if (e.button === 0) { + setCollapsed(!collapsed); + e.preventDefault(); + } + }; + + mediaIconTitleText (mediaIcon) { + const { intl } = this.props; + + switch (mediaIcon) { + case 'link': + return intl.formatMessage(messages.previewCard); + case 'picture-o': + return intl.formatMessage(messages.pictures); + case 'tasks': + return intl.formatMessage(messages.poll); + case 'video-camera': + return intl.formatMessage(messages.video); + case 'music': + return intl.formatMessage(messages.audio); + } + } + + renderIcon (mediaIcon) { + return ( + <Icon + fixedWidth + className='status__media-icon' + key={`media-icon--${mediaIcon}`} + id={mediaIcon} + aria-hidden='true' + title={this.mediaIconTitleText(mediaIcon)} + /> + ); + } + + // Rendering. + render () { + const { + status, + mediaIcons, + collapsible, + collapsed, + settings, + intl, + } = this.props; + + return ( + <div className='status__info__icons'> + {settings.get('language') && status.get('language') && <LanguageIcon language={status.get('language')} />} + {settings.get('reply') && status.get('in_reply_to_id', null) !== null ? ( + <Icon + className='status__reply-icon' + fixedWidth + id='comment' + aria-hidden='true' + title={intl.formatMessage(messages.inReplyTo)} + /> + ) : null} + {settings.get('local_only') && status.get('local_only') && + <Icon + fixedWidth + id='home' + aria-hidden='true' + title={intl.formatMessage(messages.localOnly)} + />} + {settings.get('media') && !!mediaIcons && mediaIcons.map(icon => this.renderIcon(icon))} + {settings.get('visibility') && <VisibilityIcon visibility={status.get('visibility')} />} + {collapsible && ( + <IconButton + className='status__collapse-button' + animate + active={collapsed} + title={ + collapsed ? + intl.formatMessage(messages.uncollapse) : + intl.formatMessage(messages.collapse) + } + icon='angle-double-up' + onClick={this.handleCollapsedClick} + /> + )} + </div> + ); + } + +} + +export default injectIntl(StatusIcons); |