1
1
import { injectable } from '@theia/core/shared/inversify' ;
2
2
import * as remote from '@theia/core/electron-shared/@electron/remote' ;
3
3
import { 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' ;
4
11
import { ArduinoMenus } from '../menu/arduino-menus' ;
5
12
import {
6
13
SketchContribution ,
@@ -11,17 +18,21 @@ import {
11
18
Sketch ,
12
19
URI ,
13
20
} from './contribution' ;
14
- import { nls } from '@theia/core/lib/common' ;
15
21
import { Dialog } from '@theia/core/lib/browser/dialogs' ;
16
22
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl' ;
17
23
import { SaveAsSketch } from './save-as-sketch' ;
18
- import type { OnWillStopAction } from '@theia/core/lib/browser/frontend-application' ;
19
24
20
25
/**
21
26
* Closes the `current` closeable editor, or any closeable current widget from the main area, or the current sketch window.
22
27
*/
23
28
@injectable ( )
24
29
export class Close extends SketchContribution {
30
+ private shell : ApplicationShell | undefined ;
31
+
32
+ override onStart ( app : FrontendApplication ) : MaybePromise < void > {
33
+ this . shell = app . shell ;
34
+ }
35
+
25
36
override registerCommands ( registry : CommandRegistry ) : void {
26
37
registry . registerCommand ( Close . Commands . CLOSE , {
27
38
execute : ( ) => remote . getCurrentWindow ( ) . close ( ) ,
@@ -46,20 +57,41 @@ export class Close extends SketchContribution {
46
57
// `FrontendApplicationContribution#onWillStop`
47
58
onWillStop ( ) : OnWillStopAction {
48
59
return {
49
- reason : 'temp -sketch' ,
60
+ reason : 'save -sketch' ,
50
61
action : ( ) => {
51
- return this . showSaveTempSketchDialog ( ) ;
62
+ return this . showSaveSketchDialog ( ) ;
52
63
} ,
53
64
} ;
54
65
}
55
66
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
+ }
63
95
return true ;
64
96
}
65
97
@@ -71,11 +103,36 @@ export class Close extends SketchContribution {
71
103
return true ;
72
104
}
73
105
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 (
75
132
remote . getCurrentWindow ( ) ,
76
133
{
77
134
message : nls . localize (
78
- 'arduino/sketch/saveTempSketch ' ,
135
+ 'arduino/sketch/saveSketch ' ,
79
136
'Save your sketch to open it again later.'
80
137
) ,
81
138
title : nls . localize (
@@ -84,24 +141,32 @@ export class Close extends SketchContribution {
84
141
) ,
85
142
type : 'question' ,
86
143
buttons : [
87
- Dialog . CANCEL ,
88
- nls . localizeByDefault ( 'Save As...' ) ,
89
144
nls . localizeByDefault ( "Don't Save" ) ,
145
+ Dialog . CANCEL ,
146
+ nls . localizeByDefault ( isTemp ? 'Save As...' : 'Save' ) ,
90
147
] ,
148
+ defaultId : 2 , // `Save`/`Save As...` button index is the default.
91
149
}
92
150
) ;
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
+ }
105
170
}
106
171
return false ;
107
172
}
@@ -128,6 +193,12 @@ export class Close extends SketchContribution {
128
193
}
129
194
}
130
195
196
+ enum Prompt {
197
+ Save ,
198
+ DoNotSave ,
199
+ Cancel ,
200
+ }
201
+
131
202
export namespace Close {
132
203
export namespace Commands {
133
204
export const CLOSE : Command = {
0 commit comments