1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

add confirm to internal install extension route

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2020-12-10 15:59:37 -05:00
parent dc6623ec65
commit 30f59655f0
3 changed files with 40 additions and 12 deletions

View File

@ -13,7 +13,7 @@ export async function installExtension(params: RouteParams): Promise<void> {
try {
navigate(extensionsURL());
await installFromNpm(name);
await installFromNpm(name, true);
} catch (error) {
logger.error("[PH - Install Extension]: failed to install from NPM", error);
}

View File

@ -30,6 +30,7 @@ interface InstallRequest {
fileName: string;
filePath?: string;
data?: Buffer;
confirmInstall?: boolean;
}
interface InstallRequestPreloaded extends InstallRequest {
@ -164,6 +165,10 @@ async function requestInstall(init: InstallRequest | InstallRequest[]) {
const folderExists = await fse.pathExists(extensionFolder);
if (!folderExists) {
if (install.confirmInstall && !(await confirmInstallExtension(install.manifest))) {
continue;
}
// auto-install extension if not yet exists
return unpackExtension(install);
} else {
@ -309,6 +314,20 @@ async function uninstallExtension(extension: InstalledExtension) {
}
}
function confirmInstallExtension({name, version}: LensExtensionManifest): Promise<boolean> {
const displayName = extensionDisplayName(name, version);
return new Promise(resolve => {
ConfirmDialog.open({
message: <p>Are you sure you want to install extension <b>{displayName}</b>?</p>,
labelOk: <Trans>Yes</Trans>,
labelCancel: <Trans>No</Trans>,
ok: () => resolve(true),
cancel: () => resolve(false),
});
});
}
function confirmUninstallExtension(extension: InstalledExtension) {
const displayName = extensionDisplayName(extension.manifest.name, extension.manifest.version);
@ -357,15 +376,15 @@ async function installFromSelectFileDialog() {
* Start extension install using a package name, which is resolved to a tarball url using the npm registry.
* @param packageName e.g. "@publisher/extension-name"
*/
export async function installFromNpm(packageName: string) {
export async function installFromNpm(packageName: string, confirm = false) {
const tarballUrl = await extensionLoader.getNpmPackageTarballUrl(packageName, "@hackweek");
Notifications.info(`Installing ${packageName}`);
return installFromUrlOrPath(tarballUrl);
return installFromUrlOrPath(tarballUrl, confirm);
}
async function installFromUrlOrPath(installPath: string) {
async function installFromUrlOrPath(installPath: string, confirmInstall = false) {
ExtensionStateStore.getInstance<ExtensionStateStore>().startingInstall = true;
const fileName = path.basename(installPath);
@ -376,11 +395,11 @@ async function installFromUrlOrPath(installPath: string) {
const { promise: filePromise } = downloadFile({ url: installPath, timeout: 60000 /*1m*/ });
const data = await filePromise;
await requestInstall({ fileName, data });
await requestInstall({ fileName, data, confirmInstall });
}
// otherwise installing from system path
else if (InputValidators.isPath.validate(installPath)) {
await requestInstall({ fileName, filePath: installPath });
await requestInstall({ fileName, filePath: installPath, confirmInstall });
}
} catch (error) {
ExtensionStateStore.getInstance<ExtensionStateStore>().startingInstall = false;

View File

@ -4,7 +4,7 @@ import React, { ReactNode } from "react";
import { observable } from "mobx";
import { observer } from "mobx-react";
import { Trans } from "@lingui/macro";
import { cssNames, noop, prevDefault } from "../../utils";
import { cssNames, prevDefault } from "../../utils";
import { Button, ButtonProps } from "../button";
import { Dialog, DialogProps } from "../dialog";
import { Icon } from "../icon";
@ -13,7 +13,8 @@ export interface ConfirmDialogProps extends Partial<DialogProps> {
}
export interface ConfirmDialogParams {
ok?: () => void;
ok?: () => void | Promise<void> | Promise<any>;
cancel?: () => void | Promise<void> | Promise<any>;
labelOk?: ReactNode;
labelCancel?: ReactNode;
message?: ReactNode;
@ -39,7 +40,6 @@ export class ConfirmDialog extends React.Component<ConfirmDialogProps> {
}
public defaultParams: ConfirmDialogParams = {
ok: noop,
labelOk: <Trans>Ok</Trans>,
labelCancel: <Trans>Cancel</Trans>,
icon: <Icon big material="warning"/>,
@ -52,18 +52,27 @@ export class ConfirmDialog extends React.Component<ConfirmDialogProps> {
ok = async () => {
try {
this.isSaving = true;
await Promise.resolve(this.params.ok()).catch(noop);
await this.params.ok?.();
} catch {
// ignore
} finally {
this.isSaving = false;
}
this.close();
ConfirmDialog.close();
};
onClose = () => {
this.isSaving = false;
};
close = () => {
close = async () => {
try {
await this.params.cancel?.();
} catch {
// ignore
} finally {
this.isSaving = false;
}
ConfirmDialog.close();
};