mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-06-04 03:06:32 +00:00
ATL-1054: Support for Add .ZIP LIbrary...
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
parent
86be874bb0
commit
e1b36c6c56
@ -142,6 +142,7 @@ import { AddFile } from './contributions/add-file';
|
||||
import { ArchiveSketch } from './contributions/archive-sketch';
|
||||
import { OutputToolbarContribution as TheiaOutputToolbarContribution } from '@theia/output/lib/browser/output-toolbar-contribution';
|
||||
import { OutputToolbarContribution } from './theia/output/output-toolbar-contribution';
|
||||
import { AddZipLibrary } from './contributions/add-zip-library';
|
||||
|
||||
const ElementQueries = require('css-element-queries/src/ElementQueries');
|
||||
|
||||
@ -354,6 +355,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
Contribution.configure(bind, Help);
|
||||
Contribution.configure(bind, AddFile);
|
||||
Contribution.configure(bind, ArchiveSketch);
|
||||
Contribution.configure(bind, AddZipLibrary);
|
||||
|
||||
bind(OutputServiceImpl).toSelf().inSingletonScope().onActivation(({ container }, outputService) => {
|
||||
WebSocketConnectionProvider.createProxy(container, OutputServicePath, outputService);
|
||||
|
@ -0,0 +1,73 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { remote } from 'electron';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { SketchContribution, Command, CommandRegistry, MenuModelRegistry } from './contribution';
|
||||
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { InstallationProgressDialog } from '../widgets/progress-dialog';
|
||||
import { LibraryService } from '../../common/protocol';
|
||||
|
||||
@injectable()
|
||||
export class AddZipLibrary extends SketchContribution {
|
||||
|
||||
@inject(EnvVariablesServer)
|
||||
protected readonly envVariableServer: EnvVariablesServer;
|
||||
|
||||
@inject(LibraryService)
|
||||
protected readonly libraryService: LibraryService;
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(AddZipLibrary.Commands.ADD_ZIP_LIBRARY, {
|
||||
execute: () => this.addZipLibrary()
|
||||
});
|
||||
}
|
||||
|
||||
registerMenus(registry: MenuModelRegistry): void {
|
||||
const includeLibMenuPath = [...ArduinoMenus.SKETCH__UTILS_GROUP, '0_include'];
|
||||
// TODO: do we need it? calling `registerSubmenu` multiple times is noop, so it does not hurt.
|
||||
registry.registerSubmenu(includeLibMenuPath, 'Include Library', { order: '1' });
|
||||
registry.registerMenuAction([...includeLibMenuPath, '1_install'], {
|
||||
commandId: AddZipLibrary.Commands.ADD_ZIP_LIBRARY.id,
|
||||
label: 'Add .ZIP Library...',
|
||||
order: '1'
|
||||
});
|
||||
}
|
||||
|
||||
async addZipLibrary(): Promise<void> {
|
||||
const homeUri = await this.envVariableServer.getHomeDirUri();
|
||||
const defaultPath = await this.fileService.fsPath(new URI(homeUri));
|
||||
const { canceled, filePaths } = await remote.dialog.showOpenDialog({
|
||||
title: "Select a zip file containing the library you'd like to add",
|
||||
defaultPath,
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
{
|
||||
name: 'Library',
|
||||
extensions: ['zip']
|
||||
}
|
||||
]
|
||||
});
|
||||
if (!canceled && filePaths.length) {
|
||||
const zipUri = await this.fileSystemExt.getUri(filePaths[0]);
|
||||
const dialog = new InstallationProgressDialog('Installing library', 'zip');
|
||||
try {
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
dialog.open();
|
||||
await this.libraryService.installZip({ zipUri });
|
||||
} catch (e) {
|
||||
this.messageService.error(e.toString());
|
||||
} finally {
|
||||
dialog.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace AddZipLibrary {
|
||||
export namespace Commands {
|
||||
export const ADD_ZIP_LIBRARY: Command = {
|
||||
id: 'arduino-add-zip-library'
|
||||
};
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
||||
import { open, OpenerService } from '@theia/core/lib/browser/opener-service';
|
||||
import { OutputChannelManager } from '@theia/output/lib/common/output-channel';
|
||||
import { MenuModelRegistry, MenuContribution } from '@theia/core/lib/common/menu';
|
||||
import { KeybindingRegistry, KeybindingContribution } from '@theia/core/lib/browser/keybinding';
|
||||
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
@ -90,6 +91,9 @@ export abstract class SketchContribution extends Contribution {
|
||||
@inject(EditorManager)
|
||||
protected readonly editorManager: EditorManager;
|
||||
|
||||
@inject(OutputChannelManager)
|
||||
protected readonly outputChannelManager: OutputChannelManager;
|
||||
|
||||
protected async sourceOverride(): Promise<Record<string, string>> {
|
||||
const override: Record<string, string> = {};
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
|
@ -47,6 +47,17 @@ export class IncludeLibrary extends SketchContribution {
|
||||
this.notificationCenter.onLibraryUninstalled(() => this.updateMenuActions());
|
||||
}
|
||||
|
||||
registerMenus(registry: MenuModelRegistry): void {
|
||||
// `Include Library` submenu
|
||||
const includeLibMenuPath = [...ArduinoMenus.SKETCH__UTILS_GROUP, '0_include'];
|
||||
registry.registerSubmenu(includeLibMenuPath, 'Include Library', { order: '1' });
|
||||
// `Manage Libraries...` group.
|
||||
registry.registerMenuAction([...includeLibMenuPath, '0_manage'], {
|
||||
commandId: `${LibraryListWidget.WIDGET_ID}:toggle`,
|
||||
label: 'Manage Libraries...'
|
||||
});
|
||||
}
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY, {
|
||||
execute: async arg => {
|
||||
@ -68,16 +79,7 @@ export class IncludeLibrary extends SketchContribution {
|
||||
libraries.push(...await this.libraryService.list({ fqbn }));
|
||||
}
|
||||
|
||||
// `Include Library` submenu
|
||||
const includeLibMenuPath = [...ArduinoMenus.SKETCH__UTILS_GROUP, '0_include'];
|
||||
this.menuRegistry.registerSubmenu(includeLibMenuPath, 'Include Library', { order: '1' });
|
||||
// `Manage Libraries...` group.
|
||||
this.menuRegistry.registerMenuAction([...includeLibMenuPath, '0_manage'], {
|
||||
commandId: `${LibraryListWidget.WIDGET_ID}:toggle`,
|
||||
label: 'Manage Libraries...'
|
||||
});
|
||||
this.toDispose.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction({ commandId: `${LibraryListWidget.WIDGET_ID}:toggle` })));
|
||||
|
||||
// `Add .ZIP Library...`
|
||||
// TODO: implement it
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { OutputChannelManager } from '@theia/output/lib/common/output-channel';
|
||||
import { CoreService } from '../../common/protocol';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||
@ -23,9 +22,6 @@ export class UploadSketch extends SketchContribution {
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
|
||||
@inject(OutputChannelManager)
|
||||
protected readonly outputChannelManager: OutputChannelManager;
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH, {
|
||||
execute: () => this.uploadSketch()
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { OutputChannelManager } from '@theia/output/lib/common/output-channel';
|
||||
import { CoreService } from '../../common/protocol';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||
@ -19,9 +18,6 @@ export class VerifySketch extends SketchContribution {
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
|
||||
@inject(OutputChannelManager)
|
||||
protected readonly outputChannelManager: OutputChannelManager;
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, {
|
||||
execute: () => this.verifySketch()
|
||||
|
@ -10,6 +10,7 @@ export interface LibraryService extends Installable<LibraryPackage>, Searchable<
|
||||
* When `installDependencies` is not set, it is `true` by default. If you want to skip the installation of required dependencies, set it to `false`.
|
||||
*/
|
||||
install(options: { item: LibraryPackage, version?: Installable.Version, installDependencies?: boolean }): Promise<void>;
|
||||
installZip(options: { zipUri: string }): Promise<void>;
|
||||
/**
|
||||
* Set `filterSelf` to `true` if you want to avoid having `item` in the result set.
|
||||
* Note: as of today (22.02.2021), the CLI works like this: `./arduino-cli lib deps Adaino@0.1.0 ✕ Adaino 0.1.0 must be installed.`.
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { injectable, inject } from 'inversify';
|
||||
import * as path from 'path';
|
||||
import { LibraryDependency, LibraryPackage, LibraryService } from '../common/protocol/library-service';
|
||||
import { CoreClientAware } from './core-client-provider';
|
||||
import {
|
||||
@ -13,13 +14,16 @@ import {
|
||||
LibraryUninstallReq,
|
||||
LibraryUninstallResp,
|
||||
Library,
|
||||
LibraryResolveDependenciesReq
|
||||
LibraryResolveDependenciesReq,
|
||||
ZipLibraryInstallReq,
|
||||
ZipLibraryInstallResp
|
||||
} from './cli-protocol/commands/lib_pb';
|
||||
import { Installable } from '../common/protocol/installable';
|
||||
import { ILogger, notEmpty } from '@theia/core';
|
||||
import { FileUri } from '@theia/core/lib/node';
|
||||
import { OutputService, NotificationServiceServer } from '../common/protocol';
|
||||
|
||||
|
||||
@injectable()
|
||||
export class LibraryServiceImpl extends CoreClientAware implements LibraryService {
|
||||
|
||||
@ -188,6 +192,37 @@ export class LibraryServiceImpl extends CoreClientAware implements LibraryServic
|
||||
console.info('<<< Library package installation done.', item);
|
||||
}
|
||||
|
||||
async installZip({ zipUri }: { zipUri: string }): Promise<void> {
|
||||
const coreClient = await this.coreClient();
|
||||
const { client, instance } = coreClient;
|
||||
const req = new ZipLibraryInstallReq();
|
||||
req.setPath(FileUri.fsPath(zipUri));
|
||||
req.setInstance(instance);
|
||||
const resp = client.zipLibraryInstall(req);
|
||||
resp.on('data', (r: ZipLibraryInstallResp) => {
|
||||
const task = r.getTaskProgress();
|
||||
if (task && task.getMessage()) {
|
||||
this.outputService.append({ chunk: task.getMessage() });
|
||||
}
|
||||
});
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
resp.on('end', resolve);
|
||||
resp.on('error', error => {
|
||||
// This is a hack to have better error messages for the user. We try to get the name of the library from this:
|
||||
// Request installZip failed with error: 2 UNKNOWN: copying library: destination /path/to/lib already exists
|
||||
const match = error.message.match(/destination (.*?) already exists/);
|
||||
if (match && match.length >= 2) {
|
||||
const name = path.basename(match[1].trim());
|
||||
if (name) {
|
||||
reject(new Error(`A library named ${name} already exists.`));
|
||||
return;
|
||||
}
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async uninstall(options: { item: LibraryPackage }): Promise<void> {
|
||||
const item = options.item;
|
||||
const coreClient = await this.coreClient();
|
||||
|
Loading…
x
Reference in New Issue
Block a user