mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
Merge pull request #107215 from microsoft/aeschli/welcomeViewGroups
groups for viewsWelcome
This commit is contained in:
commit
2ef6c258b0
|
@ -2083,27 +2083,32 @@
|
|||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.empty%",
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == empty"
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == empty",
|
||||
"group": "2_open@1"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.folder%",
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == folder"
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == folder",
|
||||
"group": "5_scm@1"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.workspace%",
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0"
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount != 0",
|
||||
"group": "5_scm@1"
|
||||
},
|
||||
{
|
||||
"view": "scm",
|
||||
"contents": "%view.workbench.scm.emptyWorkspace%",
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount == 0"
|
||||
"when": "config.git.enabled && git.state == initialized && workbenchState == workspace && workspaceFolderCount == 0",
|
||||
"group": "2_open@1"
|
||||
},
|
||||
{
|
||||
"view": "explorer",
|
||||
"contents": "%view.workbench.cloneRepository%",
|
||||
"when": "config.git.enabled && git.state == initialized"
|
||||
"when": "config.git.enabled && git.state == initialized",
|
||||
"group": "5_scm@1"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -278,16 +278,18 @@ export interface IViewContainerModel {
|
|||
move(from: string, to: string): void;
|
||||
}
|
||||
|
||||
export enum ViewContentPriority {
|
||||
Normal = 0,
|
||||
Low = 1,
|
||||
Lowest = 2
|
||||
export enum ViewContentGroups {
|
||||
Open = '2_open',
|
||||
Debug = '4_debug',
|
||||
SCM = '5_scm',
|
||||
More = '9_more'
|
||||
}
|
||||
|
||||
export interface IViewContentDescriptor {
|
||||
readonly content: string;
|
||||
readonly when?: ContextKeyExpression | 'default';
|
||||
readonly priority?: ViewContentPriority;
|
||||
readonly group?: string;
|
||||
readonly order?: number;
|
||||
|
||||
/**
|
||||
* ordered preconditions for each button in the content
|
||||
|
@ -323,15 +325,12 @@ export interface IViewsRegistry {
|
|||
}
|
||||
|
||||
function compareViewContentDescriptors(a: IViewContentDescriptor, b: IViewContentDescriptor): number {
|
||||
const aPriority = a.priority ?? ViewContentPriority.Normal;
|
||||
const bPriority = b.priority ?? ViewContentPriority.Normal;
|
||||
|
||||
if (aPriority !== bPriority) {
|
||||
return aPriority - bPriority;
|
||||
const aGroup = a.group ?? ViewContentGroups.More;
|
||||
const bGroup = b.group ?? ViewContentGroups.More;
|
||||
if (aGroup !== bGroup) {
|
||||
return aGroup.localeCompare(bGroup);
|
||||
}
|
||||
|
||||
// No priroity, keep views sorted in the order they got registered
|
||||
return 0;
|
||||
return (a.order ?? 5) - (b.order ?? 5);
|
||||
}
|
||||
|
||||
class ViewsRegistry extends Disposable implements IViewsRegistry {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { IDebugService, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib
|
|||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IViewDescriptorService, IViewsRegistry, Extensions, ViewContentPriority } from 'vs/workbench/common/views';
|
||||
import { IViewDescriptorService, IViewsRegistry, Extensions, ViewContentGroups } from 'vs/workbench/common/views';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys';
|
||||
|
@ -109,7 +109,8 @@ const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
|||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize({ key: 'openAFileWhichCanBeDebugged', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"[Open a file](command:{0}) which can be debugged or run.", isMacintosh ? OpenFileFolderAction.ID : OpenFileAction.ID),
|
||||
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR.toNegated())
|
||||
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR.toNegated()),
|
||||
group: ViewContentGroups.Open
|
||||
});
|
||||
|
||||
let debugKeybindingLabel = '';
|
||||
|
@ -117,24 +118,28 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
|||
content: localize({ key: 'runAndDebugAction', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"[Run and Debug{0}](command:{1})", debugKeybindingLabel, StartAction.ID),
|
||||
preconditions: [CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR],
|
||||
when: CONTEXT_DEBUGGERS_AVAILABLE
|
||||
when: CONTEXT_DEBUGGERS_AVAILABLE,
|
||||
group: ViewContentGroups.Debug
|
||||
});
|
||||
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize({ key: 'detectThenRunAndDebug', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"[Show](command:{0}) all automatic debug configurations.", SelectAndStartAction.ID),
|
||||
priority: ViewContentPriority.Lowest,
|
||||
when: CONTEXT_DEBUGGERS_AVAILABLE
|
||||
when: CONTEXT_DEBUGGERS_AVAILABLE,
|
||||
group: ViewContentGroups.Debug,
|
||||
order: 10
|
||||
});
|
||||
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize({ key: 'customizeRunAndDebug', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"To customize Run and Debug [create a launch.json file](command:{0}).", ConfigureAction.ID),
|
||||
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.notEqualsTo('empty'))
|
||||
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.notEqualsTo('empty')),
|
||||
group: ViewContentGroups.Debug
|
||||
});
|
||||
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize({ key: 'customizeRunAndDebugOpenFolder', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"To customize Run and Debug, [open a folder](command:{0}) and create a launch.json file.", isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID),
|
||||
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.isEqualTo('empty'))
|
||||
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.isEqualTo('empty')),
|
||||
group: ViewContentGroups.Debug
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IViewsRegistry, IViewDescriptor, Extensions, ViewContainer, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService, ViewContentGroups } from 'vs/workbench/common/views';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
|
@ -273,18 +273,24 @@ const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
|||
viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
||||
content: localize({ key: 'noWorkspaceHelp', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"You have not yet added a folder to the workspace.\n[Add Folder](command:{0})", AddRootFolderAction.ID),
|
||||
when: WorkbenchStateContext.isEqualTo('workspace')
|
||||
when: WorkbenchStateContext.isEqualTo('workspace'),
|
||||
group: ViewContentGroups.Open,
|
||||
order: 1
|
||||
});
|
||||
|
||||
const commandId = isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID;
|
||||
viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
||||
content: localize({ key: 'remoteNoFolderHelp', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"Connected to remote.\n[Open Folder](command:{0})", commandId),
|
||||
when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.notEqualsTo(''), IsWebContext.toNegated())
|
||||
when: ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.notEqualsTo(''), IsWebContext.toNegated()),
|
||||
group: ViewContentGroups.Open,
|
||||
order: 1
|
||||
});
|
||||
|
||||
viewsRegistry.registerViewWelcomeContent(EmptyView.ID, {
|
||||
content: localize({ key: 'noFolderHelp', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] },
|
||||
"You have not yet opened a folder.\n[Open Folder](command:{0})", commandId),
|
||||
when: ContextKeyExpr.or(ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.isEqualTo('')), ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), IsWebContext))
|
||||
when: ContextKeyExpr.or(ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), RemoteNameContext.isEqualTo('')), ContextKeyExpr.and(WorkbenchStateContext.notEqualsTo('workspace'), IsWebContext)),
|
||||
group: ViewContentGroups.Open,
|
||||
order: 1
|
||||
});
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { ViewsWelcomeExtensionPoint, ViewWelcome, ViewIdentifierMap } from './viewsWelcomeExtensionPoint';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Extensions as ViewContainerExtensions, IViewsRegistry, ViewContentPriority } from 'vs/workbench/common/views';
|
||||
import { Extensions as ViewContainerExtensions, IViewsRegistry } from 'vs/workbench/common/views';
|
||||
|
||||
const viewsRegistry = Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry);
|
||||
|
||||
|
@ -34,10 +35,12 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo
|
|||
for (const contribution of added) {
|
||||
for (const welcome of contribution.value) {
|
||||
const id = ViewIdentifierMap[welcome.view] ?? welcome.view;
|
||||
const { group, order } = parseGroupAndOrder(welcome, contribution);
|
||||
const disposable = viewsRegistry.registerViewWelcomeContent(id, {
|
||||
content: welcome.contents,
|
||||
when: ContextKeyExpr.deserialize(welcome.when),
|
||||
priority: contribution.description.isBuiltin ? ViewContentPriority.Low : ViewContentPriority.Lowest
|
||||
group,
|
||||
order
|
||||
});
|
||||
|
||||
this.viewWelcomeContents.set(welcome, disposable);
|
||||
|
@ -46,3 +49,24 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
function parseGroupAndOrder(welcome: ViewWelcome, contribution: IExtensionPointUser<ViewsWelcomeExtensionPoint>): { group: string | undefined, order: number | undefined } {
|
||||
|
||||
let group: string | undefined;
|
||||
let order: number | undefined;
|
||||
if (welcome.group) {
|
||||
if (!contribution.description.enableProposedApi) {
|
||||
contribution.collector.warn(nls.localize('ViewsWelcomeExtensionPoint.proposedAPI', "The viewsWelcome contribution in '{0}' requires 'enableProposedApi' to be enabled.", contribution.description.identifier.value));
|
||||
return { group, order };
|
||||
}
|
||||
|
||||
const idx = welcome.group.lastIndexOf('@');
|
||||
if (idx > 0) {
|
||||
group = welcome.group.substr(0, idx);
|
||||
order = Number(welcome.group.substr(idx + 1)) || undefined;
|
||||
} else {
|
||||
group = welcome.group;
|
||||
}
|
||||
}
|
||||
return { group, order };
|
||||
}
|
||||
|
|
|
@ -10,12 +10,14 @@ export enum ViewsWelcomeExtensionPointFields {
|
|||
view = 'view',
|
||||
contents = 'contents',
|
||||
when = 'when',
|
||||
group = 'group',
|
||||
}
|
||||
|
||||
export interface ViewWelcome {
|
||||
readonly [ViewsWelcomeExtensionPointFields.view]: string;
|
||||
readonly [ViewsWelcomeExtensionPointFields.contents]: string;
|
||||
readonly [ViewsWelcomeExtensionPointFields.when]: string;
|
||||
readonly [ViewsWelcomeExtensionPointFields.group]: string;
|
||||
}
|
||||
|
||||
export type ViewsWelcomeExtensionPoint = ViewWelcome[];
|
||||
|
@ -58,6 +60,10 @@ const viewsWelcomeExtensionPointSchema = Object.freeze<IConfigurationPropertySch
|
|||
type: 'string',
|
||||
description: nls.localize('contributes.viewsWelcome.view.when', "Condition when the welcome content should be displayed."),
|
||||
},
|
||||
[ViewsWelcomeExtensionPointFields.group]: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.viewsWelcome.view.group', "Group to which this welcome content belongs."),
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue