import PropTypes from 'prop-types'; import React, { Component } from 'react'; import Autosuggest from 'react-autosuggest'; import Icon from 'Components/Icon'; import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import { icons } from 'Helpers/Props'; import translate from 'Utilities/String/translate'; import IndexerSearchResult from './IndexerSearchResult'; import styles from './IndexerSearchInput.css'; const ADD_NEW_TYPE = 'addNew'; class IndexerSearchInput extends Component { // // Lifecycle constructor(props, context) { super(props, context); this._autosuggest = null; this.state = { value: '', suggestions: [] }; } componentDidMount() { this.props.bindShortcut(shortcuts.MOVIE_SEARCH_INPUT.key, this.focusInput); } componentWillUnmount() { if (this._worker) { this._worker.removeEventListener('message', this.onSuggestionsReceived, false); this._worker.terminate(); this._worker = null; } } // // Control setAutosuggestRef = (ref) => { this._autosuggest = ref; } focusInput = (event) => { event.preventDefault(); this._autosuggest.input.focus(); } getSectionSuggestions(section) { return section.suggestions; } renderSectionTitle(section) { return (
{section.title} { section.loading && }
); } getSuggestionValue({ title }) { return title; } renderSuggestion(item, { query }) { if (item.type === ADD_NEW_TYPE) { return (
Search for {query}
); } return ( ); } reset() { this.setState({ value: '', suggestions: [], loading: false }); } // // Listeners onChange = (event, { newValue, method }) => { if (method === 'up' || method === 'down') { return; } this.setState({ value: newValue }); } onKeyDown = (event) => { if (event.shiftKey || event.altKey || event.ctrlKey) { return; } if (event.key === 'Escape') { this.reset(); return; } if (event.key !== 'Tab' && event.key !== 'Enter') { return; } const { suggestions, value } = this.state; const { highlightedSectionIndex } = this._autosuggest.state; if (!suggestions.length || highlightedSectionIndex) { this.props.onGoToAddNewMovie(value); this._autosuggest.input.blur(); this.reset(); return; } this._autosuggest.input.blur(); this.reset(); } onBlur = () => { this.reset(); } onSuggestionsClearRequested = () => { this.setState({ suggestions: [], loading: false }); } onSuggestionsFetchRequested = () => { this.setState({ suggestions: [], loading: false }); } onSuggestionSelected = (event, { suggestion }) => { if (suggestion.type === ADD_NEW_TYPE) { this.props.onGoToAddNewMovie(this.state.value); } } // // Render render() { const { value } = this.state; const suggestionGroups = []; suggestionGroups.push({ title: translate('SearchIndexers'), suggestions: [ { type: ADD_NEW_TYPE, title: value } ] }); const inputProps = { ref: this.setInputRef, className: styles.input, name: 'movieSearch', value, placeholder: translate('Search'), autoComplete: 'off', spellCheck: false, onChange: this.onChange, onKeyDown: this.onKeyDown, onBlur: this.onBlur, onFocus: this.onFocus }; const theme = { container: styles.container, containerOpen: styles.containerOpen, suggestionsContainer: styles.movieContainer, suggestionsList: styles.list, suggestion: styles.listItem, suggestionHighlighted: styles.highlighted }; return (
); } } IndexerSearchInput.propTypes = { onGoToAddNewMovie: PropTypes.func.isRequired, bindShortcut: PropTypes.func.isRequired }; export default keyboardShortcuts(IndexerSearchInput);