From f8c01e379c086c73acc8b2c4a374a3b0c9e32521 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 7 Dec 2022 18:02:19 +0100 Subject: [PATCH] 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 --- .../widgets/component-list/filterable-list-container.tsx | 2 +- .../src/browser/widgets/component-list/list-widget.tsx | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx b/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx index 3702d092c..35289f073 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx @@ -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; diff --git a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx index a27fa3cdc..25fea1050 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx @@ -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 | 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 | undefined): void { - this.searchOptionsChangeEmitter.fire(searchOptions); + this.didReceiveFirstFocus.promise.then(() => + this.searchOptionsChangeEmitter.fire(searchOptions) + ); } updateScrollBar(): void {