mirror of
https://github.com/mastodon/mastodon.git
synced 2024-12-13 22:55:07 +01:00
acb434b0c9
Unlike boosts and like, there is no confirmation dialog as misclicking can be recovered without another user seeing it.
193 lines
7.7 KiB
JavaScript
193 lines
7.7 KiB
JavaScript
import React from 'react';
|
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
import PropTypes from 'prop-types';
|
|
import IconButton from './icon_button';
|
|
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
import { me } from 'flavours/glitch/util/initial_state';
|
|
import RelativeTimestamp from './relative_timestamp';
|
|
|
|
const messages = defineMessages({
|
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
|
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
|
|
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
|
|
block: { id: 'account.block', defaultMessage: 'Block @{name}' },
|
|
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
|
share: { id: 'status.share', defaultMessage: 'Share' },
|
|
more: { id: 'status.more', defaultMessage: 'More' },
|
|
replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
|
|
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
|
|
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
|
|
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
|
|
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
|
|
open: { id: 'status.open', defaultMessage: 'Expand this status' },
|
|
report: { id: 'status.report', defaultMessage: 'Report @{name}' },
|
|
muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' },
|
|
unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' },
|
|
pin: { id: 'status.pin', defaultMessage: 'Pin on profile' },
|
|
unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' },
|
|
embed: { id: 'status.embed', defaultMessage: 'Embed' },
|
|
});
|
|
|
|
@injectIntl
|
|
export default class StatusActionBar extends ImmutablePureComponent {
|
|
|
|
static contextTypes = {
|
|
router: PropTypes.object,
|
|
};
|
|
|
|
static propTypes = {
|
|
status: ImmutablePropTypes.map.isRequired,
|
|
onReply: PropTypes.func,
|
|
onFavourite: PropTypes.func,
|
|
onReblog: PropTypes.func,
|
|
onDelete: PropTypes.func,
|
|
onMention: PropTypes.func,
|
|
onMute: PropTypes.func,
|
|
onBlock: PropTypes.func,
|
|
onReport: PropTypes.func,
|
|
onEmbed: PropTypes.func,
|
|
onMuteConversation: PropTypes.func,
|
|
onPin: PropTypes.func,
|
|
onBookmark: PropTypes.func,
|
|
withDismiss: PropTypes.bool,
|
|
intl: PropTypes.object.isRequired,
|
|
};
|
|
|
|
// Avoid checking props that are functions (and whose equality will always
|
|
// evaluate to false. See react-immutable-pure-component for usage.
|
|
updateOnProps = [
|
|
'status',
|
|
'withDismiss',
|
|
]
|
|
|
|
handleReplyClick = () => {
|
|
this.props.onReply(this.props.status, this.context.router.history);
|
|
}
|
|
|
|
handleShareClick = () => {
|
|
navigator.share({
|
|
text: this.props.status.get('search_index'),
|
|
url: this.props.status.get('url'),
|
|
});
|
|
}
|
|
|
|
handleFavouriteClick = (e) => {
|
|
this.props.onFavourite(this.props.status, e);
|
|
}
|
|
|
|
handleBookmarkClick = (e) => {
|
|
this.props.onBookmark(this.props.status, e);
|
|
}
|
|
|
|
handleReblogClick = (e) => {
|
|
this.props.onReblog(this.props.status, e);
|
|
}
|
|
|
|
handleDeleteClick = () => {
|
|
this.props.onDelete(this.props.status);
|
|
}
|
|
|
|
handlePinClick = () => {
|
|
this.props.onPin(this.props.status);
|
|
}
|
|
|
|
handleMentionClick = () => {
|
|
this.props.onMention(this.props.status.get('account'), this.context.router.history);
|
|
}
|
|
|
|
handleMuteClick = () => {
|
|
this.props.onMute(this.props.status.get('account'));
|
|
}
|
|
|
|
handleBlockClick = () => {
|
|
this.props.onBlock(this.props.status.get('account'));
|
|
}
|
|
|
|
handleOpen = () => {
|
|
this.context.router.history.push(`/statuses/${this.props.status.get('id')}`);
|
|
}
|
|
|
|
handleEmbed = () => {
|
|
this.props.onEmbed(this.props.status);
|
|
}
|
|
|
|
handleReport = () => {
|
|
this.props.onReport(this.props.status);
|
|
}
|
|
|
|
handleConversationMuteClick = () => {
|
|
this.props.onMuteConversation(this.props.status);
|
|
}
|
|
|
|
render () {
|
|
const { status, intl, withDismiss } = this.props;
|
|
|
|
const mutingConversation = status.get('muted');
|
|
const anonymousAccess = !me;
|
|
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
|
|
|
|
let menu = [];
|
|
let reblogIcon = 'retweet';
|
|
let replyIcon;
|
|
let replyTitle;
|
|
|
|
menu.push({ text: intl.formatMessage(messages.open), action: this.handleOpen });
|
|
|
|
if (publicStatus) {
|
|
menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed });
|
|
}
|
|
|
|
menu.push(null);
|
|
|
|
if (status.getIn(['account', 'id']) === me || withDismiss) {
|
|
menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
|
menu.push(null);
|
|
}
|
|
|
|
if (status.getIn(['account', 'id']) === me) {
|
|
if (publicStatus) {
|
|
menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
|
|
}
|
|
|
|
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
|
} else {
|
|
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
|
|
menu.push(null);
|
|
menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
|
|
menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
|
|
menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
|
|
}
|
|
|
|
if (status.get('in_reply_to_id', null) === null) {
|
|
replyIcon = 'reply';
|
|
replyTitle = intl.formatMessage(messages.reply);
|
|
} else {
|
|
replyIcon = 'reply-all';
|
|
replyTitle = intl.formatMessage(messages.replyAll);
|
|
}
|
|
|
|
const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && (
|
|
<IconButton className='status__action-bar-button' title={intl.formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
|
);
|
|
|
|
return (
|
|
<div className='status__action-bar'>
|
|
<IconButton className='status__action-bar-button' disabled={anonymousAccess} title={replyTitle} icon={replyIcon} onClick={this.handleReplyClick} />
|
|
<IconButton className='status__action-bar-button' disabled={anonymousAccess || !publicStatus} active={status.get('reblogged')} pressed={status.get('reblogged')} title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)} icon={reblogIcon} onClick={this.handleReblogClick} />
|
|
<IconButton className='status__action-bar-button star-icon' disabled={anonymousAccess} animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} />
|
|
{shareButton}
|
|
<IconButton className='status__action-bar-button' disabled={anonymousAccess} active={status.get('bookmarked')} pressed={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} />
|
|
|
|
<div className='status__action-bar-dropdown'>
|
|
<DropdownMenuContainer disabled={anonymousAccess} status={status} items={menu} icon='ellipsis-h' size={18} direction='right' ariaLabel={intl.formatMessage(messages.more)} />
|
|
</div>
|
|
|
|
<a href={status.get('url')} className='status__relative-time' target='_blank' rel='noopener'><RelativeTimestamp timestamp={status.get('created_at')} /></a>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
}
|