import CharacterCounter from './character_counter' ;
import Button from '../../../components/button' ;
import PureRenderMixin from 'react-addons-pure-render-mixin' ;
import ImmutablePropTypes from 'react-immutable-proptypes' ;
import ReplyIndicator from './reply_indicator' ;
import UploadButton from './upload_button' ;
import AutosuggestTextarea from '../../../components/autosuggest_textarea' ;
import AutosuggestAccountContainer from '../../compose/containers/autosuggest_account_container' ;
import { debounce } from 'react-decoration' ;
import UploadButtonContainer from '../containers/upload_button_container' ;
import { defineMessages , injectIntl , FormattedMessage } from 'react-intl' ;
import Toggle from 'react-toggle' ;
import { Motion , spring } from 'react-motion' ;
const messages = defineMessages ( {
placeholder : { id : 'compose_form.placeholder' , defaultMessage : 'What is on your mind?' } ,
publish : { id : 'compose_form.publish' , defaultMessage : 'Publish' }
} ) ;
const ComposeForm = React . createClass ( {
propTypes : {
intl : React . PropTypes . object . isRequired ,
text : React . PropTypes . string . isRequired ,
suggestion _token : React . PropTypes . string ,
suggestions : ImmutablePropTypes . list ,
sensitive : React . PropTypes . bool ,
unlisted : React . PropTypes . bool ,
private : React . PropTypes . bool ,
fileDropDate : React . PropTypes . instanceOf ( Date ) ,
is _submitting : React . PropTypes . bool ,
is _uploading : React . PropTypes . bool ,
in _reply _to : ImmutablePropTypes . map ,
media _count : React . PropTypes . number ,
me : React . PropTypes . number ,
onChange : React . PropTypes . func . isRequired ,
onSubmit : React . PropTypes . func . isRequired ,
onCancelReply : React . PropTypes . func . isRequired ,
onClearSuggestions : React . PropTypes . func . isRequired ,
onFetchSuggestions : React . PropTypes . func . isRequired ,
onSuggestionSelected : React . PropTypes . func . isRequired ,
onChangeSensitivity : React . PropTypes . func . isRequired ,
onChangeVisibility : React . PropTypes . func . isRequired ,
onChangeListability : React . PropTypes . func . isRequired ,
} ,
mixins : [ PureRenderMixin ] ,
handleChange ( e ) {
this . props . onChange ( e . target . value ) ;
} ,
handleKeyDown ( e ) {
if ( e . keyCode === 13 && ( e . ctrlKey || e . metaKey ) ) {
this . props . onSubmit ( ) ;
}
} ,
handleSubmit ( ) {
this . props . onSubmit ( ) ;
} ,
onSuggestionsClearRequested ( ) {
this . props . onClearSuggestions ( ) ;
} ,
@ debounce ( 500 )
onSuggestionsFetchRequested ( token ) {
this . props . onFetchSuggestions ( token ) ;
} ,
onSuggestionSelected ( tokenStart , token , value ) {
this . props . onSuggestionSelected ( tokenStart , token , value ) ;
} ,
handleChangeSensitivity ( e ) {
this . props . onChangeSensitivity ( e . target . checked ) ;
} ,
handleChangeVisibility ( e ) {
this . props . onChangeVisibility ( e . target . checked ) ;
} ,
handleChangeListability ( e ) {
this . props . onChangeListability ( e . target . checked ) ;
} ,
componentDidUpdate ( prevProps ) {
if ( ( prevProps . in _reply _to === null && this . props . in _reply _to !== null ) || ( prevProps . in _reply _to !== null && this . props . in _reply _to !== null && prevProps . in _reply _to . get ( 'id' ) !== this . props . in _reply _to . get ( 'id' ) ) ) {
// If replying to zero or one users, places the cursor at the end of the textbox.
// If replying to more than one user, selects any usernames past the first;
// this provides a convenient shortcut to drop everyone else from the conversation.
const selectionStart = this . props . text . search ( /\s/ ) + 1 ;
const selectionEnd = this . props . text . length ;
this . autosuggestTextarea . textarea . setSelectionRange ( selectionStart , selectionEnd ) ;
this . autosuggestTextarea . textarea . focus ( ) ;
}
} ,
setAutosuggestTextarea ( c ) {
this . autosuggestTextarea = c ;
} ,
render ( ) {
const { intl } = this . props ;
let replyArea = '' ;
const disabled = this . props . is _submitting || this . props . is _uploading ;
if ( this . props . in _reply _to ) {
replyArea = < ReplyIndicator status = { this . props . in _reply _to } onCancel = { this . props . onCancelReply } / > ;
}
let reply _to _other = ! ! this . props . in _reply _to && ( this . props . in _reply _to . getIn ( [ 'account' , 'id' ] ) !== this . props . me ) ;
return (
< div style = { { padding : '10px' } } >
{ replyArea }
< AutosuggestTextarea
ref = { this . setAutosuggestTextarea }
placeholder = { intl . formatMessage ( messages . placeholder ) }
disabled = { disabled }
fileDropDate = { this . props . fileDropDate }
value = { this . props . text }
onChange = { this . handleChange }
suggestions = { this . props . suggestions }
onKeyDown = { this . handleKeyDown }
onSuggestionsFetchRequested = { this . onSuggestionsFetchRequested }
onSuggestionsClearRequested = { this . onSuggestionsClearRequested }
onSuggestionSelected = { this . onSuggestionSelected }
/ >
< div style = { { marginTop : '10px' , overflow : 'hidden' } } >
< div style = { { float : 'right' } } > < Button text = { intl . formatMessage ( messages . publish ) } onClick = { this . handleSubmit } disabled = { disabled } / > < / div >
< div style = { { float : 'right' , marginRight : '16px' , lineHeight : '36px' } } > < CharacterCounter max = { 500 } text = { this . props . text } / > < / div >
< UploadButtonContainer style = { { paddingTop : '4px' } } / >
< / div >
< label style = { { display : 'block' , lineHeight : '24px' , verticalAlign : 'middle' , marginTop : '10px' , borderTop : '1px solid #282c37' , paddingTop : '10px' } } >
< Toggle checked = { this . props . private } onChange = { this . handleChangeVisibility } / >
< span style = { { display : 'inline-block' , verticalAlign : 'middle' , marginBottom : '14px' , marginLeft : '8px' , color : '#9baec8' } } > < FormattedMessage id = 'compose_form.private' defaultMessage = 'Mark as private' / > < / span >
< / label >
< Motion defaultStyle = { { opacity : ( this . props . private || reply _to _other ) ? 0 : 100 , height : ( this . props . private || reply _to _other ) ? 39.5 : 0 } } style = { { opacity : spring ( ( this . props . private || reply _to _other ) ? 0 : 100 ) , height : spring ( ( this . props . private || reply _to _other ) ? 0 : 39.5 ) } } >
{ ( { opacity , height } ) =>
< label style = { { display : 'block' , lineHeight : '24px' , verticalAlign : 'middle' , height : ` ${ height } px ` , overflow : 'hidden' , opacity : opacity / 100 } } >
< Toggle checked = { this . props . unlisted } onChange = { this . handleChangeListability } / >
< span style = { { display : 'inline-block' , verticalAlign : 'middle' , marginBottom : '14px' , marginLeft : '8px' , color : '#9baec8' } } > < FormattedMessage id = 'compose_form.unlisted' defaultMessage = 'Do not display in public timeline' / > < / span >
< / label >
}
< / Motion >
< Motion defaultStyle = { { opacity : 0 , height : 0 } } style = { { opacity : spring ( this . props . media _count === 0 ? 0 : 100 ) , height : spring ( this . props . media _count === 0 ? 0 : 39.5 ) } } >
{ ( { opacity , height } ) =>
< label style = { { display : 'block' , lineHeight : '24px' , verticalAlign : 'middle' , height : ` ${ height } px ` , overflow : 'hidden' , opacity : opacity / 100 } } >
< Toggle checked = { this . props . sensitive } onChange = { this . handleChangeSensitivity } / >
< span style = { { display : 'inline-block' , verticalAlign : 'middle' , marginBottom : '14px' , marginLeft : '8px' , color : '#9baec8' } } > < FormattedMessage id = 'compose_form.sensitive' defaultMessage = 'Mark content as sensitive' / > < / span >
< / label >
}
< / Motion >
< / div >
) ;
}
} ) ;
export default injectIntl ( ComposeForm ) ;