From ba9f61840519b6d93ba3e776f7052ef535972029 Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Wed, 1 Sep 2021 21:04:39 +0100 Subject: [PATCH] Lazy Loading fuse-worker and fixed some potential timing issues when it's slow. Also keep last result while typing. (cherry picked from commit 1e98002b8f3b01e41bff011644a9345c37c259c1) --- .../Page/Header/AuthorSearchInput.css | 8 +- .../Page/Header/AuthorSearchInput.js | 131 +++++++++++++----- .../src/Components/Page/Header/fuse.worker.js | 13 +- 3 files changed, 112 insertions(+), 40 deletions(-) diff --git a/frontend/src/Components/Page/Header/AuthorSearchInput.css b/frontend/src/Components/Page/Header/AuthorSearchInput.css index 77ec088d5..e71f194d5 100644 --- a/frontend/src/Components/Page/Header/AuthorSearchInput.css +++ b/frontend/src/Components/Page/Header/AuthorSearchInput.css @@ -4,15 +4,15 @@ } .loading { - margin-top: 18px; - margin-bottom: 18px; - text-align: center; + position: absolute; + display: inline-block; + 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/AuthorSearchInput.js b/frontend/src/Components/Page/Header/AuthorSearchInput.js index 0c673582b..0b6f33d5d 100644 --- a/frontend/src/Components/Page/Header/AuthorSearchInput.js +++ b/frontend/src/Components/Page/Header/AuthorSearchInput.js @@ -10,9 +10,7 @@ import AuthorSearchResult from './AuthorSearchResult'; import FuseWorker from './fuse.worker'; import styles from './AuthorSearchInput.css'; -const LOADING_TYPE = 'suggestionsLoading'; const ADD_NEW_TYPE = 'addNew'; -const workerInstance = new FuseWorker(); class AuthorSearchInput extends Component { @@ -23,6 +21,7 @@ class AuthorSearchInput extends Component { super(props, context); this._autosuggest = null; + this._worker = null; this.state = { value: '', @@ -32,7 +31,23 @@ class AuthorSearchInput extends Component { componentDidMount() { this.props.bindShortcut(shortcuts.AUTHOR_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 AuthorSearchInput extends Component { return (
{section.title} + + { + section.loading && + + }
); } @@ -72,16 +96,6 @@ class AuthorSearchInput 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; } @@ -128,7 +152,7 @@ class AuthorSearchInput extends Component { highlightedSuggestionIndex } = this._autosuggest.state; - if (!suggestions.length || suggestions[0].type === LOADING_TYPE || highlightedSectionIndex) { + if (!suggestions.length || highlightedSectionIndex) { this.props.onGoToAddNewAuthor(value); this._autosuggest.input.blur(); this.reset(); @@ -154,35 +178,74 @@ class AuthorSearchInput 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, - authors: this.props.authors - }; + if (!this.state.loading) { + return; + } - workerInstance.postMessage(payload); - }, 250); + const requestLoading = this.state.requestLoading; - onSuggestionsReceived = (message) => { this.setState({ - suggestions: message.data + requestValue: value, + requestLoading: true }); + + if (!requestLoading) { + const payload = { + value, + authors: this.props.authors + }; + + this.getWorker().postMessage(payload); + } + }, 250); + + onSuggestionsReceived = (message) => { + 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, + authors: this.props.authors + }; + + this.getWorker().postMessage(payload); + } } onSuggestionsClearRequested = () => { this.setState({ - suggestions: [] + suggestions: [], + loading: false }); } @@ -200,14 +263,16 @@ class AuthorSearchInput extends Component { render() { const { value, + loading, suggestions } = this.state; const suggestionGroups = []; - if (suggestions.length) { + if (suggestions.length || loading) { suggestionGroups.push({ title: 'Existing Author', + loading, suggestions }); } diff --git a/frontend/src/Components/Page/Header/fuse.worker.js b/frontend/src/Components/Page/Header/fuse.worker.js index 6a0799ca9..8d0f06c60 100644 --- a/frontend/src/Components/Page/Header/fuse.worker.js +++ b/frontend/src/Components/Page/Header/fuse.worker.js @@ -47,7 +47,7 @@ function getSuggestions(authors, value) { return suggestions; } -self.addEventListener('message', (e) => { +onmessage = function(e) { if (!e) { return; } @@ -57,5 +57,12 @@ self.addEventListener('message', (e) => { value } = e.data; - self.postMessage(getSuggestions(authors, value)); -}); + const suggestions = getSuggestions(authors, value); + + const results = { + value, + suggestions + }; + + self.postMessage(results); +};