11import { injectable } from '@theia/core/shared/inversify' ;
22import * as remote from '@theia/core/electron-shared/@electron/remote' ;
33import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor' ;
4+ import type { MaybePromise } from '@theia/core/lib/common/types' ;
5+ import type {
6+ FrontendApplication ,
7+ OnWillStopAction ,
8+ } from '@theia/core/lib/browser/frontend-application' ;
9+ import { nls } from '@theia/core/lib/common/nls' ;
10+ import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell' ;
411import { ArduinoMenus } from '../menu/arduino-menus' ;
512import {
613 SketchContribution ,
@@ -11,17 +18,21 @@ import {
1118 Sketch ,
1219 URI ,
1320} from './contribution' ;
14- import { nls } from '@theia/core/lib/common' ;
1521import { Dialog } from '@theia/core/lib/browser/dialogs' ;
1622import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl' ;
1723import { SaveAsSketch } from './save-as-sketch' ;
18- import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application' ;
1924
2025/**
2126 * Closes the `current` closeable editor, or any closeable current widget from the main area, or the current sketch window.
2227 */
2328@injectable ( )
2429export class Close extends SketchContribution {
30+ private shell : ApplicationShell | undefined ;
31+
32+ override onStart ( app : FrontendApplication ) : MaybePromise < void > {
33+ this . shell = app . shell ;
34+ }
35+
2536 override registerCommands ( registry : CommandRegistry ) : void {
2637 registry . registerCommand ( Close . Commands . CLOSE , {
2738 execute : ( ) => remote . getCurrentWindow ( ) . close ( ) ,
@@ -46,20 +57,41 @@ export class Close extends SketchContribution {
4657 // `FrontendApplicationContribution#onWillStop`
4758 onWillStop ( ) : OnWillStopAction {
4859 return {
49- reason : 'temp -sketch' ,
60+ reason : 'save -sketch' ,
5061 action : ( ) => {
51- return this . showSaveTempSketchDialog ( ) ;
62+ return this . showSaveSketchDialog ( ) ;
5263 } ,
5364 } ;
5465 }
5566
56- private async showSaveTempSketchDialog ( ) : Promise < boolean > {
57- const sketch = await this . sketchServiceClient . currentSketch ( ) ;
58- if ( ! CurrentSketch . isValid ( sketch ) ) {
59- return true ;
60- }
61- const isTemp = await this . sketchService . isTemp ( sketch ) ;
62- if ( ! isTemp ) {
67+ /**
68+ * If returns with `true`, IDE2 will close. Otherwise, it won't.
69+ */
70+ private async showSaveSketchDialog ( ) : Promise < boolean > {
71+ const sketch = await this . isCurrentSketchTemp ( ) ;
72+ if ( ! sketch ) {
73+ // Normal close workflow: if there are dirty editors prompt the user.
74+ if ( ! this . shell ) {
75+ console . error (
76+ `Could not get the application shell. Something went wrong.`
77+ ) ;
78+ return true ;
79+ }
80+ if ( this . shell . canSaveAll ( ) ) {
81+ const prompt = await this . prompt ( false ) ;
82+ switch ( prompt ) {
83+ case Prompt . DoNotSave :
84+ return true ;
85+ case Prompt . Cancel :
86+ return false ;
87+ case Prompt . Save : {
88+ await this . shell . saveAll ( ) ;
89+ return true ;
90+ }
91+ default :
92+ throw new Error ( `Unexpected prompt: ${ prompt } ` ) ;
93+ }
94+ }
6395 return true ;
6496 }
6597
@@ -71,11 +103,36 @@ export class Close extends SketchContribution {
71103 return true ;
72104 }
73105
74- const messageBoxResult = await remote . dialog . showMessageBox (
106+ const prompt = await this . prompt ( true ) ;
107+ switch ( prompt ) {
108+ case Prompt . DoNotSave :
109+ return true ;
110+ case Prompt . Cancel :
111+ return false ;
112+ case Prompt . Save : {
113+ // If `save as` was canceled by user, the result will be `undefined`, otherwise the new URI.
114+ const result = await this . commandService . executeCommand (
115+ SaveAsSketch . Commands . SAVE_AS_SKETCH . id ,
116+ {
117+ execOnlyIfTemp : false ,
118+ openAfterMove : false ,
119+ wipeOriginal : true ,
120+ markAsRecentlyOpened : true ,
121+ }
122+ ) ;
123+ return ! ! result ;
124+ }
125+ default :
126+ throw new Error ( `Unexpected prompt: ${ prompt } ` ) ;
127+ }
128+ }
129+
130+ private async prompt ( isTemp : boolean ) : Promise < Prompt > {
131+ const { response } = await remote . dialog . showMessageBox (
75132 remote . getCurrentWindow ( ) ,
76133 {
77134 message : nls . localize (
78- 'arduino/sketch/saveTempSketch ' ,
135+ 'arduino/sketch/saveSketch ' ,
79136 'Save your sketch to open it again later.'
80137 ) ,
81138 title : nls . localize (
@@ -84,24 +141,32 @@ export class Close extends SketchContribution {
84141 ) ,
85142 type : 'question' ,
86143 buttons : [
87- Dialog . CANCEL ,
88- nls . localizeByDefault ( 'Save As...' ) ,
89144 nls . localizeByDefault ( "Don't Save" ) ,
145+ Dialog . CANCEL ,
146+ nls . localizeByDefault ( isTemp ? 'Save As...' : 'Save' ) ,
90147 ] ,
148+ defaultId : 2 , // `Save`/`Save As...` button index is the default.
91149 }
92150 ) ;
93- const result = messageBoxResult . response ;
94- if ( result === 2 ) {
95- return true ;
96- } else if ( result === 1 ) {
97- return ! ! ( await this . commandService . executeCommand (
98- SaveAsSketch . Commands . SAVE_AS_SKETCH . id ,
99- {
100- execOnlyIfTemp : false ,
101- openAfterMove : false ,
102- wipeOriginal : true ,
103- }
104- ) ) ;
151+ switch ( response ) {
152+ case 0 :
153+ return Prompt . DoNotSave ;
154+ case 1 :
155+ return Prompt . Cancel ;
156+ case 2 :
157+ return Prompt . Save ;
158+ default :
159+ throw new Error ( `Unexpected response: ${ response } ` ) ;
160+ }
161+ }
162+
163+ private async isCurrentSketchTemp ( ) : Promise < false | Sketch > {
164+ const currentSketch = await this . sketchServiceClient . currentSketch ( ) ;
165+ if ( CurrentSketch . isValid ( currentSketch ) ) {
166+ const isTemp = await this . sketchService . isTemp ( currentSketch ) ;
167+ if ( isTemp ) {
168+ return currentSketch ;
169+ }
105170 }
106171 return false ;
107172 }
@@ -128,6 +193,12 @@ export class Close extends SketchContribution {
128193 }
129194}
130195
196+ enum Prompt {
197+ Save ,
198+ DoNotSave ,
199+ Cancel ,
200+ }
201+
131202export namespace Close {
132203 export namespace Commands {
133204 export const CLOSE : Command = {
0 commit comments