mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
reworks -- part 1
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
f505dab282
commit
78dcd5d18d
@ -97,6 +97,11 @@ export class ExtensionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNpmPackageTarballUrl(packageName: string) {
|
||||||
|
const command = [this.npmPath, "view", packageName, "dist.tarball", "--silent"];
|
||||||
|
return child_process.execSync(command.join(" "), { encoding: "utf8" });
|
||||||
|
}
|
||||||
|
|
||||||
protected installPackages(): Promise<void> {
|
protected installPackages(): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const child = child_process.fork(this.npmPath, ["install", "--silent", "--no-audit", "--only=prod", "--prefer-offline", "--no-package-lock"], {
|
const child = child_process.fork(this.npmPath, ["install", "--silent", "--no-audit", "--only=prod", "--prefer-offline", "--no-package-lock"], {
|
||||||
|
|||||||
@ -24,8 +24,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.install-extension {
|
.install-extension {
|
||||||
.Clipboard:hover code {
|
.Clipboard {
|
||||||
color: $textColorSecondary;
|
font-size: $font-size-small;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $textColorSecondary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import "./extensions.scss";
|
import "./extensions.scss";
|
||||||
import { remote, shell } from "electron";
|
import { remote, shell } from "electron";
|
||||||
|
import path from "path";
|
||||||
|
import fse from "fs-extra";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { computed, observable } from "mobx";
|
import { computed, observable } from "mobx";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
@ -13,10 +15,12 @@ import { PageLayout } from "../layout/page-layout";
|
|||||||
import { Clipboard } from "../clipboard";
|
import { Clipboard } from "../clipboard";
|
||||||
import { extensionLoader } from "../../../extensions/extension-loader";
|
import { extensionLoader } from "../../../extensions/extension-loader";
|
||||||
import { extensionManager } from "../../../extensions/extension-manager";
|
import { extensionManager } from "../../../extensions/extension-manager";
|
||||||
|
import { Notifications } from "../notifications";
|
||||||
|
import request from "request";
|
||||||
|
import logger from "../../../main/logger";
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class Extensions extends React.Component {
|
export class Extensions extends React.Component {
|
||||||
@observable.ref input: Input;
|
|
||||||
@observable search = "";
|
@observable search = "";
|
||||||
@observable downloadUrl = "";
|
@observable downloadUrl = "";
|
||||||
|
|
||||||
@ -41,34 +45,75 @@ export class Extensions extends React.Component {
|
|||||||
const { canceled, filePaths } = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow(), {
|
const { canceled, filePaths } = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow(), {
|
||||||
defaultPath: app.getPath("downloads"),
|
defaultPath: app.getPath("downloads"),
|
||||||
properties: ["openFile", "multiSelections"],
|
properties: ["openFile", "multiSelections"],
|
||||||
message: _i18n._(t`Select extensions to install (supported: ${supportedFormats.join(", ")}), `),
|
message: _i18n._(t`Select extensions to install (supported formats: ${supportedFormats.join(", ")}), `),
|
||||||
buttonLabel: _i18n._(t`Use configuration`),
|
buttonLabel: _i18n._(t`Use configuration`),
|
||||||
filters: [
|
filters: [
|
||||||
{ name: "tarball", extensions: supportedFormats }
|
{ name: "tarball", extensions: supportedFormats }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
if (!canceled && filePaths.length) {
|
if (!canceled && filePaths.length) {
|
||||||
this.installFromLocalPath(filePaths);
|
this.installFromSelectFileDialog(filePaths);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo
|
// fixme: doesn't work
|
||||||
installFromUrl = () => {
|
// todo: move to common/utils
|
||||||
if (!this.downloadUrl) {
|
async downloadFile(url: string, fileName = path.basename(url)): Promise<File> {
|
||||||
this.input?.focus();
|
return new Promise((resolve, reject) => {
|
||||||
|
const downloadingReq = request(url, { gzip: true });
|
||||||
|
downloadingReq.on("complete", (res, body: Buffer) => {
|
||||||
|
resolve(new File([body], fileName));
|
||||||
|
});
|
||||||
|
downloadingReq.on("error", reject);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
installFromUrl = async () => {
|
||||||
|
const { downloadUrl } = this;
|
||||||
|
if (!downloadUrl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('Install from URL', this.downloadUrl);
|
let tarballUrl: string;
|
||||||
|
if (InputValidators.isUrl.validate(downloadUrl)) {
|
||||||
|
tarballUrl = downloadUrl;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
tarballUrl = extensionManager.getNpmPackageTarballUrl(downloadUrl);
|
||||||
|
} catch (err) {
|
||||||
|
Notifications.error(`Error: npm package "${downloadUrl}" not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info('Install from packed extension URL', { tarballUrl });
|
||||||
|
if (tarballUrl) {
|
||||||
|
try {
|
||||||
|
const file = await this.downloadFile(tarballUrl);
|
||||||
|
this.installExtensionFromFile([file]);
|
||||||
|
} catch (err) {
|
||||||
|
Notifications.error(`Installing extension from ${tarballUrl} has failed: ${String(err)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo
|
installFromSelectFileDialog = async (filePaths: string[]) => {
|
||||||
installFromLocalPath = (filePaths: string[]) => {
|
logger.info('Install from select dialog', { filePaths });
|
||||||
console.log('Install select from dialog', filePaths)
|
const files: File[] = await Promise.all(
|
||||||
|
filePaths.map(filePath => {
|
||||||
|
const fileName = path.basename(filePath);
|
||||||
|
return fse.readFile(filePath).then(buffer => new File([buffer], fileName));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return this.installExtensionFromFile(files);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo
|
|
||||||
installOnDrop = (files: File[]) => {
|
installOnDrop = (files: File[]) => {
|
||||||
console.log('Install from D&D', files);
|
logger.info('Install from D&D', { files });
|
||||||
|
return this.installExtensionFromFile(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo
|
||||||
|
async installExtensionFromFile(files: File[]) {
|
||||||
|
console.log(`Install files:`, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderInfo() {
|
renderInfo() {
|
||||||
@ -80,31 +125,29 @@ export class Extensions extends React.Component {
|
|||||||
features of Lens are built as extensions and use the same Extension API.
|
features of Lens are built as extensions and use the same Extension API.
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p><em>All custom extensions located in:</em></p>
|
<p><em>Extensions loaded from:</em></p>
|
||||||
<div className="extensions-path flex inline" onClick={() => shell.openPath(this.extensionsPath)}>
|
<div className="extensions-path flex inline" onClick={() => shell.openPath(this.extensionsPath)}>
|
||||||
<Icon material="folder" tooltip={{ children: "Open folder", preferredPositions: "bottom" }}/>
|
<Icon material="folder" tooltip={{ children: "Open folder", preferredPositions: "bottom" }}/>
|
||||||
<code>{this.extensionsPath}</code>
|
<code>{this.extensionsPath}</code>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="install-extension flex column gaps">
|
<div className="install-extension flex column gaps">
|
||||||
<p><em>Install extensions from local file-system or URL:</em></p>
|
<p><em>Install extensions from archive (tarball.tgz):</em></p>
|
||||||
<div className="install-extension-by-url flex gaps align-center">
|
<div className="install-extension-by-url flex gaps align-center">
|
||||||
<Icon
|
|
||||||
material="get_app"
|
|
||||||
tooltip={{ children: "Download and Install", preferredPositions: "bottom" }}
|
|
||||||
interactive={this.downloadUrl.length > 0}
|
|
||||||
onClick={this.installFromUrl}
|
|
||||||
/>
|
|
||||||
<Input
|
<Input
|
||||||
showErrorsAsTooltip={true}
|
showErrorsAsTooltip={true}
|
||||||
className="box grow"
|
className="box grow"
|
||||||
theme="round-black"
|
theme="round-black"
|
||||||
placeholder="URL, e.g. https://registry.npmjs.org/%path-to-ext.tgz"
|
placeholder="URL or NPM package name"
|
||||||
validators={InputValidators.isUrl}
|
value={this.downloadUrl}
|
||||||
value={this.downloadUrl} // TODO: in addition we could support npm-package-name (if non-url value)?
|
|
||||||
onChange={v => this.downloadUrl = v}
|
onChange={v => this.downloadUrl = v}
|
||||||
onSubmit={this.installFromUrl}
|
onSubmit={this.installFromUrl}
|
||||||
ref={e => this.input = e}
|
/>
|
||||||
|
<Icon
|
||||||
|
material="get_app"
|
||||||
|
tooltip={{ children: "Install", preferredPositions: "bottom" }}
|
||||||
|
interactive={this.downloadUrl.length > 0}
|
||||||
|
onClick={this.installFromUrl}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@ -113,24 +156,13 @@ export class Extensions extends React.Component {
|
|||||||
onClick={this.selectLocalExtensionsDialog}
|
onClick={this.selectLocalExtensionsDialog}
|
||||||
/>
|
/>
|
||||||
<p className="hint">
|
<p className="hint">
|
||||||
<Trans><b>Pro-Tip 1</b>: you can download extension archive.tgz via NPM:</Trans>
|
<Trans><b>Pro-Tip 1</b>: you can download NPM-package to local folder with</Trans>
|
||||||
|
<Clipboard showNotification>
|
||||||
|
<code>npm pack %package-name</code>
|
||||||
|
</Clipboard>
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
|
||||||
<Clipboard showNotification cssSelectorLimit="code">
|
|
||||||
<li>
|
|
||||||
<code>npm pack %name</code>
|
|
||||||
<em> (click to copy)</em>
|
|
||||||
</li>
|
|
||||||
</Clipboard>
|
|
||||||
<Clipboard showNotification cssSelectorLimit="code">
|
|
||||||
<li>
|
|
||||||
<code>npm view %name dist.tarball</code>
|
|
||||||
<em> (click to copy)</em>
|
|
||||||
</li>
|
|
||||||
</Clipboard>
|
|
||||||
</ul>
|
|
||||||
<p className="hint">
|
<p className="hint">
|
||||||
<Trans><b>Pro-Tip 2</b>: you also can drop archive from file-system to this window to request installation</Trans>
|
<Trans><b>Pro-Tip 2</b>: you can drag & drop extension's tarball here to request installation</Trans>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="more-info flex inline gaps align-center">
|
<div className="more-info flex inline gaps align-center">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user