-
-
Notifications
You must be signed in to change notification settings - Fork 435
/
Copy pathcomponent-list-item.tsx
96 lines (87 loc) · 2.81 KB
/
component-list-item.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import React from '@theia/core/shared/react';
import type { ArduinoComponent } from '../../../common/protocol/arduino-component';
import { Installable } from '../../../common/protocol/installable';
import type { ListItemRenderer } from './list-item-renderer';
import { UserAbortError } from '../../../common/protocol/progressible';
export class ComponentListItem<
T extends ArduinoComponent
> extends React.Component<ComponentListItem.Props<T>, ComponentListItem.State> {
constructor(props: ComponentListItem.Props<T>) {
super(props);
this.state = {};
}
override render(): React.ReactNode {
const { item, itemRenderer } = this.props;
const selectedVersion =
this.props.edited?.item.name === item.name
? this.props.edited.selectedVersion
: this.latestVersion;
return (
<>
{itemRenderer.renderItem({
item,
selectedVersion,
inProgress: this.state.inProgress,
install: (item) => this.install(item),
uninstall: (item) => this.uninstall(item),
onVersionChange: (version) => this.onVersionChange(version),
})}
</>
);
}
private async install(item: T): Promise<void> {
await this.withState('installing', () =>
this.props.install(
item,
this.props.edited?.item.name === item.name
? this.props.edited.selectedVersion
: Installable.latest(this.props.item.availableVersions)
)
);
}
private async uninstall(item: T): Promise<void> {
await this.withState('uninstalling', () => this.props.uninstall(item));
}
private async withState(
inProgress: 'installing' | 'uninstalling',
task: () => Promise<unknown>
): Promise<void> {
this.setState({ inProgress });
try {
await task();
} catch (err) {
if (err instanceof UserAbortError) {
// No state update when user cancels the task
return;
}
throw err;
} finally {
this.setState({ inProgress: undefined });
}
}
private onVersionChange(version: Installable.Version): void {
this.props.onItemEdit(this.props.item, version);
}
private get latestVersion(): Installable.Version | undefined {
return Installable.latest(this.props.item.availableVersions);
}
}
export namespace ComponentListItem {
export interface Props<T extends ArduinoComponent> {
readonly item: T;
readonly install: (item: T, version?: Installable.Version) => Promise<void>;
readonly uninstall: (item: T) => Promise<void>;
readonly edited?: {
item: T;
selectedVersion: Installable.Version;
};
readonly onItemEdit: (
item: T,
selectedVersion: Installable.Version
) => void;
readonly itemRenderer: ListItemRenderer<T>;
}
export interface State {
inProgress?: 'installing' | 'uninstalling' | undefined;
}
}