mastodon/app/assets/javascripts/components/features/compose/components/search.jsx

125 lines
3.5 KiB
React
Raw Normal View History

2016-11-13 12:04:18 +00:00
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Autosuggest from 'react-autosuggest';
import AutosuggestAccountContainer from '../containers/autosuggest_account_container';
import AutosuggestStatusContainer from '../containers/autosuggest_status_container';
2016-11-13 12:13:36 +00:00
import { debounce } from 'react-decoration';
2016-11-18 14:36:16 +00:00
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
const messages = defineMessages({
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }
});
2016-11-13 12:04:18 +00:00
const getSuggestionValue = suggestion => suggestion.value;
const renderSuggestion = suggestion => {
if (suggestion.type === 'account') {
return <AutosuggestAccountContainer id={suggestion.id} />;
} else if (suggestion.type === 'hashtag') {
return <span>#{suggestion.id}</span>;
2016-11-13 12:04:18 +00:00
} else {
return <AutosuggestStatusContainer id={suggestion.id} />;
2016-11-13 12:04:18 +00:00
}
};
const renderSectionTitle = section => (
2016-11-18 14:36:16 +00:00
<strong><FormattedMessage id={`search.${section.title}`} defaultMessage={section.title} /></strong>
2016-11-13 12:04:18 +00:00
);
const getSectionSuggestions = section => section.items;
const outerStyle = {
padding: '10px',
lineHeight: '20px',
position: 'relative'
};
const iconStyle = {
position: 'absolute',
top: '18px',
right: '20px',
fontSize: '18px',
pointerEvents: 'none'
};
const Search = React.createClass({
contextTypes: {
router: React.PropTypes.object
},
propTypes: {
suggestions: React.PropTypes.array.isRequired,
value: React.PropTypes.string.isRequired,
onChange: React.PropTypes.func.isRequired,
onClear: React.PropTypes.func.isRequired,
onFetch: React.PropTypes.func.isRequired,
onReset: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired
2016-11-13 12:04:18 +00:00
},
mixins: [PureRenderMixin],
onChange (_, { newValue }) {
if (typeof newValue !== 'string') {
return;
}
this.props.onChange(newValue);
},
onSuggestionsClearRequested () {
this.props.onClear();
},
2016-11-13 12:13:36 +00:00
@debounce(500)
2016-11-13 12:04:18 +00:00
onSuggestionsFetchRequested ({ value }) {
value = value.replace('#', '');
this.props.onFetch(value.trim());
},
onSuggestionSelected (_, { suggestion }) {
if (suggestion.type === 'account') {
this.context.router.push(`/accounts/${suggestion.id}`);
} else if(suggestion.type === 'hashtag') {
this.context.router.push(`/timelines/tag/${suggestion.id}`);
} else {
this.context.router.push(`/statuses/${suggestion.id}`);
2016-11-13 12:04:18 +00:00
}
},
render () {
const inputProps = {
2016-11-18 14:36:16 +00:00
placeholder: this.props.intl.formatMessage(messages.placeholder),
2016-11-13 12:04:18 +00:00
value: this.props.value,
onChange: this.onChange,
className: 'search__input'
2016-11-13 12:04:18 +00:00
};
return (
<div className='search' style={outerStyle}>
2016-11-13 12:04:18 +00:00
<Autosuggest
multiSection={true}
suggestions={this.props.suggestions}
focusFirstSuggestion={true}
focusInputOnSuggestionClick={false}
alwaysRenderSuggestions={false}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
onSuggestionSelected={this.onSuggestionSelected}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
renderSectionTitle={renderSectionTitle}
getSectionSuggestions={getSectionSuggestions}
inputProps={inputProps}
/>
<div style={iconStyle}><i className='fa fa-search' /></div>
</div>
);
},
});
export default injectIntl(Search);