mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-23 03:06:40 +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 { ArchiveSketch } from './contributions/archive-sketch';
|
||||||
import { OutputToolbarContribution as TheiaOutputToolbarContribution } from '@theia/output/lib/browser/output-toolbar-contribution';
|
import { OutputToolbarContribution as TheiaOutputToolbarContribution } from '@theia/output/lib/browser/output-toolbar-contribution';
|
||||||
import { OutputToolbarContribution } from './theia/output/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');
|
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, Help);
|
||||||
Contribution.configure(bind, AddFile);
|
Contribution.configure(bind, AddFile);
|
||||||
Contribution.configure(bind, ArchiveSketch);
|
Contribution.configure(bind, ArchiveSketch);
|
||||||
|
Contribution.configure(bind, AddZipLibrary);
|
||||||
|
|
||||||
bind(OutputServiceImpl).toSelf().inSingletonScope().onActivation(({ container }, outputService) => {
|
bind(OutputServiceImpl).toSelf().inSingletonScope().onActivation(({ container }, outputService) => {
|
||||||
WebSocketConnectionProvider.createProxy(container, OutputServicePath, 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 { MessageService } from '@theia/core/lib/common/message-service';
|
||||||
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
||||||
import { open, OpenerService } from '@theia/core/lib/browser/opener-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 { MenuModelRegistry, MenuContribution } from '@theia/core/lib/common/menu';
|
||||||
import { KeybindingRegistry, KeybindingContribution } from '@theia/core/lib/browser/keybinding';
|
import { KeybindingRegistry, KeybindingContribution } from '@theia/core/lib/browser/keybinding';
|
||||||
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||||
@ -90,6 +91,9 @@ export abstract class SketchContribution extends Contribution {
|
|||||||
@inject(EditorManager)
|
@inject(EditorManager)
|
||||||
protected readonly editorManager: EditorManager;
|
protected readonly editorManager: EditorManager;
|
||||||
|
|
||||||
|
@inject(OutputChannelManager)
|
||||||
|
protected readonly outputChannelManager: OutputChannelManager;
|
||||||
|
|
||||||
protected async sourceOverride(): Promise<Record<string, string>> {
|
protected async sourceOverride(): Promise<Record<string, string>> {
|
||||||
const override: Record<string, string> = {};
|
const override: Record<string, string> = {};
|
||||||
const sketch = await this.sketchServiceClient.currentSketch();
|
const sketch = await this.sketchServiceClient.currentSketch();
|
||||||
|
@ -47,6 +47,17 @@ export class IncludeLibrary extends SketchContribution {
|
|||||||
this.notificationCenter.onLibraryUninstalled(() => this.updateMenuActions());
|
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 {
|
registerCommands(registry: CommandRegistry): void {
|
||||||
registry.registerCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY, {
|
registry.registerCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY, {
|
||||||
execute: async arg => {
|
execute: async arg => {
|
||||||
@ -68,16 +79,7 @@ export class IncludeLibrary extends SketchContribution {
|
|||||||
libraries.push(...await this.libraryService.list({ fqbn }));
|
libraries.push(...await this.libraryService.list({ fqbn }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Include Library` submenu
|
|
||||||
const includeLibMenuPath = [...ArduinoMenus.SKETCH__UTILS_GROUP, '0_include'];
|
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...`
|
// `Add .ZIP Library...`
|
||||||
// TODO: implement it
|
// TODO: implement it
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import { OutputChannelManager } from '@theia/output/lib/common/output-channel';
|
|
||||||
import { CoreService } from '../../common/protocol';
|
import { CoreService } from '../../common/protocol';
|
||||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||||
@ -23,9 +22,6 @@ export class UploadSketch extends SketchContribution {
|
|||||||
@inject(BoardsServiceProvider)
|
@inject(BoardsServiceProvider)
|
||||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||||
|
|
||||||
@inject(OutputChannelManager)
|
|
||||||
protected readonly outputChannelManager: OutputChannelManager;
|
|
||||||
|
|
||||||
registerCommands(registry: CommandRegistry): void {
|
registerCommands(registry: CommandRegistry): void {
|
||||||
registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH, {
|
registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH, {
|
||||||
execute: () => this.uploadSketch()
|
execute: () => this.uploadSketch()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import { OutputChannelManager } from '@theia/output/lib/common/output-channel';
|
|
||||||
import { CoreService } from '../../common/protocol';
|
import { CoreService } from '../../common/protocol';
|
||||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||||
@ -19,9 +18,6 @@ export class VerifySketch extends SketchContribution {
|
|||||||
@inject(BoardsServiceProvider)
|
@inject(BoardsServiceProvider)
|
||||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||||
|
|
||||||
@inject(OutputChannelManager)
|
|
||||||
protected readonly outputChannelManager: OutputChannelManager;
|
|
||||||
|
|
||||||
registerCommands(registry: CommandRegistry): void {
|
registerCommands(registry: CommandRegistry): void {
|
||||||
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, {
|
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, {
|
||||||
execute: () => this.verifySketch()
|
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`.
|
* 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>;
|
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.
|
* 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.`.
|
* 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 { injectable, inject } from 'inversify';
|
||||||
|
import * as path from 'path';
|
||||||
import { LibraryDependency, LibraryPackage, LibraryService } from '../common/protocol/library-service';
|
import { LibraryDependency, LibraryPackage, LibraryService } from '../common/protocol/library-service';
|
||||||
import { CoreClientAware } from './core-client-provider';
|
import { CoreClientAware } from './core-client-provider';
|
||||||
import {
|
import {
|
||||||
@ -13,13 +14,16 @@ import {
|
|||||||
LibraryUninstallReq,
|
LibraryUninstallReq,
|
||||||
LibraryUninstallResp,
|
LibraryUninstallResp,
|
||||||
Library,
|
Library,
|
||||||
LibraryResolveDependenciesReq
|
LibraryResolveDependenciesReq,
|
||||||
|
ZipLibraryInstallReq,
|
||||||
|
ZipLibraryInstallResp
|
||||||
} from './cli-protocol/commands/lib_pb';
|
} from './cli-protocol/commands/lib_pb';
|
||||||
import { Installable } from '../common/protocol/installable';
|
import { Installable } from '../common/protocol/installable';
|
||||||
import { ILogger, notEmpty } from '@theia/core';
|
import { ILogger, notEmpty } from '@theia/core';
|
||||||
import { FileUri } from '@theia/core/lib/node';
|
import { FileUri } from '@theia/core/lib/node';
|
||||||
import { OutputService, NotificationServiceServer } from '../common/protocol';
|
import { OutputService, NotificationServiceServer } from '../common/protocol';
|
||||||
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class LibraryServiceImpl extends CoreClientAware implements LibraryService {
|
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);
|
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> {
|
async uninstall(options: { item: LibraryPackage }): Promise<void> {
|
||||||
const item = options.item;
|
const item = options.item;
|
||||||
const coreClient = await this.coreClient();
|
const coreClient = await this.coreClient();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user