2020-05-02 07:25:55 +01:00
import { FormattedMessage } from 'react-intl'
2020-05-27 06:13:46 +01:00
import {
Map as ImmutableMap ,
List as ImmutableList ,
fromJS ,
} from 'immutable' ;
2019-07-02 08:10:25 +01:00
import {
replyCompose ,
mentionCompose ,
2020-05-27 06:13:46 +01:00
quoteCompose ,
2019-07-02 08:10:25 +01:00
} from '../actions/compose' ;
import {
2020-03-14 17:31:29 +00:00
repost ,
2020-03-04 22:26:01 +00:00
favorite ,
2020-03-14 17:31:29 +00:00
unrepost ,
2020-03-04 22:26:01 +00:00
unfavorite ,
2019-07-02 08:10:25 +01:00
} from '../actions/interactions' ;
import {
hideStatus ,
revealStatus ,
2020-04-22 06:00:11 +01:00
fetchComments ,
2020-05-05 06:16:01 +01:00
fetchContext ,
2019-07-02 08:10:25 +01:00
} from '../actions/statuses' ;
import { openModal } from '../actions/modal' ;
2020-04-22 06:00:11 +01:00
import { openPopover } from '../actions/popover' ;
2020-05-27 06:13:46 +01:00
import {
me ,
boostModal ,
} from '../initial_state'
import {
MODAL _BOOST ,
MODAL _CONFIRM ,
2020-05-27 06:15:10 +01:00
POPOVER _COMMENT _SORTING _OPTIONS ,
COMMENT _SORTING _TYPE _OLDEST ,
COMMENT _SORTING _TYPE _NEWEST ,
COMMENT _SORTING _TYPE _TOP ,
2020-05-27 06:13:46 +01:00
} from '../constants'
2020-05-07 00:40:54 +01:00
import { makeGetStatus } from '../selectors'
2020-01-29 21:53:33 +00:00
import Status from '../components/status' ;
2019-07-02 08:10:25 +01:00
2020-05-27 06:15:10 +01:00
const sortReplies = ( replyIds , state , type ) => {
if ( ! replyIds ) return replyIds
if ( type === COMMENT _SORTING _TYPE _OLDEST || ! type ) {
return replyIds // default
} else if ( type === COMMENT _SORTING _TYPE _NEWEST ) {
return replyIds . reverse ( )
} else if ( type === COMMENT _SORTING _TYPE _TOP ) {
let statusList = [ ]
replyIds . forEach ( ( replyId ) => {
const status = state . getIn ( [ 'statuses' , replyId ] )
if ( status ) {
statusList . push ( {
id : replyId ,
likeCount : status . get ( 'favourites_count' ) ,
} )
}
} )
statusList . sort ( ( a , b ) => parseFloat ( b . likeCount ) - parseFloat ( a . likeCount ) )
let newReplyIds = ImmutableList ( )
for ( let i = 0 ; i < statusList . length ; i ++ ) {
const block = statusList [ i ] ;
newReplyIds = newReplyIds . set ( i , block . id )
}
return newReplyIds
}
return replyIds
}
const getDescendants = ( state , status , highlightStatusId , commentSortingType ) => {
2020-05-05 06:16:01 +01:00
let descendantsIds = ImmutableList ( )
let indent = - 1
2020-05-27 06:15:10 +01:00
let index = 0
2020-05-05 06:16:01 +01:00
descendantsIds = descendantsIds . withMutations ( mutable => {
const ids = [ status . get ( 'id' ) ]
while ( ids . length > 0 ) {
let id = ids . shift ( )
2020-05-27 06:15:10 +01:00
let replies = state . getIn ( [ 'contexts' , 'replies' , id ] )
// Sort only Top-level replies
if ( index === 0 ) {
replies = sortReplies ( replies , state , commentSortingType )
}
2020-05-05 06:16:01 +01:00
if ( status . get ( 'id' ) !== id ) {
mutable . push ( ImmutableMap ( {
statusId : id ,
indent : indent ,
2020-05-27 06:15:10 +01:00
isHighlighted : ! ! highlightStatusId && highlightStatusId === id ,
2020-05-05 06:16:01 +01:00
} ) )
}
if ( replies ) {
replies . reverse ( ) . forEach ( reply => {
ids . unshift ( reply )
} ) ;
indent ++
indent = Math . min ( 2 , indent )
} else {
indent = 0 // reset
}
2020-05-27 06:15:10 +01:00
index ++
2020-05-05 06:16:01 +01:00
}
} )
return descendantsIds
}
2019-07-02 08:10:25 +01:00
const makeMapStateToProps = ( ) => {
2020-05-02 07:25:55 +01:00
const getStatus = makeGetStatus ( )
2019-07-02 08:10:25 +01:00
2020-04-22 06:00:11 +01:00
const mapStateToProps = ( state , props ) => {
2020-04-29 23:32:49 +01:00
const statusId = props . id || props . params . statusId
const username = props . params ? props . params . username : undefined
2020-05-27 06:15:10 +01:00
const commentSortingType = state . getIn ( [ 'settings' , 'commentSorting' ] )
2020-04-29 23:32:49 +01:00
const status = getStatus ( state , {
id : statusId ,
username : username ,
} )
2019-07-02 08:10:25 +01:00
2020-05-06 05:33:54 +01:00
let fetchedContext = false
2020-04-22 06:00:11 +01:00
let descendantsIds = ImmutableList ( )
2020-05-04 19:44:37 +01:00
let ancestorStatus
2020-05-05 06:16:01 +01:00
2020-05-06 05:33:54 +01:00
//
if ( status && status . get ( 'in_reply_to_account_id' ) && ! props . isChild ) {
2020-05-05 06:16:01 +01:00
fetchedContext = true
let inReplyTos = state . getIn ( [ 'contexts' , 'inReplyTos' ] )
let ancestorsIds = ImmutableList ( )
ancestorsIds = ancestorsIds . withMutations ( mutable => {
let id = statusId ;
while ( id ) {
mutable . unshift ( id )
id = inReplyTos . get ( id )
2020-04-22 06:00:11 +01:00
}
} )
2020-05-05 06:16:01 +01:00
const ancestorStatusId = ancestorsIds . get ( 0 )
2020-05-06 05:33:54 +01:00
if ( ancestorStatusId !== statusId ) {
ancestorStatus = getStatus ( state , {
id : ancestorStatusId ,
} )
descendantsIds = getDescendants ( state , ancestorStatus , statusId )
}
2020-04-22 06:00:11 +01:00
}
2020-05-05 06:16:01 +01:00
2020-05-06 05:33:54 +01:00
//
2020-05-05 06:16:01 +01:00
if ( status && status . get ( 'replies_count' ) > 0 && ! fetchedContext ) {
2020-05-27 06:15:10 +01:00
descendantsIds = getDescendants ( state , status , null , commentSortingType )
2020-05-04 19:44:37 +01:00
}
2020-05-05 06:16:01 +01:00
const isComment = ! ! status ? ! ! status . get ( 'in_reply_to_id' ) : false
2020-04-22 06:00:11 +01:00
return {
status ,
2020-05-04 19:44:37 +01:00
ancestorStatus ,
2020-05-05 06:16:01 +01:00
descendantsIds ,
isComment ,
2020-05-27 06:15:10 +01:00
commentSortingType ,
2020-05-07 00:40:54 +01:00
isComposeModalOpen : state . getIn ( [ 'modal' , 'modalType' ] ) === 'COMPOSE' ,
2020-04-22 06:00:11 +01:00
}
}
return mapStateToProps
2019-07-02 08:10:25 +01:00
} ;
2020-05-02 07:25:55 +01:00
const mapDispatchToProps = ( dispatch ) => ( {
onReply ( status , router , showModal ) {
2020-04-22 06:00:11 +01:00
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
2019-07-02 08:10:25 +01:00
dispatch ( ( _ , getState ) => {
2020-04-08 02:06:59 +01:00
const state = getState ( ) ;
2019-07-02 08:10:25 +01:00
if ( state . getIn ( [ 'compose' , 'text' ] ) . trim ( ) . length !== 0 ) {
dispatch ( openModal ( 'CONFIRM' , {
2020-05-02 07:25:55 +01:00
message : < FormattedMessage id = 'confirmations.reply.message' defaultMessage = 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' / > ,
confirm : < FormattedMessage id = 'confirmations.reply.confirm' defaultMessage = 'Reply' / > ,
2019-07-02 08:10:25 +01:00
onConfirm : ( ) => dispatch ( replyCompose ( status , router ) ) ,
2020-05-02 07:25:55 +01:00
} ) )
2019-07-02 08:10:25 +01:00
} else {
2020-05-02 07:25:55 +01:00
dispatch ( replyCompose ( status , router , showModal ) ) ;
2019-07-02 08:10:25 +01:00
}
2020-05-02 07:25:55 +01:00
} )
2019-07-02 08:10:25 +01:00
} ,
2019-09-17 16:23:51 +01:00
onShowRevisions ( status ) {
2020-04-22 06:00:11 +01:00
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
2019-09-17 16:23:51 +01:00
dispatch ( openModal ( 'STATUS_REVISION' , { status } ) ) ;
} ,
2020-03-04 22:26:01 +00:00
onFavorite ( status ) {
2020-04-22 06:00:11 +01:00
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
2019-07-02 08:10:25 +01:00
if ( status . get ( 'favourited' ) ) {
2020-03-04 22:26:01 +00:00
dispatch ( unfavorite ( status ) ) ;
2019-07-02 08:10:25 +01:00
} else {
2020-03-04 22:26:01 +00:00
dispatch ( favorite ( status ) ) ;
2019-07-02 08:10:25 +01:00
}
} ,
onMention ( account , router ) {
2020-04-22 06:00:11 +01:00
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
2019-07-02 08:10:25 +01:00
dispatch ( mentionCompose ( account , router ) ) ;
} ,
onOpenMedia ( media , index ) {
dispatch ( openModal ( 'MEDIA' , { media , index } ) ) ;
} ,
onOpenVideo ( media , time ) {
dispatch ( openModal ( 'VIDEO' , { media , time } ) ) ;
} ,
onToggleHidden ( status ) {
2020-04-22 06:00:11 +01:00
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
2019-07-02 08:10:25 +01:00
if ( status . get ( 'hidden' ) ) {
dispatch ( revealStatus ( status . get ( 'id' ) ) ) ;
} else {
dispatch ( hideStatus ( status . get ( 'id' ) ) ) ;
}
} ,
2020-05-03 06:22:49 +01:00
onOpenLikes ( status ) {
2020-05-09 03:17:19 +01:00
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
2020-05-03 06:22:49 +01:00
dispatch ( openModal ( 'STATUS_LIKES' , { status } ) )
} ,
onOpenReposts ( status ) {
2020-05-09 03:17:19 +01:00
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
2020-05-03 06:22:49 +01:00
dispatch ( openModal ( 'STATUS_REPOSTS' , { status } ) )
} ,
2020-05-09 03:17:19 +01:00
onFetchComments ( statusId ) {
dispatch ( fetchComments ( statusId ) )
} ,
onFetchContext ( statusId ) {
dispatch ( fetchContext ( statusId ) )
} ,
2020-05-03 06:22:49 +01:00
2020-05-27 06:13:46 +01:00
onQuote ( status , router ) {
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
dispatch ( ( _ , getState ) => {
const state = getState ( )
if ( state . getIn ( [ 'compose' , 'text' ] ) . trim ( ) . length !== 0 ) {
dispatch ( openModal ( MODAL _CONFIRM , {
message : < FormattedMessage id = 'confirmations.quote.message' defaultMessage = 'Quoting now will overwrite the message you are currently composing. Are you sure you want to proceed?' / > ,
confirm : < FormattedMessage id = 'confirmations.quote.confirm' defaultMessage = 'Quote' / > ,
onConfirm : ( ) => dispatch ( quoteCompose ( status , router ) ) ,
} ) )
} else {
dispatch ( quoteCompose ( status , router ) )
}
} )
} ,
onRepost ( status ) {
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
const alreadyReposted = status . get ( 'reblogged' )
if ( boostModal && ! alreadyReposted ) {
dispatch ( openModal ( MODAL _BOOST , {
status ,
onRepost : ( ) => dispatch ( repost ( status ) ) ,
} ) )
} else {
if ( alreadyReposted ) {
dispatch ( unrepost ( status ) )
} else {
dispatch ( repost ( status ) )
}
}
} ,
2020-05-27 06:15:10 +01:00
onCommentSortOpen ( targetRef , callback ) {
dispatch ( openPopover ( POPOVER _COMMENT _SORTING _OPTIONS , {
targetRef ,
callback ,
position : 'top' ,
} ) )
}
2019-07-02 08:10:25 +01:00
} ) ;
2020-04-23 07:13:29 +01:00
export default connect ( makeMapStateToProps , mapDispatchToProps ) ( Status ) ;