@ -2,9 +2,28 @@ import React from 'react';
import PropTypes from 'prop-types' ;
import ImmutablePropTypes from 'react-immutable-proptypes' ;
import ImmutablePureComponent from 'react-immutable-pure-component' ;
import StatusContainer from '../../../containers/status_container' ;
import StatusContent from 'mastodon/components/status_content' ;
import AttachmentList from 'mastodon/components/attachment_list' ;
import { defineMessages , injectIntl , FormattedMessage } from 'react-intl' ;
import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container' ;
import AvatarComposite from 'mastodon/components/avatar_composite' ;
import Permalink from 'mastodon/components/permalink' ;
import IconButton from 'mastodon/components/icon_button' ;
import RelativeTimestamp from 'mastodon/components/relative_timestamp' ;
import { HotKeys } from 'react-hotkeys' ;
export default class Conversation extends ImmutablePureComponent {
const messages = defineMessages ( {
more : { id : 'status.more' , defaultMessage : 'More' } ,
open : { id : 'conversation.open' , defaultMessage : 'View conversation' } ,
reply : { id : 'status.reply' , defaultMessage : 'Reply' } ,
markAsRead : { id : 'conversation.mark_as_read' , defaultMessage : 'Mark as read' } ,
delete : { id : 'conversation.delete' , defaultMessage : 'Delete conversation' } ,
muteConversation : { id : 'status.mute_conversation' , defaultMessage : 'Mute conversation' } ,
unmuteConversation : { id : 'status.unmute_conversation' , defaultMessage : 'Unmute conversation' } ,
} ) ;
export default @ injectIntl
class Conversation extends ImmutablePureComponent {
static contextTypes = {
router : PropTypes . object ,
@ -13,11 +32,12 @@ export default class Conversation extends ImmutablePureComponent {
static propTypes = {
conversationId : PropTypes . string . isRequired ,
accounts : ImmutablePropTypes . list . isRequired ,
lastStatusId : PropTypes . string ,
lastStatus : Immutable PropTypes. map ,
unread : PropTypes . bool . isRequired ,
onMoveUp : PropTypes . func ,
onMoveDown : PropTypes . func ,
markRead : PropTypes . func . isRequired ,
intl : PropTypes . object . isRequired ,
} ;
handleClick = ( ) => {
@ -25,13 +45,25 @@ export default class Conversation extends ImmutablePureComponent {
return ;
}
const { lastStatusId , unread , markRead } = this . props ;
const { lastStatus , unread , markRead } = this . props ;
if ( unread ) {
markRead ( ) ;
}
this . context . router . history . push ( ` /statuses/ ${ lastStatusId } ` ) ;
this . context . router . history . push ( ` /statuses/ ${ lastStatus . get ( 'id' ) } ` ) ;
}
handleMarkAsRead = ( ) => {
this . props . markRead ( ) ;
}
handleReply = ( ) => {
this . props . reply ( this . props . lastStatus , this . context . router . history ) ;
}
handleDelete = ( ) => {
this . props . delete ( ) ;
}
handleHotkeyMoveUp = ( ) => {
@ -42,22 +74,88 @@ export default class Conversation extends ImmutablePureComponent {
this . props . onMoveDown ( this . props . conversationId ) ;
}
handleConversationMute = ( ) => {
this . props . onMute ( this . props . lastStatus ) ;
}
handleShowMore = ( ) => {
this . props . onToggleHidden ( this . props . lastStatus ) ;
}
render ( ) {
const { accounts , lastStatusId , unread } = this . props ;
const { accounts , lastStatus , unread , intl } = this . props ;
if ( lastStatusId === null ) {
if ( lastStatus === null ) {
return null ;
}
const menu = [
{ text : intl . formatMessage ( messages . open ) , action : this . handleClick } ,
null ,
] ;
menu . push ( { text : intl . formatMessage ( lastStatus . get ( 'muted' ) ? messages . unmuteConversation : messages . muteConversation ) , action : this . handleConversationMute } ) ;
if ( unread ) {
menu . push ( { text : intl . formatMessage ( messages . markAsRead ) , action : this . handleMarkAsRead } ) ;
menu . push ( null ) ;
}
menu . push ( { text : intl . formatMessage ( messages . delete ) , action : this . handleDelete } ) ;
const names = accounts . map ( a => < Permalink to = { ` /accounts/ ${ a . get ( 'id' ) } ` } href = { a . get ( 'url' ) } key = { a . get ( 'id' ) } title = { a . get ( 'acct' ) } > < bdi > < strong className = 'display-name__html' dangerouslySetInnerHTML = { { __html : a . get ( 'display_name_html' ) } } / > < / b d i > < / P e r m a l i n k > ) . r e d u c e ( ( p r e v , c u r ) = > [ p r e v , ' , ' , c u r ] ) ;
const handlers = {
reply : this . handleReply ,
open : this . handleClick ,
moveUp : this . handleHotkeyMoveUp ,
moveDown : this . handleHotkeyMoveDown ,
toggleHidden : this . handleShowMore ,
} ;
return (
< StatusContainer
id = { lastStatusId }
unread = { unread }
otherAccounts = { accounts }
onMoveUp = { this . handleHotkeyMoveUp }
onMoveDown = { this . handleHotkeyMoveDown }
onClick = { this . handleClick }
/ >
< HotKeys handlers = { handlers } >
< div className = 'conversation focusable muted' tabIndex = '0' >
< div className = 'conversation__avatar' >
< AvatarComposite accounts = { accounts } size = { 48 } / >
< / d i v >
< div className = 'conversation__content' >
< div className = 'conversation__content__info' >
< div className = 'conversation__content__relative-time' >
< RelativeTimestamp timestamp = { lastStatus . get ( 'created_at' ) } / >
< / d i v >
< div className = 'conversation__content__names' >
< FormattedMessage id = 'conversation.with' defaultMessage = 'With {names}' values = { { names : < span > { names } < /span> }} / >
< / d i v >
< / d i v >
< StatusContent
status = { lastStatus }
onClick = { this . handleClick }
expanded = { ! lastStatus . get ( 'hidden' ) }
onExpandedToggle = { this . handleShowMore }
collapsable
/ >
{ lastStatus . get ( 'media_attachments' ) . size > 0 && (
< AttachmentList
compact
media = { lastStatus . get ( 'media_attachments' ) }
/ >
) }
< div className = 'status__action-bar' >
< IconButton className = 'status__action-bar-button' title = { intl . formatMessage ( messages . reply ) } icon = 'reply' onClick = { this . handleReply } / >
< div className = 'status__action-bar-dropdown' >
< DropdownMenuContainer status = { lastStatus } items = { menu } icon = 'ellipsis-h' size = { 18 } direction = 'right' title = { intl . formatMessage ( messages . more ) } / >
< / d i v >
< / d i v >
< / d i v >
< / d i v >
< / H o t K e y s >
) ;
}