in desktop/flipper-ui-core/src/chrome/plugin-manager/PluginInstaller.tsx [126:239]
function InstallButton(props: {
name: string;
version: string;
onInstall: () => void;
updateStatus: UpdateResult;
}) {
type InstallAction =
| {kind: 'Install'; error?: string}
| {kind: 'Waiting'}
| {kind: 'Remove'; error?: string}
| {kind: 'Update'; error?: string};
const catchError =
(actionKind: 'Install' | 'Remove' | 'Update', fn: () => Promise<void>) =>
async () => {
try {
await fn();
} catch (err) {
console.error(
`Installation process of kind ${actionKind} failed with:`,
err,
);
setAction({kind: actionKind, error: err.toString()});
}
};
const mkInstallCallback = (action: 'Install' | 'Update') =>
catchError(action, async () => {
reportUsage(
action === 'Install' ? `${TAG}:install` : `${TAG}:update`,
undefined,
props.name,
);
setAction({kind: 'Waiting'});
await installPluginFromNpm(props.name);
props.onInstall();
setAction({kind: 'Remove'});
});
const performInstall = useCallback(mkInstallCallback('Install'), [
props.name,
props.version,
]);
const performUpdate = useCallback(mkInstallCallback('Update'), [
props.name,
props.version,
]);
const performRemove = useCallback(
catchError('Remove', async () => {
reportUsage(`${TAG}:remove`, undefined, props.name);
setAction({kind: 'Waiting'});
await removePlugin(props.name);
props.onInstall();
setAction({kind: 'Install'});
}),
[props.name],
);
const [action, setAction] = useState<InstallAction>(
props.updateStatus.kind === 'update-available'
? {kind: 'Update'}
: props.updateStatus.kind === 'not-installed'
? {kind: 'Install'}
: {kind: 'Remove'},
);
if (action.kind === 'Waiting') {
return <LoadingIndicator size={16} />;
}
if ((action.kind === 'Install' || action.kind === 'Remove') && action.error) {
}
const button = (
<Button
size="small"
type={action.kind !== 'Remove' ? 'primary' : undefined}
onClick={() => {
switch (action.kind) {
case 'Install':
reportPlatformFailures(performInstall(), `${TAG}:install`);
break;
case 'Remove':
reportPlatformFailures(performRemove(), `${TAG}:remove`);
break;
case 'Update':
reportPlatformFailures(performUpdate(), `${TAG}:update`);
break;
}
}}>
{action.kind}
</Button>
);
if (action.error) {
const glyph = (
<Glyph color={theme.warningColor} size={16} name="caution-triangle" />
);
return (
<Layout.Horizontal gap>
<Tooltip
placement="leftBottom"
title={`Something went wrong: ${action.error}`}
children={glyph}
/>
{button}
</Layout.Horizontal>
);
} else {
return button;
}
}