mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-10-06 01:58:32 +00:00

Closes #1879 Closes #1876 Closes #1899 Closes #1878 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
205 lines
6.4 KiB
TypeScript
205 lines
6.4 KiB
TypeScript
import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding';
|
|
import { CompositeTreeNode } from '@theia/core/lib/browser/tree';
|
|
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
|
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
|
|
import { Progress } from '@theia/core/lib/common/message-service-protocol';
|
|
import { nls } from '@theia/core/lib/common/nls';
|
|
import { injectable } from '@theia/core/shared/inversify';
|
|
import { CreateUri } from '../create/create-uri';
|
|
import { Create, isConflict } from '../create/typings';
|
|
import { ArduinoMenus } from '../menu/arduino-menus';
|
|
import {
|
|
TaskFactoryImpl,
|
|
WorkspaceInputDialogWithProgress,
|
|
} from '../theia/workspace/workspace-input-dialog';
|
|
import { CloudSketchbookTree } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree';
|
|
import { CloudSketchbookTreeModel } from '../widgets/cloud-sketchbook/cloud-sketchbook-tree-model';
|
|
import { SketchbookCommands } from '../widgets/sketchbook/sketchbook-commands';
|
|
import {
|
|
CloudSketchContribution,
|
|
pullingSketch,
|
|
sketchAlreadyExists,
|
|
synchronizingSketchbook,
|
|
} from './cloud-contribution';
|
|
import { Command, CommandRegistry, Sketch } from './contribution';
|
|
|
|
export interface CreateNewCloudSketchCallback {
|
|
(
|
|
newSketch: Create.Sketch,
|
|
newNode: CloudSketchbookTree.CloudSketchDirNode,
|
|
progress: Progress
|
|
): Promise<void>;
|
|
}
|
|
|
|
export interface NewCloudSketchParams {
|
|
/**
|
|
* Value to populate the dialog `<input>` when it opens.
|
|
*/
|
|
readonly initialValue?: string | undefined;
|
|
/**
|
|
* Additional callback to call when the new cloud sketch has been created.
|
|
*/
|
|
readonly callback?: CreateNewCloudSketchCallback;
|
|
/**
|
|
* If `true`, the validation error message will not be visible in the input dialog, but the `OK` button will be disabled. Defaults to `true`.
|
|
*/
|
|
readonly skipShowErrorMessageOnOpen?: boolean;
|
|
}
|
|
|
|
@injectable()
|
|
export class NewCloudSketch extends CloudSketchContribution {
|
|
private readonly toDispose = new DisposableCollection();
|
|
|
|
override onReady(): void {
|
|
this.toDispose.pushAll([
|
|
this.createFeatures.onDidChangeEnabled(() => this.menuManager.update()),
|
|
this.createFeatures.onDidChangeSession(() => this.menuManager.update()),
|
|
]);
|
|
if (this.createFeatures.session) {
|
|
this.menuManager.update();
|
|
}
|
|
}
|
|
|
|
onStop(): void {
|
|
this.toDispose.dispose();
|
|
}
|
|
|
|
override registerCommands(registry: CommandRegistry): void {
|
|
registry.registerCommand(NewCloudSketch.Commands.NEW_CLOUD_SKETCH, {
|
|
execute: (params: NewCloudSketchParams) =>
|
|
this.createNewSketch(
|
|
params?.skipShowErrorMessageOnOpen === false ? false : true,
|
|
params?.initialValue,
|
|
params?.callback
|
|
),
|
|
isEnabled: () => Boolean(this.createFeatures.session),
|
|
isVisible: () => this.createFeatures.enabled,
|
|
});
|
|
}
|
|
|
|
override registerMenus(registry: MenuModelRegistry): void {
|
|
registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, {
|
|
commandId: NewCloudSketch.Commands.NEW_CLOUD_SKETCH.id,
|
|
label: nls.localize('arduino/cloudSketch/new', 'New Cloud Sketch'),
|
|
order: '1',
|
|
});
|
|
}
|
|
|
|
override registerKeybindings(registry: KeybindingRegistry): void {
|
|
registry.registerKeybinding({
|
|
command: NewCloudSketch.Commands.NEW_CLOUD_SKETCH.id,
|
|
keybinding: 'CtrlCmd+Alt+N',
|
|
});
|
|
}
|
|
|
|
private async createNewSketch(
|
|
skipShowErrorMessageOnOpen: boolean,
|
|
initialValue?: string | undefined,
|
|
callback?: CreateNewCloudSketchCallback
|
|
): Promise<void> {
|
|
const treeModel = await this.treeModel();
|
|
if (treeModel) {
|
|
const rootNode = treeModel.root;
|
|
return this.openWizard(
|
|
rootNode,
|
|
treeModel,
|
|
skipShowErrorMessageOnOpen,
|
|
initialValue,
|
|
callback
|
|
);
|
|
}
|
|
}
|
|
|
|
private async openWizard(
|
|
rootNode: CompositeTreeNode,
|
|
treeModel: CloudSketchbookTreeModel,
|
|
skipShowErrorMessageOnOpen: boolean,
|
|
initialValue?: string | undefined,
|
|
callback?: CreateNewCloudSketchCallback
|
|
): Promise<void> {
|
|
const existingNames = rootNode.children
|
|
.filter(CloudSketchbookTree.CloudSketchDirNode.is)
|
|
.map(({ fileStat }) => fileStat.name);
|
|
const taskFactory = new TaskFactoryImpl((value) =>
|
|
this.createNewSketchWithProgress(treeModel, value, callback)
|
|
);
|
|
try {
|
|
const dialog = new WorkspaceInputDialogWithProgress(
|
|
{
|
|
title: nls.localize(
|
|
'arduino/newCloudSketch/newSketchTitle',
|
|
'Name of the new Cloud Sketch'
|
|
),
|
|
parentUri: CreateUri.root,
|
|
initialValue,
|
|
validate: (input) => {
|
|
if (existingNames.includes(input)) {
|
|
return sketchAlreadyExists(input);
|
|
}
|
|
return Sketch.validateCloudSketchFolderName(input) ?? '';
|
|
},
|
|
},
|
|
this.labelProvider,
|
|
taskFactory
|
|
);
|
|
await dialog.open(skipShowErrorMessageOnOpen);
|
|
if (dialog.taskResult) {
|
|
this.openInNewWindow(dialog.taskResult);
|
|
}
|
|
} catch (err) {
|
|
if (isConflict(err)) {
|
|
await treeModel.refresh();
|
|
return this.createNewSketch(
|
|
false,
|
|
taskFactory.value ?? initialValue,
|
|
callback
|
|
);
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
private createNewSketchWithProgress(
|
|
treeModel: CloudSketchbookTreeModel,
|
|
value: string,
|
|
callback?: CreateNewCloudSketchCallback
|
|
): (
|
|
progress: Progress
|
|
) => Promise<CloudSketchbookTree.CloudSketchDirNode | undefined> {
|
|
return async (progress: Progress) => {
|
|
progress.report({
|
|
message: nls.localize(
|
|
'arduino/cloudSketch/creating',
|
|
"Creating cloud sketch '{0}'...",
|
|
value
|
|
),
|
|
});
|
|
const sketch = await this.createApi.createSketch(value);
|
|
progress.report({ message: synchronizingSketchbook });
|
|
await treeModel.refresh();
|
|
progress.report({ message: pullingSketch(sketch.name) });
|
|
const node = await this.pull(sketch);
|
|
if (callback && node) {
|
|
await callback(sketch, node, progress);
|
|
}
|
|
return node;
|
|
};
|
|
}
|
|
|
|
private openInNewWindow(
|
|
node: CloudSketchbookTree.CloudSketchDirNode
|
|
): Promise<void> {
|
|
return this.commandService.executeCommand(
|
|
SketchbookCommands.OPEN_NEW_WINDOW.id,
|
|
{ node, treeWidgetId: 'cloud-sketchbook-composite-widget' }
|
|
);
|
|
}
|
|
}
|
|
export namespace NewCloudSketch {
|
|
export namespace Commands {
|
|
export const NEW_CLOUD_SKETCH: Command = {
|
|
id: 'arduino-new-cloud-sketch',
|
|
};
|
|
}
|
|
}
|