254 lines
8.7 KiB
JavaScript
Raw Normal View History

2020-02-28 10:20:47 -05:00
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { defineMessages, injectIntl } from 'react-intl'
2020-02-08 01:12:01 -05:00
import classNames from 'classnames/bind'
2020-03-06 10:38:22 -05:00
import { openModal } from '../actions/modal'
2020-03-24 23:08:43 -04:00
import { openPopover } from '../actions/popover'
import { me } from '../initial_state'
2020-03-06 23:53:28 -05:00
import Text from './text'
2020-03-27 20:17:32 -04:00
import Button from './button'
2020-03-06 10:38:22 -05:00
import StatusActionBarItem from './status_action_bar_item'
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
2019-08-17 14:09:15 +03:00
edit: { id: 'status.edit', defaultMessage: 'Edit' },
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' },
2020-02-08 17:57:09 -05:00
comment: { id: 'status.comment', defaultMessage: 'Comment' },
more: { id: 'status.more', defaultMessage: 'More' },
2020-02-08 17:57:09 -05:00
share: { id: 'status.share', defaultMessage: 'Share' },
replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
2020-03-04 17:50:15 -05:00
repost: { id: 'repost', defaultMessage: 'Repost' },
2019-07-30 21:27:49 +03:00
quote: { id: 'status.quote', defaultMessage: 'Quote' },
2020-03-04 17:50:15 -05:00
repost_private: { id: 'status.repost_private', defaultMessage: 'Repost to original audience' },
cancel_repost_private: { id: 'status.cancel_repost_private', defaultMessage: 'Un-repost' },
cannot_repost: { id: 'status.cannot_repost', defaultMessage: 'This post cannot be reposted' },
2019-07-30 21:27:49 +03:00
cannot_quote: { id: 'status.cannot_quote', defaultMessage: 'This post cannot be quoted' },
2020-02-08 17:57:09 -05:00
like: { id: 'status.like', defaultMessage: 'Like' },
2020-04-02 12:57:04 -04:00
likesLabel: { id: 'likes.label', defaultMessage: '{number, plural, one {# like} other {# likes}}' },
repostsLabel: { id: 'reposts.label', defaultMessage: '{number, plural, one {# repost} other {# reposts}}' },
commentsLabel: { id: 'comments.label', defaultMessage: '{number, plural, one {# comment} other {# comments}}' },
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' },
admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' },
copy: { id: 'status.copy', defaultMessage: 'Copy link to status' },
group_remove_account: { id: 'status.remove_account_from_group', defaultMessage: 'Remove account from group' },
group_remove_post: { id: 'status.remove_post_from_group', defaultMessage: 'Remove status from group' },
2020-02-28 10:20:47 -05:00
})
const mapDispatchToProps = (dispatch) => ({
onOpenUnauthorizedModal() {
2020-02-28 10:20:47 -05:00
dispatch(openModal('UNAUTHORIZED'))
},
2020-03-24 23:08:43 -04:00
onOpenStatusSharePopover(targetRef, status) {
console.log("targetRef, status:", targetRef, status)
dispatch(openPopover('STATUS_SHARE', {
status,
targetRef,
position: 'top',
}))
},
2020-02-28 10:20:47 -05:00
})
2020-02-19 18:57:07 -05:00
const cx = classNames.bind(_s)
2020-02-25 11:04:44 -05:00
export default
@connect(null, mapDispatchToProps)
@injectIntl
class StatusActionBar extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
2020-02-28 10:20:47 -05:00
}
static propTypes = {
status: ImmutablePropTypes.map.isRequired,
onOpenUnauthorizedModal: PropTypes.func.isRequired,
2020-03-24 23:08:43 -04:00
onOpenStatusSharePopover: PropTypes.func.isRequired,
onReply: PropTypes.func,
2019-07-30 21:27:49 +03:00
onQuote: PropTypes.func,
2020-03-04 17:26:01 -05:00
onFavorite: PropTypes.func,
onRepost: 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,
withDismiss: PropTypes.bool,
withGroupAdmin: PropTypes.bool,
intl: PropTypes.object.isRequired,
2020-02-28 10:20:47 -05:00
}
// 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 = () => {
if (me) {
2020-02-28 10:20:47 -05:00
this.props.onReply(this.props.status, this.context.router.history)
} else {
2020-02-28 10:20:47 -05:00
this.props.onOpenUnauthorizedModal()
}
}
2019-07-30 21:27:49 +03:00
handleQuoteClick = () => {
if (me) {
2020-02-28 10:20:47 -05:00
this.props.onQuote(this.props.status, this.context.router.history)
2019-07-30 21:27:49 +03:00
} else {
2020-02-28 10:20:47 -05:00
this.props.onOpenUnauthorizedModal()
2019-07-30 21:27:49 +03:00
}
}
2020-03-04 17:26:01 -05:00
handleFavoriteClick = () => {
if (me) {
2020-03-04 17:26:01 -05:00
this.props.onFavorite(this.props.status)
} else {
2020-02-28 10:20:47 -05:00
this.props.onOpenUnauthorizedModal()
}
}
2020-03-04 17:26:01 -05:00
handleRepostClick = e => {
if (me) {
2020-03-04 17:26:01 -05:00
this.props.onRepost(this.props.status, e)
} else {
2020-02-28 10:20:47 -05:00
this.props.onOpenUnauthorizedModal()
}
}
2020-03-06 23:53:28 -05:00
handleShareClick = () => {
2020-03-24 23:08:43 -04:00
console.log("handleShareClick:", this.shareButton, this.props.status)
this.props.onOpenStatusSharePopover(this.shareButton, this.props.status)
}
setShareButton = (n) => {
this.shareButton = n
2020-03-06 23:53:28 -05:00
}
2020-02-28 10:20:47 -05:00
render() {
const { status, intl: { formatMessage } } = this.props
2020-02-28 10:20:47 -05:00
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'))
2020-02-28 10:20:47 -05:00
const replyCount = status.get('replies_count')
2020-03-04 17:50:15 -05:00
const repostCount = status.get('reblogs_count')
2020-04-06 21:53:23 -04:00
const favoriteCount = status.get('favourites_count')
2020-03-04 17:50:15 -05:00
const hasInteractions = favoriteCount > 0 || replyCount > 0 || repostCount > 0
2020-04-01 23:17:21 -04:00
const shouldCondense = (
!!status.get('card') ||
status.get('media_attachments').size > 0 ||
!!status.get('quote')
) && !hasInteractions
2020-02-13 19:40:04 -05:00
const containerClasses = cx({
default: 1,
2020-03-11 19:56:18 -04:00
px10: 1,
mt10: !shouldCondense,
mt5: shouldCondense,
2020-02-13 19:40:04 -05:00
})
const innerContainerClasses = cx({
default: 1,
2020-03-11 19:56:18 -04:00
py2: 1,
2020-02-13 19:40:04 -05:00
flexRow: 1,
width100PC: 1,
borderTop1PX: !shouldCondense,
2020-02-20 19:57:29 -05:00
borderColorSecondary: !shouldCondense,
2020-03-11 19:56:18 -04:00
mt5: hasInteractions,
2020-02-13 19:40:04 -05:00
})
const interactionBtnClasses = cx({
default: 1,
text: 1,
cursorPointer: 1,
fontWeightNormal: 1,
2020-03-11 19:56:18 -04:00
mr10: 1,
py5: 1,
2020-02-13 19:40:04 -05:00
})
2020-02-08 01:12:01 -05:00
return (
2020-02-13 19:40:04 -05:00
<div className={containerClasses}>
{
hasInteractions &&
2020-03-11 19:56:18 -04:00
<div className={[_s.default, _s.flexRow, _s.px5].join(' ')}>
2020-03-06 23:53:28 -05:00
{
favoriteCount > 0 &&
2020-02-13 19:40:04 -05:00
<button className={interactionBtnClasses}>
2020-03-25 23:11:32 -04:00
<Text color='secondary' size='small'>
2020-04-02 12:57:04 -04:00
{formatMessage(messages.likesLabel, {
number: favoriteCount,
})}
2020-03-06 23:53:28 -05:00
</Text>
2020-02-13 19:40:04 -05:00
</button>
}
2020-03-06 23:53:28 -05:00
{
replyCount > 0 &&
2020-02-13 19:40:04 -05:00
<button className={interactionBtnClasses}>
2020-03-25 23:11:32 -04:00
<Text color='secondary' size='small'>
2020-04-02 12:57:04 -04:00
{formatMessage(messages.commentsLabel, {
number: replyCount,
})}
2020-03-06 23:53:28 -05:00
</Text>
2020-02-13 19:40:04 -05:00
</button>
}
2020-03-06 23:53:28 -05:00
{
repostCount > 0 &&
2020-02-13 19:40:04 -05:00
<button className={interactionBtnClasses}>
2020-03-25 23:11:32 -04:00
<Text color='secondary' size='small'>
2020-04-02 12:57:04 -04:00
{formatMessage(messages.repostsLabel, {
number: repostCount,
})}
2020-03-06 23:53:28 -05:00
</Text>
2020-02-13 19:40:04 -05:00
</button>
}
</div>
}
<div className={innerContainerClasses}>
2020-03-11 19:56:18 -04:00
<div className={[_s.default, _s.flexRow, _s.py2, _s.width100PC].join(' ')}>
2020-03-06 23:53:28 -05:00
<StatusActionBarItem
title={formatMessage(messages.like)}
2020-04-02 12:57:04 -04:00
icon={!!status.get('favourited') ? 'liked' : 'like'}
active={!!status.get('favourited')}
2020-03-06 23:53:28 -05:00
onClick={this.handleFavoriteClick}
/>
<StatusActionBarItem
title={formatMessage(messages.comment)}
icon='comment'
onClick={this.handleReplyClick}
/>
<StatusActionBarItem
2020-04-06 21:53:23 -04:00
title={formatMessage(messages.repost)}
altTitle={!publicStatus ? formatMessage(messages.cannot_repost) : ''}
icon={!publicStatus ? 'lock' : 'repost'}
2020-03-06 23:53:28 -05:00
disabled={!publicStatus}
active={!!status.get('reblogged')}
onClick={this.handleRepostClick}
/>
<StatusActionBarItem
2020-03-24 23:08:43 -04:00
buttonRef={this.setShareButton}
2020-03-06 23:53:28 -05:00
title={formatMessage(messages.share)}
icon='share'
onClick={this.handleShareClick}
/>
2020-02-13 19:40:04 -05:00
</div>
</div>
</div>
2020-02-28 10:20:47 -05:00
)
}
}