2020-02-28 15:20:47 +00:00
|
|
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
|
|
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
|
|
|
import { defineMessages, injectIntl } from 'react-intl'
|
2020-02-08 06:12:01 +00:00
|
|
|
import classNames from 'classnames/bind'
|
2020-03-06 15:38:22 +00:00
|
|
|
import { openModal } from '../actions/modal'
|
2020-03-25 03:08:43 +00:00
|
|
|
import { openPopover } from '../actions/popover'
|
|
|
|
import { me } from '../initial_state'
|
2020-03-07 04:53:28 +00:00
|
|
|
import Text from './text'
|
2020-03-06 15:38:22 +00:00
|
|
|
import StatusActionBarItem from './status_action_bar_item'
|
2019-08-07 06:02:36 +01:00
|
|
|
|
|
|
|
const messages = defineMessages({
|
|
|
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
2019-08-17 12:09:15 +01:00
|
|
|
edit: { id: 'status.edit', defaultMessage: 'Edit' },
|
2019-08-07 06:02:36 +01:00
|
|
|
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 22:57:09 +00:00
|
|
|
comment: { id: 'status.comment', defaultMessage: 'Comment' },
|
2019-08-07 06:02:36 +01:00
|
|
|
more: { id: 'status.more', defaultMessage: 'More' },
|
2020-02-08 22:57:09 +00:00
|
|
|
share: { id: 'status.share', defaultMessage: 'Share' },
|
2019-08-07 06:02:36 +01:00
|
|
|
replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
|
2020-03-04 22:50:15 +00:00
|
|
|
repost: { id: 'repost', defaultMessage: 'Repost' },
|
2019-07-30 19:27:49 +01:00
|
|
|
quote: { id: 'status.quote', defaultMessage: 'Quote' },
|
2020-03-04 22:50:15 +00: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 19:27:49 +01:00
|
|
|
cannot_quote: { id: 'status.cannot_quote', defaultMessage: 'This post cannot be quoted' },
|
2020-02-08 22:57:09 +00:00
|
|
|
like: { id: 'status.like', defaultMessage: 'Like' },
|
2019-08-07 06:02:36 +01:00
|
|
|
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 15:20:47 +00:00
|
|
|
})
|
2019-08-07 06:02:36 +01:00
|
|
|
|
|
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
|
|
onOpenUnauthorizedModal() {
|
2020-02-28 15:20:47 +00:00
|
|
|
dispatch(openModal('UNAUTHORIZED'))
|
2019-08-07 06:02:36 +01:00
|
|
|
},
|
2020-03-25 03:08:43 +00:00
|
|
|
onOpenStatusSharePopover(targetRef, status) {
|
|
|
|
console.log("targetRef, status:", targetRef, status)
|
|
|
|
dispatch(openPopover('STATUS_SHARE', {
|
|
|
|
status,
|
|
|
|
targetRef,
|
|
|
|
position: 'top',
|
|
|
|
}))
|
|
|
|
},
|
2020-02-28 15:20:47 +00:00
|
|
|
})
|
2019-08-07 06:02:36 +01:00
|
|
|
|
2020-02-19 23:57:07 +00:00
|
|
|
const cx = classNames.bind(_s)
|
|
|
|
|
2020-02-25 16:04:44 +00:00
|
|
|
export default
|
|
|
|
@connect(null, mapDispatchToProps)
|
2019-08-07 06:02:36 +01:00
|
|
|
@injectIntl
|
|
|
|
class StatusActionBar extends ImmutablePureComponent {
|
|
|
|
|
|
|
|
static contextTypes = {
|
|
|
|
router: PropTypes.object,
|
2020-02-28 15:20:47 +00:00
|
|
|
}
|
2019-08-07 06:02:36 +01:00
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
status: ImmutablePropTypes.map.isRequired,
|
|
|
|
onOpenUnauthorizedModal: PropTypes.func.isRequired,
|
2020-03-25 03:08:43 +00:00
|
|
|
onOpenStatusSharePopover: PropTypes.func.isRequired,
|
2019-08-07 06:02:36 +01:00
|
|
|
onReply: PropTypes.func,
|
2019-07-30 19:27:49 +01:00
|
|
|
onQuote: PropTypes.func,
|
2020-03-04 22:26:01 +00:00
|
|
|
onFavorite: PropTypes.func,
|
|
|
|
onRepost: PropTypes.func,
|
2019-08-07 06:02:36 +01:00
|
|
|
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 15:20:47 +00:00
|
|
|
}
|
2019-08-07 06:02:36 +01: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 15:20:47 +00:00
|
|
|
this.props.onReply(this.props.status, this.context.router.history)
|
2019-08-07 06:02:36 +01:00
|
|
|
} else {
|
2020-02-28 15:20:47 +00:00
|
|
|
this.props.onOpenUnauthorizedModal()
|
2019-08-07 06:02:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-30 19:27:49 +01:00
|
|
|
handleQuoteClick = () => {
|
|
|
|
if (me) {
|
2020-02-28 15:20:47 +00:00
|
|
|
this.props.onQuote(this.props.status, this.context.router.history)
|
2019-07-30 19:27:49 +01:00
|
|
|
} else {
|
2020-02-28 15:20:47 +00:00
|
|
|
this.props.onOpenUnauthorizedModal()
|
2019-07-30 19:27:49 +01:00
|
|
|
}
|
2019-08-07 06:02:36 +01:00
|
|
|
}
|
|
|
|
|
2020-03-04 22:26:01 +00:00
|
|
|
handleFavoriteClick = () => {
|
2019-08-07 06:02:36 +01:00
|
|
|
if (me) {
|
2020-03-04 22:26:01 +00:00
|
|
|
this.props.onFavorite(this.props.status)
|
2019-08-07 06:02:36 +01:00
|
|
|
} else {
|
2020-02-28 15:20:47 +00:00
|
|
|
this.props.onOpenUnauthorizedModal()
|
2019-08-07 06:02:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-04 22:26:01 +00:00
|
|
|
handleRepostClick = e => {
|
2019-08-07 06:02:36 +01:00
|
|
|
if (me) {
|
2020-03-04 22:26:01 +00:00
|
|
|
this.props.onRepost(this.props.status, e)
|
2019-08-07 06:02:36 +01:00
|
|
|
} else {
|
2020-02-28 15:20:47 +00:00
|
|
|
this.props.onOpenUnauthorizedModal()
|
2019-08-07 06:02:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-07 04:53:28 +00:00
|
|
|
handleShareClick = () => {
|
2020-03-25 03:08:43 +00:00
|
|
|
console.log("handleShareClick:", this.shareButton, this.props.status)
|
|
|
|
this.props.onOpenStatusSharePopover(this.shareButton, this.props.status)
|
|
|
|
}
|
|
|
|
|
|
|
|
setShareButton = (n) => {
|
|
|
|
this.shareButton = n
|
2020-03-07 04:53:28 +00:00
|
|
|
}
|
|
|
|
|
2020-02-28 15:20:47 +00:00
|
|
|
render() {
|
|
|
|
const { status, intl: { formatMessage } } = this.props
|
2019-08-07 06:02:36 +01:00
|
|
|
|
2020-02-28 15:20:47 +00:00
|
|
|
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'))
|
2019-08-07 06:02:36 +01:00
|
|
|
|
2020-02-28 15:20:47 +00:00
|
|
|
const replyCount = status.get('replies_count')
|
|
|
|
const replyIcon = (status.get('in_reply_to_id', null) === null) ? 'reply' : 'reply-all'
|
|
|
|
const replyTitle = (status.get('in_reply_to_id', null) === null) ? formatMessage(messages.reply) : formatMessage(messages.replyAll)
|
2019-08-07 06:02:36 +01:00
|
|
|
|
2020-03-04 22:50:15 +00:00
|
|
|
const repostCount = status.get('reblogs_count')
|
|
|
|
const repostTitle = !publicStatus ? formatMessage(messages.cannot_repost) : formatMessage(messages.repost)
|
2019-08-07 06:02:36 +01:00
|
|
|
|
2020-03-08 23:02:28 +00:00
|
|
|
const favoriteCount = status.get('favourites_count') // : todo :
|
2019-08-07 06:02:36 +01:00
|
|
|
|
|
|
|
const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && (
|
2020-03-26 03:11:32 +00:00
|
|
|
<Button className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
2020-02-28 15:20:47 +00:00
|
|
|
)
|
2019-08-07 06:02:36 +01:00
|
|
|
|
2020-03-04 22:50:15 +00:00
|
|
|
const hasInteractions = favoriteCount > 0 || replyCount > 0 || repostCount > 0
|
2020-02-14 00:40:04 +00:00
|
|
|
const shouldCondense = (!!status.get('card') || status.get('media_attachments').size > 0) && !hasInteractions
|
|
|
|
|
|
|
|
const containerClasses = cx({
|
|
|
|
default: 1,
|
2020-03-11 23:56:18 +00:00
|
|
|
px10: 1,
|
|
|
|
mt10: !shouldCondense,
|
|
|
|
mt5: shouldCondense,
|
2020-02-14 00:40:04 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
const innerContainerClasses = cx({
|
|
|
|
default: 1,
|
2020-03-11 23:56:18 +00:00
|
|
|
py2: 1,
|
2020-02-14 00:40:04 +00:00
|
|
|
flexRow: 1,
|
|
|
|
width100PC: 1,
|
|
|
|
borderTop1PX: !shouldCondense,
|
2020-02-21 00:57:29 +00:00
|
|
|
borderColorSecondary: !shouldCondense,
|
2020-03-11 23:56:18 +00:00
|
|
|
mt5: hasInteractions,
|
2020-02-14 00:40:04 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
const interactionBtnClasses = cx({
|
|
|
|
default: 1,
|
|
|
|
text: 1,
|
|
|
|
cursorPointer: 1,
|
|
|
|
fontWeightNormal: 1,
|
2020-03-11 23:56:18 +00:00
|
|
|
mr10: 1,
|
|
|
|
py5: 1,
|
2020-02-14 00:40:04 +00:00
|
|
|
})
|
|
|
|
|
2020-02-08 06:12:01 +00:00
|
|
|
return (
|
2020-02-14 00:40:04 +00:00
|
|
|
<div className={containerClasses}>
|
|
|
|
{
|
|
|
|
hasInteractions &&
|
2020-03-11 23:56:18 +00:00
|
|
|
<div className={[_s.default, _s.flexRow, _s.px5].join(' ')}>
|
2020-03-07 04:53:28 +00:00
|
|
|
{
|
|
|
|
favoriteCount > 0 &&
|
2020-02-14 00:40:04 +00:00
|
|
|
<button className={interactionBtnClasses}>
|
2020-03-26 03:11:32 +00:00
|
|
|
<Text color='secondary' size='small'>
|
2020-03-07 04:53:28 +00:00
|
|
|
{favoriteCount}
|
|
|
|
Likes
|
|
|
|
</Text>
|
2020-02-14 00:40:04 +00:00
|
|
|
</button>
|
|
|
|
}
|
2020-03-07 04:53:28 +00:00
|
|
|
{
|
|
|
|
replyCount > 0 &&
|
2020-02-14 00:40:04 +00:00
|
|
|
<button className={interactionBtnClasses}>
|
2020-03-26 03:11:32 +00:00
|
|
|
<Text color='secondary' size='small'>
|
2020-03-07 04:53:28 +00:00
|
|
|
{replyCount}
|
|
|
|
Comments
|
|
|
|
</Text>
|
2020-02-14 00:40:04 +00:00
|
|
|
</button>
|
|
|
|
}
|
2020-03-07 04:53:28 +00:00
|
|
|
{
|
|
|
|
repostCount > 0 &&
|
2020-02-14 00:40:04 +00:00
|
|
|
<button className={interactionBtnClasses}>
|
2020-03-26 03:11:32 +00:00
|
|
|
<Text color='secondary' size='small'>
|
2020-03-07 04:53:28 +00:00
|
|
|
{repostCount}
|
|
|
|
Reposts
|
|
|
|
</Text>
|
2020-02-14 00:40:04 +00:00
|
|
|
</button>
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
<div className={innerContainerClasses}>
|
2020-03-11 23:56:18 +00:00
|
|
|
<div className={[_s.default, _s.flexRow, _s.py2, _s.width100PC].join(' ')}>
|
2020-03-07 04:53:28 +00:00
|
|
|
<StatusActionBarItem
|
|
|
|
title={formatMessage(messages.like)}
|
|
|
|
icon='like'
|
|
|
|
active={!!status.get('favorited')}
|
|
|
|
onClick={this.handleFavoriteClick}
|
|
|
|
/>
|
|
|
|
<StatusActionBarItem
|
|
|
|
title={formatMessage(messages.comment)}
|
|
|
|
icon='comment'
|
|
|
|
onClick={this.handleReplyClick}
|
|
|
|
/>
|
|
|
|
<StatusActionBarItem
|
|
|
|
title={repostTitle}
|
|
|
|
icon={(status.get('visibility') === 'private') ? 'lock' : 'repost'}
|
|
|
|
disabled={!publicStatus}
|
|
|
|
active={!!status.get('reblogged')}
|
|
|
|
onClick={this.handleRepostClick}
|
|
|
|
/>
|
|
|
|
<StatusActionBarItem
|
2020-03-25 03:08:43 +00:00
|
|
|
buttonRef={this.setShareButton}
|
2020-03-07 04:53:28 +00:00
|
|
|
title={formatMessage(messages.share)}
|
|
|
|
icon='share'
|
|
|
|
onClick={this.handleShareClick}
|
|
|
|
/>
|
2020-02-14 00:40:04 +00:00
|
|
|
</div>
|
2019-08-07 06:02:36 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
2020-02-28 15:20:47 +00:00
|
|
|
)
|
2019-08-07 06:02:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|