Skip to content

Commit 2b0d397

Browse files
author
Akos Kitta
committed
Generic type for the search options.
Signed-off-by: Akos Kitta <[email protected]>
1 parent a4a91d6 commit 2b0d397

9 files changed

+92
-40
lines changed

arduino-ide-extension/src/browser/boards/boards-list-widget.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
postConstruct,
55
} from '@theia/core/shared/inversify';
66
import {
7+
BoardSearch,
78
BoardsPackage,
89
BoardsService,
910
} from '../../common/protocol/boards-service';
@@ -12,7 +13,7 @@ import { ListItemRenderer } from '../widgets/component-list/list-item-renderer';
1213
import { nls } from '@theia/core/lib/common';
1314

1415
@injectable()
15-
export class BoardsListWidget extends ListWidget<BoardsPackage> {
16+
export class BoardsListWidget extends ListWidget<BoardsPackage, BoardSearch> {
1617
static WIDGET_ID = 'boards-list-widget';
1718
static WIDGET_LABEL = nls.localize('arduino/boardsManager', 'Boards Manager');
1819

arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import { injectable } from '@theia/core/shared/inversify';
22
import { BoardsListWidget } from './boards-list-widget';
3-
import { BoardsPackage } from '../../common/protocol/boards-service';
3+
import type {
4+
BoardSearch,
5+
BoardsPackage,
6+
} from '../../common/protocol/boards-service';
47
import { ListWidgetFrontendContribution } from '../widgets/component-list/list-widget-frontend-contribution';
58

69
@injectable()
7-
export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendContribution<BoardsPackage> {
10+
export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendContribution<
11+
BoardsPackage,
12+
BoardSearch
13+
> {
814
constructor() {
915
super({
1016
widgetId: BoardsListWidget.WIDGET_ID,

arduino-ide-extension/src/browser/library/library-list-widget.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { injectable, postConstruct, inject } from '@theia/core/shared/inversify';
1+
import {
2+
injectable,
3+
postConstruct,
4+
inject,
5+
} from '@theia/core/shared/inversify';
26
import { Message } from '@theia/core/shared/@phosphor/messaging';
37
import { addEventListener } from '@theia/core/lib/browser/widgets/widget';
48
import { DialogProps } from '@theia/core/lib/browser/dialogs';
59
import { AbstractDialog } from '../theia/dialogs/dialogs';
610
import {
711
LibraryPackage,
12+
LibrarySearch,
813
LibraryService,
914
} from '../../common/protocol/library-service';
1015
import { ListWidget } from '../widgets/component-list/list-widget';
@@ -13,7 +18,10 @@ import { ListItemRenderer } from '../widgets/component-list/list-item-renderer';
1318
import { nls } from '@theia/core/lib/common';
1419

1520
@injectable()
16-
export class LibraryListWidget extends ListWidget<LibraryPackage> {
21+
export class LibraryListWidget extends ListWidget<
22+
LibraryPackage,
23+
LibrarySearch
24+
> {
1725
static WIDGET_ID = 'library-list-widget';
1826
static WIDGET_LABEL = nls.localize(
1927
'arduino/library/title',
@@ -41,7 +49,9 @@ export class LibraryListWidget extends ListWidget<LibraryPackage> {
4149
protected override init(): void {
4250
super.init();
4351
this.toDispose.pushAll([
44-
this.notificationCenter.onLibraryDidInstall(() => this.refresh(undefined)),
52+
this.notificationCenter.onLibraryDidInstall(() =>
53+
this.refresh(undefined)
54+
),
4555
this.notificationCenter.onLibraryDidUninstall(() =>
4656
this.refresh(undefined)
4757
),

arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx

+30-22
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,24 @@ import { ResponseServiceClient } from '../../../common/protocol';
1616
import { nls } from '@theia/core/lib/common';
1717

1818
export class FilterableListContainer<
19-
T extends ArduinoComponent
19+
T extends ArduinoComponent,
20+
S extends Searchable.Options
2021
> extends React.Component<
21-
FilterableListContainer.Props<T>,
22-
FilterableListContainer.State<T>
22+
FilterableListContainer.Props<T, S>,
23+
FilterableListContainer.State<T, S>
2324
> {
24-
constructor(props: Readonly<FilterableListContainer.Props<T>>) {
25+
constructor(props: Readonly<FilterableListContainer.Props<T, S>>) {
2526
super(props);
2627
this.state = {
27-
filterText: '',
28+
searchOptions: { query: '' } as S,
2829
items: [],
2930
};
3031
}
3132

3233
override componentDidMount(): void {
3334
this.search = debounce(this.search, 500);
34-
this.handleFilterTextChange('');
35-
this.props.filterTextChangeEvent(this.handleFilterTextChange.bind(this));
35+
this.handleQueryChange('');
36+
this.props.filterTextChangeEvent(this.handleQueryChange.bind(this));
3637
}
3738

3839
override componentDidUpdate(): void {
@@ -59,8 +60,8 @@ export class FilterableListContainer<
5960
return (
6061
<SearchBar
6162
resolveFocus={this.props.resolveFocus}
62-
filterText={this.state.filterText}
63-
onFilterTextChanged={this.handleFilterTextChange}
63+
filterText={this.state.searchOptions.query ?? ''}
64+
onFilterTextChanged={this.handleQueryChange}
6465
/>
6566
);
6667
}
@@ -79,17 +80,21 @@ export class FilterableListContainer<
7980
);
8081
}
8182

82-
protected handleFilterTextChange = (
83-
filterText: string = this.state.filterText
83+
protected handleQueryChange = (
84+
query: string = this.state.searchOptions.query ?? ''
8485
): void => {
85-
this.setState({ filterText });
86-
this.search(filterText);
86+
const newSearchOptions = {
87+
...this.state.searchOptions,
88+
query,
89+
};
90+
this.setState({ searchOptions: newSearchOptions });
91+
this.search(newSearchOptions);
8792
};
8893

89-
protected search(query: string): void {
94+
protected search(searchOptions: S): void {
9095
const { searchable } = this.props;
9196
searchable
92-
.search({ query: query.trim() })
97+
.search(searchOptions)
9398
.then((items) => this.setState({ items: this.sort(items) }));
9499
}
95100

@@ -117,7 +122,7 @@ export class FilterableListContainer<
117122
` ${item.name}:${version}`,
118123
run: ({ progressId }) => install({ item, progressId, version }),
119124
});
120-
const items = await searchable.search({ query: this.state.filterText });
125+
const items = await searchable.search(this.state.searchOptions);
121126
this.setState({ items: this.sort(items) });
122127
}
123128

@@ -145,15 +150,18 @@ export class FilterableListContainer<
145150
}`,
146151
run: ({ progressId }) => uninstall({ item, progressId }),
147152
});
148-
const items = await searchable.search({ query: this.state.filterText });
153+
const items = await searchable.search(this.state.searchOptions);
149154
this.setState({ items: this.sort(items) });
150155
}
151156
}
152157

153158
export namespace FilterableListContainer {
154-
export interface Props<T extends ArduinoComponent> {
155-
readonly container: ListWidget<T>;
156-
readonly searchable: Searchable<T>;
159+
export interface Props<
160+
T extends ArduinoComponent,
161+
S extends Searchable.Options
162+
> {
163+
readonly container: ListWidget<T, S>;
164+
readonly searchable: Searchable<T, S>;
157165
readonly itemLabel: (item: T) => string;
158166
readonly itemDeprecated: (item: T) => boolean;
159167
readonly itemRenderer: ListItemRenderer<T>;
@@ -181,8 +189,8 @@ export namespace FilterableListContainer {
181189
readonly commandService: CommandService;
182190
}
183191

184-
export interface State<T> {
185-
filterText: string;
192+
export interface State<T, S extends Searchable.Options> {
193+
searchOptions: S;
186194
items: T[];
187195
}
188196
}

arduino-ide-extension/src/browser/widgets/component-list/list-widget-frontend-contribution.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser/fronten
33
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
44
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
55
import { ListWidget } from './list-widget';
6+
import { Searchable } from '../../../common/protocol';
67

78
@injectable()
8-
export abstract class ListWidgetFrontendContribution<T extends ArduinoComponent>
9-
extends AbstractViewContribution<ListWidget<T>>
9+
export abstract class ListWidgetFrontendContribution<
10+
T extends ArduinoComponent,
11+
S extends Searchable.Options
12+
>
13+
extends AbstractViewContribution<ListWidget<T, S>>
1014
implements FrontendApplicationContribution
1115
{
12-
async initializeLayout(): Promise<void> {}
16+
async initializeLayout(): Promise<void> {
17+
// TS requires at least one method from `FrontendApplicationContribution`.
18+
// Expected to be empty.
19+
}
1320

1421
override registerMenus(): void {
1522
// NOOP

arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx

+9-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import { NotificationCenter } from '../../notification-center';
2222

2323
@injectable()
2424
export abstract class ListWidget<
25-
T extends ArduinoComponent
25+
T extends ArduinoComponent,
26+
S extends Searchable.Options
2627
> extends ReactWidget {
2728
@inject(MessageService)
2829
protected readonly messageService: MessageService;
@@ -50,7 +51,7 @@ export abstract class ListWidget<
5051
*/
5152
protected firstActivate = true;
5253

53-
constructor(protected options: ListWidget.Options<T>) {
54+
constructor(protected options: ListWidget.Options<T, S>) {
5455
super();
5556
const { id, label, iconClass } = options;
5657
this.id = id;
@@ -129,7 +130,7 @@ export abstract class ListWidget<
129130

130131
render(): React.ReactNode {
131132
return (
132-
<FilterableListContainer<T>
133+
<FilterableListContainer<T, S>
133134
container={this}
134135
resolveFocus={this.onFocusResolved}
135136
searchable={this.options.searchable}
@@ -162,12 +163,15 @@ export abstract class ListWidget<
162163
}
163164

164165
export namespace ListWidget {
165-
export interface Options<T extends ArduinoComponent> {
166+
export interface Options<
167+
T extends ArduinoComponent,
168+
S extends Searchable.Options
169+
> {
166170
readonly id: string;
167171
readonly label: string;
168172
readonly iconClass: string;
169173
readonly installable: Installable<T>;
170-
readonly searchable: Searchable<T>;
174+
readonly searchable: Searchable<T, S>;
171175
readonly itemLabel: (item: T) => string;
172176
readonly itemDeprecated: (item: T) => boolean;
173177
readonly itemRenderer: ListItemRenderer<T>;

arduino-ide-extension/src/common/protocol/boards-service.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export const BoardsServicePath = '/services/boards-service';
131131
export const BoardsService = Symbol('BoardsService');
132132
export interface BoardsService
133133
extends Installable<BoardsPackage>,
134-
Searchable<BoardsPackage> {
134+
Searchable<BoardsPackage, BoardSearch> {
135135
getState(): Promise<AvailablePorts>;
136136
getBoardDetails(options: { fqbn: string }): Promise<BoardDetails | undefined>;
137137
getBoardPackage(options: { id: string }): Promise<BoardsPackage | undefined>;
@@ -145,6 +145,22 @@ export interface BoardsService
145145
}): Promise<BoardUserField[]>;
146146
}
147147

148+
export interface BoardSearch extends Searchable.Options {
149+
readonly type?: BoardSearch.Type;
150+
}
151+
export namespace BoardSearch {
152+
export const TypeLiterals = [
153+
'All',
154+
'Updatable',
155+
'Arduino',
156+
'Contributed',
157+
'Arduino Certified',
158+
'Partner',
159+
'Arduino@Heart',
160+
] as const;
161+
export type Type = typeof TypeLiterals[number];
162+
}
163+
148164
export interface Port {
149165
readonly address: string;
150166
readonly addressLabel: string;

arduino-ide-extension/src/common/protocol/library-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const LibraryServicePath = '/services/library-service';
66
export const LibraryService = Symbol('LibraryService');
77
export interface LibraryService
88
extends Installable<LibraryPackage>,
9-
Searchable<LibraryPackage> {
9+
Searchable<LibraryPackage, LibrarySearch> {
1010
list(options: LibraryService.List.Options): Promise<LibraryPackage[]>;
1111
search(options: LibrarySearch): Promise<LibraryPackage[]>;
1212
/**

arduino-ide-extension/src/common/protocol/searchable.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
export interface Searchable<T> {
2-
search(options: Searchable.Options): Promise<T[]>;
1+
export interface Searchable<T, O extends Searchable.Options> {
2+
search(options: O): Promise<T[]>;
33
}
44
export namespace Searchable {
55
export interface Options {

0 commit comments

Comments
 (0)