From f78a59c6cf0b592e24774777b38cb73d3c860543 Mon Sep 17 00:00:00 2001 From: Mark Sujew Date: Mon, 4 Apr 2022 12:49:26 +0200 Subject: [PATCH 1/2] Save all open editors before running `Save As` --- .../src/browser/contributions/save-as-sketch.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts index 0c265d0c2..c1696a6a1 100644 --- a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts @@ -1,4 +1,4 @@ -import { injectable } from 'inversify'; +import { inject, injectable } from 'inversify'; import * as remote from '@theia/core/electron-shared/@electron/remote'; import * as dateFormat from 'dateformat'; import { ArduinoMenus } from '../menu/arduino-menus'; @@ -11,9 +11,15 @@ import { KeybindingRegistry, } from './contribution'; import { nls } from '@theia/core/lib/common'; +import { ApplicationShell } from '@theia/core/lib/browser'; +import { timeout } from '@theia/core/lib/common/promise-util'; @injectable() export class SaveAsSketch extends SketchContribution { + + @inject(ApplicationShell) + protected readonly applicationShell: ApplicationShell; + registerCommands(registry: CommandRegistry): void { registry.registerCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH, { execute: (args) => this.saveAs(args), @@ -87,6 +93,8 @@ export class SaveAsSketch extends SketchContribution { if (!destinationUri) { return false; } + await this.applicationShell.saveAll(); + await timeout(20); const workspaceUri = await this.sketchService.copy(sketch, { destinationUri, }); From 6299e87015c745f7e1588e4b438df893d2c300de Mon Sep 17 00:00:00 2001 From: Mark Sujew Date: Wed, 20 Apr 2022 12:50:59 +0200 Subject: [PATCH 2/2] Only save unsaved changes to new sketch --- .../browser/contributions/save-as-sketch.ts | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts index c1696a6a1..7a683a58d 100644 --- a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts @@ -11,8 +11,9 @@ import { KeybindingRegistry, } from './contribution'; import { nls } from '@theia/core/lib/common'; -import { ApplicationShell } from '@theia/core/lib/browser'; -import { timeout } from '@theia/core/lib/common/promise-util'; +import { ApplicationShell, NavigatableWidget, Saveable } from '@theia/core/lib/browser'; +import { EditorManager } from '@theia/editor/lib/browser'; +import { WindowService } from '@theia/core/lib/browser/window/window-service'; @injectable() export class SaveAsSketch extends SketchContribution { @@ -20,6 +21,12 @@ export class SaveAsSketch extends SketchContribution { @inject(ApplicationShell) protected readonly applicationShell: ApplicationShell; + @inject(EditorManager) + protected readonly editorManager: EditorManager; + + @inject(WindowService) + protected readonly windowService: WindowService; + registerCommands(registry: CommandRegistry): void { registry.registerCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH, { execute: (args) => this.saveAs(args), @@ -93,11 +100,12 @@ export class SaveAsSketch extends SketchContribution { if (!destinationUri) { return false; } - await this.applicationShell.saveAll(); - await timeout(20); const workspaceUri = await this.sketchService.copy(sketch, { destinationUri, }); + if (workspaceUri) { + await this.saveOntoCopiedSketch(sketch.mainFileUri, sketch.uri, workspaceUri); + } if (workspaceUri && openAfterMove) { if (wipeOriginal || (openAfterMove && execOnlyIfTemp)) { try { @@ -108,12 +116,48 @@ export class SaveAsSketch extends SketchContribution { /* NOOP: from time to time, it's not possible to wipe the old resource from the temp dir on Windows */ } } + this.windowService.setSafeToShutDown(); this.workspaceService.open(new URI(workspaceUri), { preserveWindow: true, }); } return !!workspaceUri; } + + private async saveOntoCopiedSketch(mainFileUri: string, sketchUri: string, newSketchUri: string): Promise { + const widgets = this.applicationShell.widgets; + const snapshots = new Map(); + for (const widget of widgets) { + const saveable = Saveable.getDirty(widget); + const uri = NavigatableWidget.getUri(widget); + const uriString = uri?.toString(); + let relativePath: string; + if (uri && uriString!.includes(sketchUri) && saveable && saveable.createSnapshot) { + // The main file will change its name during the copy process + // We need to store the new name in the map + if (mainFileUri === uriString) { + const lastPart = new URI(newSketchUri).path.base + uri.path.ext; + relativePath = '/' + lastPart; + } else { + relativePath = uri.toString().substring(sketchUri.length); + } + snapshots.set(relativePath, saveable.createSnapshot()); + } + } + await Promise.all(Array.from(snapshots.entries()).map(async ([path, snapshot]) => { + const widgetUri = new URI(newSketchUri + path); + try { + const widget = await this.editorManager.getOrCreateByUri(widgetUri); + const saveable = Saveable.get(widget); + if (saveable && saveable.applySnapshot) { + saveable.applySnapshot(snapshot); + await saveable.save(); + } + } catch (e) { + console.error(e); + } + })); + } } export namespace SaveAsSketch {