Skip to content

Commit 8ca1b94

Browse files
author
Akos Kitta
committed
init
Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent f3d3d40 commit 8ca1b94

File tree

15 files changed

+309
-295
lines changed

15 files changed

+309
-295
lines changed

arduino-ide-extension/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
"@types/p-queue": "^2.3.1",
5959
"@types/ps-tree": "^1.1.0",
6060
"@types/react-tabs": "^2.3.2",
61-
"@types/react-virtualized": "^9.21.21",
6261
"@types/temp": "^0.8.34",
6362
"@types/which": "^1.3.1",
6463
"@vscode/debugprotocol": "^1.51.0",
@@ -95,7 +94,6 @@
9594
"react-perfect-scrollbar": "^1.5.8",
9695
"react-select": "^5.6.0",
9796
"react-tabs": "^3.1.2",
98-
"react-virtualized": "^9.22.3",
9997
"react-window": "^1.8.6",
10098
"semver": "^7.3.2",
10199
"string-natural-compare": "^2.0.3",

arduino-ide-extension/src/browser/boards/boards-auto-installer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ export class BoardsAutoInstaller implements FrontendApplicationContribution {
174174
// CLI returns the packages already sorted with the deprecated ones at the end of the list
175175
// in order to ensure the new ones are preferred
176176
const candidates = packagesForBoard.filter(
177-
({ installable, installedVersion }) => installable && !installedVersion
177+
({ installedVersion }) => !installedVersion
178178
);
179179

180180
return candidates[0];

arduino-ide-extension/src/browser/style/index.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,6 @@ button.theia-button.message-box-dialog-button {
154154
font-size: 14px;
155155
}
156156

157-
.uppercase {
158-
text-transform: uppercase;
159-
}
160-
161157
/* High Contrast Theme rules */
162158
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
163159
.hc-black.hc-theia.theia-hc button.theia-button:hover,

arduino-ide-extension/src/browser/style/list-widget.css

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,7 @@
118118
background-color: var(--theia-button-foreground);
119119
color: var(--theia-button-background);
120120
content: attr(uninstall);
121-
}
122-
123-
.component-list-item[min-width~="170px"] .footer {
124-
padding: 5px 5px 0px 0px;
125-
min-height: 35px;
126-
display: flex;
127-
flex-direction: row-reverse;
121+
text-transform: uppercase;
128122
}
129123

