Add support for view initial state (collapsed or hidden) (#102002)

Fixes #101283
This commit is contained in:
Alex Ross 2020-07-17 09:47:33 +02:00 committed by GitHub
parent 27e8b9d1a3
commit 0acc996121
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 5 deletions

View file

@ -56,8 +56,9 @@
{
"id": "npm",
"name": "%view.name%",
"when": "npm:showScriptExplorer || config.npm.enableScriptExplorer",
"icon": "images/code.svg"
"when": "npm:showScriptExplorer",
"icon": "images/code.svg",
"visibility": "hidden"
}
]
},

View file

@ -83,12 +83,19 @@ interface IUserFriendlyViewDescriptor {
icon?: string;
contextualTitle?: string;
visibility?: string;
// From 'remoteViewDescriptor' type
group?: string;
remoteName?: string | string[];
}
enum InitialVisibility {
Visible = 'visible',
Hidden = 'hidden',
Collapsed = 'collapsed'
}
const viewDescriptor: IJSONSchema = {
type: 'object',
properties: {
@ -112,6 +119,20 @@ const viewDescriptor: IJSONSchema = {
description: localize('vscode.extension.contributes.view.contextualTitle', "Human-readable context for when the view is moved out of its original location. By default, the view's container name will be used. Will be shown"),
type: 'string'
},
visibility: {
description: localize('vscode.extension.contributes.view.initialState', "Initial state of the view when the extension is first installed. Once the user has changed the view state by collapsing, moving, or hiding the view, the initial state will not be used again."),
type: 'string',
enum: [
'visible',
'hidden',
'collapsed'
],
enumDescriptions: [
localize('vscode.extension.contributes.view.initialState.visible', "The default initial state for view. The view will be expanded. This may have different behavior when the view container that the view is in is built in."),
localize('vscode.extension.contributes.view.initialState.hidden', "The view will not be shown in the view container, but will be discoverable through the views menu and other view entry points and can be un-hidden by the user."),
localize('vscode.extension.contributes.view.initialState.collapsed', "The view will show in the view container, but will be collapsed.")
]
}
}
};
@ -419,6 +440,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
: undefined;
const icon = item.icon ? resources.joinPath(extension.description.extensionLocation, item.icon) : undefined;
const initialVisibility = this.convertInitialVisibility(item.visibility);
const viewDescriptor = <ICustomViewDescriptor>{
id: item.id,
name: item.name,
@ -429,12 +451,13 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
canToggleVisibility: true,
canMoveView: true,
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name),
collapsed: this.showCollapsed(container),
collapsed: this.showCollapsed(container) || initialVisibility === InitialVisibility.Collapsed,
order: order,
extensionId: extension.description.identifier,
originalContainerId: entry.key,
group: item.group,
remoteAuthority: item.remoteName || (<any>item).remoteAuthority // TODO@roblou - delete after remote extensions are updated
remoteAuthority: item.remoteName || (<any>item).remoteAuthority, // TODO@roblou - delete after remote extensions are updated
hideByDefault: initialVisibility === InitialVisibility.Hidden
};
viewIds.add(viewDescriptor.id);
@ -463,6 +486,13 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
}
}
private convertInitialVisibility(value: any): InitialVisibility | undefined {
if (Object.values(InitialVisibility).includes(value)) {
return value;
}
return undefined;
}
private isValidViewDescriptors(viewDescriptors: IUserFriendlyViewDescriptor[], collector: ExtensionMessageCollector): boolean {
if (!Array.isArray(viewDescriptors)) {
collector.error(localize('requirearray', "views must be an array"));
@ -490,6 +520,10 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'contextualTitle'));
return false;
}
if (descriptor.visibility && !this.convertInitialVisibility(descriptor.visibility)) {
collector.error(localize('optenum', "property `{0}` can be omitted or must be one of {1}", 'visibility', Object.values(InitialVisibility).join(', ')));
return false;
}
}
return true;

View file

@ -982,6 +982,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
this.updateViewHeaders();
}
});
this._register(this.viewContainerModel.onDidChangeActiveViewDescriptors(() => this._onTitleAreaUpdate.fire()));
}
getTitle(): string {

View file

@ -45,7 +45,7 @@ export abstract class Viewlet extends PaneComposite implements IViewlet {
@IConfigurationService protected configurationService: IConfigurationService
) {
super(id, viewPaneContainer, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
this._register(Event.any(viewPaneContainer.onDidAddViews, viewPaneContainer.onDidRemoveViews)(() => {
this._register(Event.any(viewPaneContainer.onDidAddViews, viewPaneContainer.onDidRemoveViews, viewPaneContainer.onTitleAreaUpdate)(() => {
// Update title area since there is no better way to update secondary actions
this.updateTitleArea();
}));