@@ -55,6 +55,13 @@ export const PLUGIN_VIEW_DATA_FACTORY_ID = 'plugin-view-data';
55
55
56
56
export type ViewDataProvider = ( params : { state ?: object , viewInfo : View } ) => Promise < TreeViewWidget > ;
57
57
58
+ export interface ViewContainerInfo {
59
+ id : string
60
+ location : string
61
+ options : ViewContainerTitleOptions
62
+ onViewAdded : ( ) => void
63
+ }
64
+
58
65
@injectable ( )
59
66
export class PluginViewRegistry implements FrontendApplicationContribution {
60
67
@@ -96,7 +103,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
96
103
97
104
private readonly views = new Map < string , [ string , View ] > ( ) ;
98
105
private readonly viewsWelcome = new Map < string , ViewWelcome [ ] > ( ) ;
99
- private readonly viewContainers = new Map < string , [ string , ViewContainerTitleOptions ] > ( ) ;
106
+ private readonly viewContainers = new Map < string , ViewContainerInfo > ( ) ;
100
107
private readonly containerViews = new Map < string , string [ ] > ( ) ;
101
108
private readonly viewClauseContexts = new Map < string , Set < string > | undefined > ( ) ;
102
109
@@ -324,34 +331,47 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
324
331
325
332
protected doRegisterViewContainer ( id : string , location : string , options : ViewContainerTitleOptions ) : Disposable {
326
333
const toDispose = new DisposableCollection ( ) ;
327
- this . viewContainers . set ( id , [ location , options ] ) ;
328
334
toDispose . push ( Disposable . create ( ( ) => this . viewContainers . delete ( id ) ) ) ;
329
335
const toggleCommandId = `plugin.view-container.${ id } .toggle` ;
330
- toDispose . push ( this . commands . registerCommand ( {
331
- id : toggleCommandId ,
332
- label : 'Toggle ' + options . label + ' View'
333
- } , {
334
- execute : ( ) => this . toggleViewContainer ( id )
335
- } ) ) ;
336
- toDispose . push ( this . menus . registerMenuAction ( CommonMenus . VIEW_VIEWS , {
337
- commandId : toggleCommandId ,
338
- label : options . label
339
- } ) ) ;
340
- toDispose . push ( this . quickView ?. registerItem ( {
341
- label : options . label ,
342
- open : async ( ) => {
343
- const widget = await this . openViewContainer ( id ) ;
336
+ // Some plugins may register empty view containers.
337
+ // We should not register commands for them immediately, as that leads to bad UX.
338
+ // Instead, we register commands the first time we add a view to them.
339
+ let activate = ( ) => {
340
+ toDispose . push ( this . commands . registerCommand ( {
341
+ id : toggleCommandId ,
342
+ category : nls . localizeByDefault ( 'View' ) ,
343
+ label : nls . localizeByDefault ( 'Toggle {0}' , options . label )
344
+ } , {
345
+ execute : ( ) => this . toggleViewContainer ( id )
346
+ } ) ) ;
347
+ toDispose . push ( this . menus . registerMenuAction ( CommonMenus . VIEW_VIEWS , {
348
+ commandId : toggleCommandId ,
349
+ label : options . label
350
+ } ) ) ;
351
+ toDispose . push ( this . quickView ?. registerItem ( {
352
+ label : options . label ,
353
+ open : async ( ) => {
354
+ const widget = await this . openViewContainer ( id ) ;
355
+ if ( widget ) {
356
+ this . shell . activateWidget ( widget . id ) ;
357
+ }
358
+ }
359
+ } ) ) ;
360
+ toDispose . push ( Disposable . create ( async ( ) => {
361
+ const widget = await this . getPluginViewContainer ( id ) ;
344
362
if ( widget ) {
345
- this . shell . activateWidget ( widget . id ) ;
363
+ widget . dispose ( ) ;
346
364
}
347
- }
348
- } ) ) ;
349
- toDispose . push ( Disposable . create ( async ( ) => {
350
- const widget = await this . getPluginViewContainer ( id ) ;
351
- if ( widget ) {
352
- widget . dispose ( ) ;
353
- }
354
- } ) ) ;
365
+ } ) ) ;
366
+ // Ignore every subsequent activation call
367
+ activate = ( ) => { } ;
368
+ } ;
369
+ this . viewContainers . set ( id , {
370
+ id,
371
+ location,
372
+ options,
373
+ onViewAdded : ( ) => activate ( )
374
+ } ) ;
355
375
return toDispose ;
356
376
}
357
377
@@ -374,6 +394,11 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
374
394
this . views . set ( view . id , [ viewContainerId , view ] ) ;
375
395
toDispose . push ( Disposable . create ( ( ) => this . views . delete ( view . id ) ) ) ;
376
396
397
+ const containerInfo = this . viewContainers . get ( viewContainerId ) ;
398
+ if ( containerInfo ) {
399
+ containerInfo . onViewAdded ( ) ;
400
+ }
401
+
377
402
const containerViews = this . getContainerViews ( viewContainerId ) ;
378
403
containerViews . push ( view . id ) ;
379
404
this . containerViews . set ( viewContainerId , containerViews ) ;
@@ -634,7 +659,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
634
659
if ( ! data ) {
635
660
return undefined ;
636
661
}
637
- const [ location ] = data ;
662
+ const { location } = data ;
638
663
const containerWidget = await this . getOrCreateViewContainerWidget ( containerId ) ;
639
664
if ( ! containerWidget . isAttached ) {
640
665
await this . shell . addWidget ( containerWidget , {
@@ -648,7 +673,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
648
673
protected async prepareViewContainer ( viewContainerId : string , containerWidget : ViewContainerWidget ) : Promise < void > {
649
674
const data = this . viewContainers . get ( viewContainerId ) ;
650
675
if ( data ) {
651
- const [ , options ] = data ;
676
+ const { options } = data ;
652
677
containerWidget . setTitleOptions ( options ) ;
653
678
}
654
679
for ( const viewId of this . getContainerViews ( viewContainerId ) ) {
0 commit comments