mirror of
https://github.com/Readarr/Readarr
synced 2026-02-21 14:13:06 +01:00
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)
This commit is contained in:
parent
468ebc3307
commit
ba9f618405
3 changed files with 112 additions and 40 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div className={styles.sectionTitle}>
|
||||
{section.title}
|
||||
|
||||
{
|
||||
section.loading &&
|
||||
<LoadingIndicator
|
||||
className={styles.loading}
|
||||
rippleClassName={styles.ripple}
|
||||
size={20}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -72,16 +96,6 @@ class AuthorSearchInput extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
if (item.type === LOADING_TYPE) {
|
||||
return (
|
||||
<LoadingIndicator
|
||||
className={styles.loading}
|
||||
rippleClassName={styles.ripple}
|
||||
size={30}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthorSearchResult
|
||||
{...item.item}
|
||||
|
|
@ -98,7 +112,8 @@ class AuthorSearchInput extends Component {
|
|||
reset() {
|
||||
this.setState({
|
||||
value: '',
|
||||
suggestions: []
|
||||
suggestions: [],
|
||||
loading: false
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +129,15 @@ class AuthorSearchInput extends Component {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
const requestLoading = this.state.requestLoading;
|
||||
|
||||
this.setState({
|
||||
requestValue: value,
|
||||
requestLoading: true
|
||||
});
|
||||
|
||||
if (!requestLoading) {
|
||||
const payload = {
|
||||
value,
|
||||
authors: this.props.authors
|
||||
};
|
||||
|
||||
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,
|
||||
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
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue