diff --git a/frontend/src/Components/Page/Header/SeriesSearchInput.css b/frontend/src/Components/Page/Header/SeriesSearchInput.css index 9927f1013..fbe5c47a7 100644 --- a/frontend/src/Components/Page/Header/SeriesSearchInput.css +++ b/frontend/src/Components/Page/Header/SeriesSearchInput.css @@ -4,15 +4,15 @@ } .loading { - margin-top: 18px; - margin-bottom: 18px; - text-align: center; + display: inline-block; + position: absolute; + margin-left: 5px; } .ripple { composes: ripple from '~Components/Loading/LoadingIndicator.css'; - border: 2px solid $toolbarColor; + border: 1px solid $toolbarColor; } .input { diff --git a/frontend/src/Components/Page/Header/SeriesSearchInput.js b/frontend/src/Components/Page/Header/SeriesSearchInput.js index 0bd5178c8..c351d0a59 100644 --- a/frontend/src/Components/Page/Header/SeriesSearchInput.js +++ b/frontend/src/Components/Page/Header/SeriesSearchInput.js @@ -10,9 +10,7 @@ import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import FuseWorker from './fuse.worker'; import styles from './SeriesSearchInput.css'; -const LOADING_TYPE = 'suggestionsLoading'; const ADD_NEW_TYPE = 'addNew'; -const workerInstance = new FuseWorker(); class SeriesSearchInput extends Component { @@ -23,6 +21,7 @@ class SeriesSearchInput extends Component { super(props, context); this._autosuggest = null; + this._worker = null; this.state = { value: '', @@ -32,7 +31,23 @@ class SeriesSearchInput extends Component { componentDidMount() { this.props.bindShortcut(shortcuts.SERIES_SEARCH_INPUT.key, this.focusInput); - workerInstance.addEventListener('message', this.onSuggestionsReceived, false); + } + + componentWillUnmount() { + if (this._worker) { + this._worker.removeEventListener('message', this.onSuggestionsReceived, false); + this._worker.terminate(); + this._worker = null; + } + } + + getWorker() { + if (!this._worker) { + this._worker = new FuseWorker(); + this._worker.addEventListener('message', this.onSuggestionsReceived, false); + } + + return this._worker; } // @@ -55,6 +70,15 @@ class SeriesSearchInput extends Component { return (
{section.title} + + { + section.loading && + + }
); } @@ -72,16 +96,6 @@ class SeriesSearchInput extends Component { ); } - if (item.type === LOADING_TYPE) { - return ( - - ); - } - return ( { + if (event.shiftKey || event.altKey || event.ctrlKey) { + return; + } + + if (event.key === 'Escape') { + this.reset(); + return; + } + if (event.key !== 'Tab' && event.key !== 'Enter') { return; } @@ -154,35 +178,74 @@ class SeriesSearchInput extends Component { } onSuggestionsFetchRequested = ({ value }) => { - this.setState({ - suggestions: [ - { - type: LOADING_TYPE, - title: value - } - ] - }); + if (!this.state.loading) { + this.setState({ + loading: true + }); + } + this.requestSuggestions(value); }; requestSuggestions = _.debounce((value) => { - const payload = { - value, - series: this.props.series - }; + if (!this.state.loading) { + return; + } - workerInstance.postMessage(payload); + const requestLoading = this.state.requestLoading; + + this.setState({ + requestValue: value, + requestLoading: true + }); + + if (!requestLoading) { + const payload = { + value, + series: this.props.series + }; + + this.getWorker().postMessage(payload); + } }, 250); onSuggestionsReceived = (message) => { - this.setState({ - suggestions: message.data - }); + const { + value, + suggestions + } = message.data; + + if (!this.state.loading) { + this.setState({ + requestValue: null, + requestLoading: false + }); + } else if (value === this.state.requestValue) { + this.setState({ + suggestions, + requestValue: null, + requestLoading: false, + loading: false + }); + } else { + this.setState({ + suggestions, + requestLoading: true + }); + + const payload = { + value: this.state.requestValue, + series: this.props.series + }; + + this.getWorker().postMessage(payload); + } } onSuggestionsClearRequested = () => { this.setState({ - suggestions: [] + suggestions: [], + loading: false }); } @@ -200,14 +263,16 @@ class SeriesSearchInput extends Component { render() { const { value, + loading, suggestions } = this.state; const suggestionGroups = []; - if (suggestions.length) { + if (suggestions.length || loading) { suggestionGroups.push({ title: 'Existing Series', + loading, suggestions }); } diff --git a/frontend/src/Components/Page/Header/SeriesSearchResult.js b/frontend/src/Components/Page/Header/SeriesSearchResult.js index 09ad9d983..aee3ce4bc 100644 --- a/frontend/src/Components/Page/Header/SeriesSearchResult.js +++ b/frontend/src/Components/Page/Header/SeriesSearchResult.js @@ -17,7 +17,7 @@ function SeriesSearchResult(props) { let alternateTitle = null; let tag = null; - if (match.key === 'alternateTitles.cleanTitle') { + if (match.key === 'alternateTitles.title') { alternateTitle = alternateTitles[match.arrayIndex]; } else if (match.key === 'tags.label') { tag = tags[match.arrayIndex]; diff --git a/frontend/src/Components/Page/Header/fuse.worker.js b/frontend/src/Components/Page/Header/fuse.worker.js index 708eaf8e0..500c0c3b5 100644 --- a/frontend/src/Components/Page/Header/fuse.worker.js +++ b/frontend/src/Components/Page/Header/fuse.worker.js @@ -49,7 +49,7 @@ function getSuggestions(series, value) { return suggestions; } -self.addEventListener('message', (e) => { +onmessage = function(e) { if (!e) { return; } @@ -59,5 +59,12 @@ self.addEventListener('message', (e) => { value } = e.data; - self.postMessage(getSuggestions(series, value)); -}); + const suggestions = getSuggestions(series, value); + + const results = { + value, + suggestions + }; + + self.postMessage(results); +};