fix: list view filtering when opening the view

When the widget is opened the first time with any search options,
the widget might miss the refresh event as it does not happen at
instantiation time. This PR ensures that all list widget refresh
events wait until the React component is rendered and is visible
in the UI.

This change also ensures that the debounced search will run with
the most recent search options by setting the `trailing` property
of the debounced function to `true`.

Closes #1740

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta 2022-12-07 18:02:19 +01:00 committed by Akos Kitta
parent af468a73bc
commit f8c01e379c
2 changed files with 7 additions and 2 deletions

View File

@ -32,7 +32,7 @@ export class FilterableListContainer<
}
override componentDidMount(): void {
this.search = debounce(this.search, 500);
this.search = debounce(this.search, 500, { trailing: true });
this.search(this.state.searchOptions);
this.props.searchOptionsDidChange((newSearchOptions) => {
const { searchOptions } = this.state;

View File

@ -7,6 +7,7 @@ import {
import { Widget } from '@theia/core/shared/@phosphor/widgets';
import { Message } from '@theia/core/shared/@phosphor/messaging';
import { Emitter } from '@theia/core/lib/common/event';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
import { CommandService } from '@theia/core/lib/common/command';
import { MessageService } from '@theia/core/lib/common/message-service';
@ -42,6 +43,7 @@ export abstract class ListWidget<
* Do not touch or use it. It is for setting the focus on the `input` after the widget activation.
*/
protected focusNode: HTMLElement | undefined;
private readonly didReceiveFirstFocus = new Deferred();
protected readonly searchOptionsChangeEmitter = new Emitter<
Partial<S> | undefined
>();
@ -117,6 +119,7 @@ export abstract class ListWidget<
protected onFocusResolved = (element: HTMLElement | undefined): void => {
this.focusNode = element;
this.didReceiveFirstFocus.resolve();
};
protected async install({
@ -192,7 +195,9 @@ export abstract class ListWidget<
* If it is `undefined`, updates the view state by re-running the search with the current `filterText` term.
*/
refresh(searchOptions: Partial<S> | undefined): void {
this.searchOptionsChangeEmitter.fire(searchOptions);
this.didReceiveFirstFocus.promise.then(() =>
this.searchOptionsChangeEmitter.fire(searchOptions)
);
}
updateScrollBar(): void {