130124
.component-list-item .footer {
@@ -155,7 +149,7 @@
155149
/* TODO: Remove it when the Theia version is upgraded to 1.27.0 and use Theia APIs to implement it*/
156150
.hc-black.hc-theia.theia-hc .component-list-item .header .installed:hover:before {
157151
background-color: transparent;
158-
outline: 1px dashed var(--theia-focusBorder);
152+
outline: 1px dashed var(--theia-focusBorder);
159153
}
160154

161155
.hc-black.hc-theia.theia-hc .component-list-item .header .installed:before {

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

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,9 @@ export class ComponentListItem<
88
> extends React.Component<ComponentListItem.Props<T>, ComponentListItem.State> {
99
constructor(props: ComponentListItem.Props<T>) {
1010
super(props);
11-
if (props.item.installable) {
12-
const version = props.item.availableVersions.filter(
13-
(version) => version !== props.item.installedVersion
14-
)[0];
15-
this.state = {
16-
selectedVersion: version,
17-
};
18-
}
11+
this.state = {
12+
selectedVersion: Installable.latest(props.item.availableVersions),
13+
};
1914
}
2015

2116
override render(): React.ReactNode {
@@ -33,24 +28,21 @@ export class ComponentListItem<
3328
}
3429

3530
private async install(item: T): Promise<void> {
36-
const toInstall = this.state.selectedVersion;
37-
const version = this.props.item.availableVersions.filter(
38-
(version) => version !== this.state.selectedVersion
39-
)[0];
40-
this.setState({
41-
selectedVersion: version,
42-
});
31+
this.setState({ state: 'uninstalling' });
4332
try {
44-
await this.props.install(item, toInstall);
45-
} catch {
46-
this.setState({
47-
selectedVersion: toInstall,
48-
});
33+
await this.props.install(item, this.state.selectedVersion);
34+
} finally {
35+
this.setState({ state: undefined });
4936
}
5037
}
5138

5239
private async uninstall(item: T): Promise<void> {
53-
await this.props.uninstall(item);
40+
this.setState({ state: 'uninstalling' });
41+
try {
42+
await this.props.uninstall(item);
43+
} finally {
44+
this.setState({ state: undefined });
45+
}
5446
}
5547

5648
private onVersionChange(version: Installable.Version): void {
@@ -68,5 +60,6 @@ export namespace ComponentListItem {
6860

6961
export interface State {
7062
selectedVersion?: Installable.Version;
63+
state?: 'installing' | 'uninstalling' | undefined;
7164
}
7265
}

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

Lines changed: 13 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,29 @@
1-
import 'react-virtualized/styles.css';
21
import * as React from '@theia/core/shared/react';
3-
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
4-
import {
5-
CellMeasurer,
6-
CellMeasurerCache,
7-
} from 'react-virtualized/dist/commonjs/CellMeasurer';
8-
import type {
9-
ListRowProps,
10-
ListRowRenderer,
11-
} from 'react-virtualized/dist/commonjs/List';
12-
import List from 'react-virtualized/dist/commonjs/List';
2+
import { ItemContent, Virtuoso } from '@theia/core/shared/react-virtuoso';
133
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
144
import { Installable } from '../../../common/protocol/installable';
155
import { ComponentListItem } from './component-list-item';
166
import { ListItemRenderer } from './list-item-renderer';
177

18-
function sameAs<T>(
19-
left: T[],
20-
right: T[],
21-
...compareProps: (keyof T)[]
22-
): boolean {
23-
if (left === right) {
24-
return true;
25-
}
26-
const leftLength = left.length;
27-
if (leftLength !== right.length) {
28-
return false;
29-
}
30-
for (let i = 0; i < leftLength; i++) {
31-
for (const prop of compareProps) {
32-
const leftValue = left[i][prop];
33-
const rightValue = right[i][prop];
34-
if (leftValue !== rightValue) {
35-
return false;
36-
}
37-
}
38-
}
39-
return true;
40-
}
41-
428
export class ComponentList<T extends ArduinoComponent> extends React.Component<
439
ComponentList.Props<T>
4410
> {
45-
private readonly cache: CellMeasurerCache;
46-
private resizeAllFlag: boolean;
47-
private list: List | undefined;
48-
private mostRecentWidth: number | undefined;
49-
50-
constructor(props: ComponentList.Props<T>) {
51-
super(props);
52-
this.cache = new CellMeasurerCache({
53-
defaultHeight: 140,
54-
fixedWidth: true,
55-
});
56-
}
57-
5811
override render(): React.ReactNode {
59-
return (
60-
<AutoSizer>
61-
{({ width, height }) => {
62-
if (this.mostRecentWidth && this.mostRecentWidth !== width) {
63-
this.resizeAllFlag = true;
64-
setTimeout(() => this.clearAll(), 0);
65-
}
66-
this.mostRecentWidth = width;
67-
return (
68-
<List
69-
className={'items-container'}
70-
rowRenderer={this.createItem}
71-
height={height}
72-
width={width}
73-
rowCount={this.props.items.length}
74-
rowHeight={this.cache.rowHeight}
75-
deferredMeasurementCache={this.cache}
76-
ref={this.setListRef}
77-
estimatedRowSize={140}
78-
// If default value, then `react-virtualized` will optimize and list item will not receive a `:hover` event.
79-
// Hence, install and version `<select>` won't be visible even if the mouse cursor is over the `<div>`.
80-
// See https://github.com/bvaughn/react-virtualized/blob/005be24a608add0344284053dae7633be86053b2/source/Grid/Grid.js#L38-L42
81-
scrollingResetTimeInterval={0}
82-
/>
83-
);
84-
}}
85-
</AutoSizer>
86-
);
87-
}
88-
89-
override componentDidUpdate(prevProps: ComponentList.Props<T>): void {
90-
if (
91-
this.resizeAllFlag ||
92-
!sameAs(this.props.items, prevProps.items, 'name', 'installedVersion')
93-
) {
94-
this.clearAll(true);
95-
}
96-
}
97-
98-
private readonly setListRef = (ref: List | null): void => {
99-
this.list = ref || undefined;
100-
};
101-
102-
private clearAll(scrollToTop = false): void {
103-
this.resizeAllFlag = false;
104-
this.cache.clearAll();
105-
if (this.list) {
106-
this.list.recomputeRowHeights();
107-
if (scrollToTop) {
108-
this.list.scrollToPosition(0);
109-
}
110-
}
12+
return <Virtuoso data={this.props.items} itemContent={this.itemContent} />;
11113
}
11214

113-
private readonly createItem: ListRowRenderer = ({
114-
index,
115-
parent,
116-
key,
117-
style,
118-
}: ListRowProps): React.ReactNode => {
119-
const item = this.props.items[index];
15+
private readonly itemContent: ItemContent<T, unknown> = (
16+
index: number,
17+
item: T
18+
) => {
12019
return (
121-
<CellMeasurer
122-
cache={this.cache}
123-
columnIndex={0}
124-
key={key}
125-
rowIndex={index}
126-
parent={parent}
127-
>
128-
{({ registerChild }) => (
129-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
130-
// @ts-ignore
131-
<div ref={registerChild} style={style}>
132-
<ComponentListItem<T>
133-
key={this.props.itemLabel(item)}
134-
item={item}
135-
itemRenderer={this.props.itemRenderer}
136-
install={this.props.install}
137-
uninstall={this.props.uninstall}
138-
/>
139-
</div>
140-
)}
141-
</CellMeasurer>
20+
<ComponentListItem<T>
21+
key={this.props.itemLabel(item)}
22+
item={item}
23+
itemRenderer={this.props.itemRenderer}
24+
install={this.props.install}
25+
uninstall={this.props.uninstall}
26+
/>
14227
);
14328
};
14429
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Installable } from '../../../common/protocol';
2+
3+
export const ItemActionLiterals = [
4+
'installLatest',
5+
'installSelected',
6+
'update',
7+
'remove',
8+
'unknown',
9+
] as const;
10+
export type ItemActionType = typeof ItemActionLiterals[number];
11+
12+
export function itemAction(params: {
13+
installed?: Installable.Version | undefined;
14+
available: Installable.Version[];
15+
selected?: Installable.Version;
16+
}): ItemActionType {
17+
const { installed, available } = params;
18+
const latest = Installable.latest(available);
19+
if (!latest || (installed && !available.includes(installed))) {
20+
return 'unknown';
21+
}
22+
const selected = params.selected ?? latest;
23+
if (installed === selected) {
24+
return 'remove';
25+
}
26+
if (installed) {
27+
return selected === latest && installed !== latest
28+
? 'update'
29+
: 'installSelected';
30+
} else {
31+
return selected === latest ? 'installLatest' : 'installSelected';
32+
}
33+
}

0 commit comments

Comments
 (0)