-
-
Notifications
You must be signed in to change notification settings - Fork 435
/
Copy pathdelete-sketch.ts
168 lines (160 loc) · 6.03 KB
/
delete-sketch.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import * as remote from '@theia/core/electron-shared/@electron/remote';
import { ipcRenderer } from '@theia/core/electron-shared/electron';
import { Dialog } from '@theia/core/lib/browser/dialogs';
import { NavigatableWidget } from '@theia/core/lib/browser/navigatable-types';
import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
import { WindowService } from '@theia/core/lib/browser/window/window-service';
import { nls } from '@theia/core/lib/common/nls';
import type { MaybeArray } from '@theia/core/lib/common/types';
import URI from '@theia/core/lib/common/uri';
import type { Widget } from '@theia/core/shared/@phosphor/widgets';
import { inject, injectable } from '@theia/core/shared/inversify';
import { SketchesError } from '../../common/protocol';
import { SCHEDULE_DELETION_SIGNAL } from '../../electron-common/electron-messages';
import { Sketch } from '../contributions/contribution';
import { isNotFound } from '../create/typings';
import { Command, CommandRegistry } from './contribution';
import { CloudSketchContribution } from './cloud-contribution';
export interface DeleteSketchParams {
/**
* Either the URI of the sketch folder or the sketch to delete.
*/
readonly toDelete: string | Sketch;
/**
* If `true`, the currently opened sketch is expected to be deleted.
* Hence, the editors must be closed, the sketch will be scheduled
* for deletion, and the browser window will close or navigate away.
* If `false`, the sketch will be scheduled for deletion,
* but the current window remains open. If `force`, the window will
* navigate away, but IDE2 won't open any confirmation dialogs.
*/
readonly willNavigateAway?: boolean | 'force';
}
@injectable()
export class DeleteSketch extends CloudSketchContribution {
@inject(ApplicationShell)
private readonly shell: ApplicationShell;
@inject(WindowService)
private readonly windowService: WindowService;
override registerCommands(registry: CommandRegistry): void {
registry.registerCommand(DeleteSketch.Commands.DELETE_SKETCH, {
execute: (params: DeleteSketchParams) => this.deleteSketch(params),
});
}
private async deleteSketch(params: DeleteSketchParams): Promise<void> {
const { toDelete, willNavigateAway } = params;
let sketch: Sketch;
if (typeof toDelete === 'string') {
const resolvedSketch = await this.loadSketch(toDelete);
if (!resolvedSketch) {
console.info(
`Failed to load the sketch. It was not found at '${toDelete}'. Skipping deletion.`
);
return;
}
sketch = resolvedSketch;
} else {
sketch = toDelete;
}
if (!willNavigateAway) {
this.scheduleDeletion(sketch);
return;
}
const cloudUri = this.createFeatures.cloudUri(sketch);
if (willNavigateAway !== 'force') {
const { response } = await remote.dialog.showMessageBox({
title: nls.localizeByDefault('Delete'),
type: 'question',
buttons: [Dialog.CANCEL, Dialog.OK],
message: cloudUri
? nls.localize(
'theia/workspace/deleteCloudSketch',
"The cloud sketch '{0}' will be permanently deleted from the Arduino servers and the local caches. This action is irreversible. Do you want to delete the current sketch?",
sketch.name
)
: nls.localize(
'theia/workspace/deleteCurrentSketch',
"The sketch '{0}' will be permanently deleted. This action is irreversible. Do you want to delete the current sketch?",
sketch.name
),
});
// cancel
if (response === 0) {
return;
}
}
if (cloudUri) {
const posixPath = cloudUri.path.toString();
const cloudSketch = this.createApi.sketchCache.getSketch(posixPath);
if (!cloudSketch) {
throw new Error(
`Cloud sketch with path '${posixPath}' was not cached. Cache: ${this.createApi.sketchCache.toString()}`
);
}
try {
// IDE2 cannot use DELETE directory as the server responses with HTTP 500 if it's missing.
// https://github.com/arduino/arduino-ide/issues/1825#issuecomment-1406301406
await this.createApi.deleteSketch(cloudSketch.path);
} catch (err) {
if (!isNotFound(err)) {
throw err;
} else {
console.info(
`Could not delete the cloud sketch with path '${posixPath}'. It does not exist.`
);
}
}
}
await Promise.all([
...Sketch.uris(sketch).map((uri) =>
this.closeWithoutSaving(new URI(uri))
),
]);
this.windowService.setSafeToShutDown();
this.scheduleDeletion(sketch);
return window.close();
}
private scheduleDeletion(sketch: Sketch): void {
ipcRenderer.send(SCHEDULE_DELETION_SIGNAL, sketch);
}
private async loadSketch(uri: string): Promise<Sketch | undefined> {
try {
const sketch = await this.sketchesService.loadSketch(uri);
return sketch;
} catch (err) {
if (SketchesError.NotFound.is(err)) {
return undefined;
}
throw err;
}
}
// fix: https://github.com/eclipse-theia/theia/issues/12107
private async closeWithoutSaving(uri: URI): Promise<void> {
const affected = getAffected(this.shell.widgets, uri);
const toClose = [...affected].map(([, widget]) => widget);
await this.shell.closeMany(toClose, { save: false });
}
}
export namespace DeleteSketch {
export namespace Commands {
export const DELETE_SKETCH: Command = {
id: 'arduino-delete-sketch',
};
}
}
function getAffected<T extends Widget>(
widgets: Iterable<T>,
context: MaybeArray<URI>
): [URI, T & NavigatableWidget][] {
const uris = Array.isArray(context) ? context : [context];
const result: [URI, T & NavigatableWidget][] = [];
for (const widget of widgets) {
if (NavigatableWidget.is(widget)) {
const resourceUri = widget.getResourceUri();
if (resourceUri && uris.some((uri) => uri.isEqualOrParent(resourceUri))) {
result.push([resourceUri, widget]);
}
}
}
return result;
}