|
|
@ -4,7 +4,7 @@ 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 Autosuggest from 'react-autosuggest'; |
|
|
|
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'; |
|
|
@ -16,59 +16,12 @@ const messages = defineMessages({ |
|
|
|
publish: { id: 'compose_form.publish', defaultMessage: 'Publish' } |
|
|
|
}); |
|
|
|
|
|
|
|
const getTokenForSuggestions = (str, caretPosition) => { |
|
|
|
let word; |
|
|
|
|
|
|
|
let left = str.slice(0, caretPosition).search(/\S+$/); |
|
|
|
let right = str.slice(caretPosition).search(/\s/); |
|
|
|
|
|
|
|
if (right < 0) { |
|
|
|
word = str.slice(left); |
|
|
|
} else { |
|
|
|
word = str.slice(left, right + caretPosition); |
|
|
|
} |
|
|
|
|
|
|
|
if (!word || word.trim().length < 2 || word[0] !== '@') { |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
word = word.trim().toLowerCase().slice(1); |
|
|
|
|
|
|
|
if (word.length > 0) { |
|
|
|
return word; |
|
|
|
} else { |
|
|
|
return null; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const getSuggestionValue = suggestionId => suggestionId; |
|
|
|
const renderSuggestion = suggestionId => <AutosuggestAccountContainer id={suggestionId} />; |
|
|
|
|
|
|
|
const textareaStyle = { |
|
|
|
display: 'block', |
|
|
|
boxSizing: 'border-box', |
|
|
|
width: '100%', |
|
|
|
height: '100px', |
|
|
|
resize: 'none', |
|
|
|
border: 'none', |
|
|
|
color: '#282c37', |
|
|
|
padding: '10px', |
|
|
|
fontFamily: 'Roboto', |
|
|
|
fontSize: '14px', |
|
|
|
margin: '0', |
|
|
|
resize: 'vertical' |
|
|
|
}; |
|
|
|
|
|
|
|
const renderInputComponent = inputProps => ( |
|
|
|
<textarea {...inputProps} className='compose-form__textarea' style={textareaStyle} /> |
|
|
|
); |
|
|
|
|
|
|
|
const ComposeForm = React.createClass({ |
|
|
|
|
|
|
|
propTypes: { |
|
|
|
text: React.PropTypes.string.isRequired, |
|
|
|
suggestion_token: React.PropTypes.string, |
|
|
|
suggestions: React.PropTypes.array, |
|
|
|
suggestions: ImmutablePropTypes.list, |
|
|
|
sensitive: React.PropTypes.bool, |
|
|
|
unlisted: React.PropTypes.bool, |
|
|
|
is_submitting: React.PropTypes.bool, |
|
|
@ -87,10 +40,6 @@ const ComposeForm = React.createClass({ |
|
|
|
mixins: [PureRenderMixin], |
|
|
|
|
|
|
|
handleChange (e) { |
|
|
|
if (typeof e.target.value === 'undefined' || typeof e.target.value === 'number') { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
this.props.onChange(e.target.value); |
|
|
|
}, |
|
|
|
|
|
|
@ -104,45 +53,17 @@ const ComposeForm = React.createClass({ |
|
|
|
this.props.onSubmit(); |
|
|
|
}, |
|
|
|
|
|
|
|
componentDidUpdate (prevProps) { |
|
|
|
if (prevProps.text !== this.props.text || prevProps.in_reply_to !== this.props.in_reply_to) { |
|
|
|
const textarea = this.autosuggest.input; |
|
|
|
|
|
|
|
if (textarea) { |
|
|
|
textarea.focus(); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
onSuggestionsClearRequested () { |
|
|
|
this.props.onClearSuggestions(); |
|
|
|
}, |
|
|
|
|
|
|
|
@debounce(500) |
|
|
|
onSuggestionsFetchRequested ({ value }) { |
|
|
|
const textarea = this.autosuggest.input; |
|
|
|
|
|
|
|
if (textarea) { |
|
|
|
const token = getTokenForSuggestions(value, textarea.selectionStart); |
|
|
|
|
|
|
|
if (token !== null) { |
|
|
|
this.props.onFetchSuggestions(token); |
|
|
|
} else { |
|
|
|
this.props.onClearSuggestions(); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
onSuggestionSelected (e, { suggestionValue }) { |
|
|
|
const textarea = this.autosuggest.input; |
|
|
|
|
|
|
|
if (textarea) { |
|
|
|
this.props.onSuggestionSelected(textarea.selectionStart, suggestionValue); |
|
|
|
} |
|
|
|
onSuggestionsFetchRequested (token) { |
|
|
|
this.props.onFetchSuggestions(token); |
|
|
|
}, |
|
|
|
|
|
|
|
setRef (c) { |
|
|
|
this.autosuggest = c; |
|
|
|
onSuggestionSelected (tokenStart, token, value) { |
|
|
|
this.props.onSuggestionSelected(tokenStart, token, value); |
|
|
|
}, |
|
|
|
|
|
|
|
handleChangeSensitivity (e) { |
|
|
@ -153,6 +74,16 @@ const ComposeForm = React.createClass({ |
|
|
|
this.props.onChangeVisibility(e.target.checked); |
|
|
|
}, |
|
|
|
|
|
|
|
componentDidUpdate (prevProps) { |
|
|
|
if (prevProps.in_reply_to !== this.props.in_reply_to) { |
|
|
|
this.autosuggestTextarea.textarea.focus(); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
setAutosuggestTextarea (c) { |
|
|
|
this.autosuggestTextarea = c; |
|
|
|
}, |
|
|
|
|
|
|
|
render () { |
|
|
|
const { intl } = this.props; |
|
|
|
let replyArea = ''; |
|
|
@ -162,29 +93,20 @@ const ComposeForm = React.createClass({ |
|
|
|
replyArea = <ReplyIndicator status={this.props.in_reply_to} onCancel={this.props.onCancelReply} />; |
|
|
|
} |
|
|
|
|
|
|
|
const inputProps = { |
|
|
|
placeholder: intl.formatMessage(messages.placeholder), |
|
|
|
value: this.props.text, |
|
|
|
onKeyUp: this.handleKeyUp, |
|
|
|
onChange: this.handleChange, |
|
|
|
disabled: disabled |
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
|
<div style={{ padding: '10px' }}> |
|
|
|
{replyArea} |
|
|
|
|
|
|
|
<Autosuggest |
|
|
|
ref={this.setRef} |
|
|
|
<AutosuggestTextarea |
|
|
|
ref={this.setAutosuggestTextarea} |
|
|
|
placeholder={intl.formatMessage(messages.placeholder)} |
|
|
|
disabled={disabled} |
|
|
|
value={this.props.text} |
|
|
|
onChange={this.handleChange} |
|
|
|
suggestions={this.props.suggestions} |
|
|
|
focusFirstSuggestion={true} |
|
|
|
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} |
|
|
|
onSuggestionsClearRequested={this.onSuggestionsClearRequested} |
|
|
|
onSuggestionSelected={this.onSuggestionSelected} |
|
|
|
getSuggestionValue={getSuggestionValue} |
|
|
|
renderSuggestion={renderSuggestion} |
|
|
|
renderInputComponent={renderInputComponent} |
|
|
|
inputProps={inputProps} |
|
|
|
/> |
|
|
|
|
|
|
|
<div style={{ marginTop: '10px', overflow: 'hidden' }}> |
|
|
|