1
1
import { nls } from '@theia/core/lib/common/nls' ;
2
- import { inject , injectable } from '@theia/core/shared/inversify' ;
2
+ import { injectable } from '@theia/core/shared/inversify' ;
3
3
import type { EditorOpenerOptions } from '@theia/editor/lib/browser/editor-manager' ;
4
4
import { Later } from '../../common/nls' ;
5
5
import { Sketch , SketchesError } from '../../common/protocol' ;
@@ -15,14 +15,9 @@ import { ApplicationError } from '@theia/core/lib/common/application-error';
15
15
import { Deferred , wait } from '@theia/core/lib/common/promise-util' ;
16
16
import { EditorWidget } from '@theia/editor/lib/browser/editor-widget' ;
17
17
import { DisposableCollection } from '@theia/core/lib/common/disposable' ;
18
- import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor' ;
19
- import { ContextKeyService as VSCodeContextKeyService } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/browser/contextKeyService' ;
20
18
21
19
@injectable ( )
22
20
export class OpenSketchFiles extends SketchContribution {
23
- @inject ( VSCodeContextKeyService )
24
- private readonly contextKeyService : VSCodeContextKeyService ;
25
-
26
21
override registerCommands ( registry : CommandRegistry ) : void {
27
22
registry . registerCommand ( OpenSketchFiles . Commands . OPEN_SKETCH_FILES , {
28
23
execute : ( uri : URI ) => this . openSketchFiles ( uri ) ,
@@ -135,39 +130,29 @@ export class OpenSketchFiles extends SketchContribution {
135
130
const widget = this . editorManager . all . find (
136
131
( widget ) => widget . editor . uri . toString ( ) === uri
137
132
) ;
133
+ if ( widget && ! forceOpen ) {
134
+ return widget ;
135
+ }
136
+
138
137
const disposables = new DisposableCollection ( ) ;
139
- if ( ! widget || forceOpen ) {
140
- const deferred = new Deferred < EditorWidget > ( ) ;
138
+ const deferred = new Deferred < EditorWidget > ( ) ;
139
+ if ( ! widget ) {
140
+ // If the editor or is not defined, assume one on create event
141
141
disposables . push (
142
142
this . editorManager . onCreated ( ( editor ) => {
143
143
if ( editor . editor . uri . toString ( ) === uri ) {
144
- if ( editor . isVisible ) {
145
- disposables . dispose ( ) ;
144
+ if ( editor . isAttached && editor . isVisible ) {
146
145
deferred . resolve ( editor ) ;
147
146
} else {
148
- // In Theia, the promise resolves after opening the editor, but the editor is neither attached to the DOM, nor visible.
149
- // This is a hack to first get an event from monaco after the widget update request, then IDE2 waits for the next monaco context key event.
150
- // Here, the monaco context key event is not used, but this is the first event after the editor is visible in the UI.
151
147
disposables . push (
152
- ( editor . editor as MonacoEditor ) . onDidResize ( ( dimension ) => {
153
- if ( dimension ) {
154
- const isKeyOwner = (
155
- arg : unknown
156
- ) : arg is { key : string } => {
157
- if ( typeof arg === 'object' ) {
158
- const object = arg as Record < string , unknown > ;
159
- return typeof object [ 'key' ] === 'string' ;
160
- }
161
- return false ;
162
- } ;
163
- disposables . push (
164
- this . contextKeyService . onDidChangeContext ( ( e ) => {
165
- // `commentIsEmpty` is the first context key change event received from monaco after the editor is for real visible in the UI.
166
- if ( isKeyOwner ( e ) && e . key === 'commentIsEmpty' ) {
167
- deferred . resolve ( editor ) ;
168
- disposables . dispose ( ) ;
169
- }
170
- } )
148
+ editor . onDidChangeVisibility ( ( visible ) => {
149
+ if ( visible ) {
150
+ // wait an animation frame. although the visible and attached props are true the editor is not there.
151
+ // let the browser render the widget
152
+ setTimeout (
153
+ ( ) =>
154
+ requestAnimationFrame ( ( ) => deferred . resolve ( editor ) ) ,
155
+ 0
171
156
) ;
172
157
}
173
158
} )
@@ -176,29 +161,39 @@ export class OpenSketchFiles extends SketchContribution {
176
161
}
177
162
} )
178
163
) ;
179
- this . editorManager . open (
164
+ }
165
+
166
+ this . editorManager
167
+ . open (
180
168
new URI ( uri ) ,
181
169
options ?? {
182
170
mode : 'reveal' ,
183
171
preview : false ,
184
172
counter : 0 ,
185
173
}
174
+ )
175
+ . then ( ( editorWidget ) => {
176
+ // if the widget was already opened we assume it was already already visible and attached to the DOM
177
+ // can resolve the deferred, no need to wait for the on create event.
178
+ if ( ! widget ) {
179
+ deferred . resolve ( editorWidget ) ;
180
+ }
181
+ } ) ;
182
+
183
+ const timeout = 5_000 ; // number of ms IDE2 waits for the editor to show up in the UI
184
+ const result = await Promise . race ( [
185
+ deferred . promise ,
186
+ wait ( timeout ) . then ( ( ) => {
187
+ disposables . dispose ( ) ;
188
+ return 'timeout' ;
189
+ } ) ,
190
+ ] ) ;
191
+ if ( result === 'timeout' ) {
192
+ console . warn (
193
+ `Timeout after ${ timeout } millis. The editor has not shown up in time. URI: ${ uri } `
186
194
) ;
187
- const timeout = 5_000 ; // number of ms IDE2 waits for the editor to show up in the UI
188
- const result = await Promise . race ( [
189
- deferred . promise ,
190
- wait ( timeout ) . then ( ( ) => {
191
- disposables . dispose ( ) ;
192
- return 'timeout' ;
193
- } ) ,
194
- ] ) ;
195
- if ( result === 'timeout' ) {
196
- console . warn (
197
- `Timeout after ${ timeout } millis. The editor has not shown up in time. URI: ${ uri } `
198
- ) ;
199
- }
200
- return result ;
201
195
}
196
+ return result ;
202
197
}
203
198
}
204
199
export namespace OpenSketchFiles {
0 commit comments