profiles ux improvements (#171065)

- support pick icon for profile
- allign profile icon with other activity bar icons
- simplify actions
This commit is contained in:
Sandeep Somavarapu 2023-01-11 15:34:59 +01:00 committed by GitHub
parent 6c06876a83
commit 40782e42bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 161 additions and 219 deletions

View file

@ -19,7 +19,7 @@ import { IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platf
import { ActivityAction, ActivityActionViewItem, IActivityActionViewItemOptions, IActivityHoverOptions, ICompositeBar, ICompositeBarColors, ToggleCompositeBadgeAction, ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IActivity } from 'vs/workbench/common/activity';
import { ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_ACTIVE_FOCUS_BORDER, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_PROFILE_BACKGROUND, ACTIVITY_BAR_PROFILE_HOVER_FOREGROUND } from 'vs/workbench/common/theme';
import { ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_ACTIVE_FOCUS_BORDER, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_PROFILE_HOVER_FOREGROUND } from 'vs/workbench/common/theme';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
@ -508,11 +508,6 @@ registerThemingParticipant((theme, collector) => {
const activityBarForegroundColor = theme.getColor(ACTIVITY_BAR_FOREGROUND);
if (activityBarForegroundColor) {
collector.addRule(`
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active .action-label:not(.codicon):not(.profile-activity-item),
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .action-label:not(.codicon):not(.profile-activity-item),
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover .action-label:not(.codicon):not(.profile-activity-item) {
background-color: ${activityBarForegroundColor} !important;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active .action-label.codicon,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .action-label.codicon,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover .action-label.codicon {
@ -521,23 +516,12 @@ registerThemingParticipant((theme, collector) => {
`);
}
const activityBarProfileBgColor = theme.getColor(ACTIVITY_BAR_PROFILE_BACKGROUND);
if (activityBarProfileBgColor) {
collector.addRule(`
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label.profile-activity-item,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label.profile-activity-item,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label.profile-activity-item {
background-color: ${activityBarProfileBgColor} !important;
}
`);
}
const activityBarProfileHoverFgColor = theme.getColor(ACTIVITY_BAR_PROFILE_HOVER_FOREGROUND);
if (activityBarProfileHoverFgColor) {
collector.addRule(`
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active .action-label.profile-activity-item,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .action-label.profile-activity-item,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover .action-label.profile-activity-item {
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active.profile-activity-item .action-label,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.profile-activity-item:focus .action-label,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.profile-activity-item:hover .action-label {
color: ${activityBarProfileHoverFgColor} !important;
}
`);

View file

@ -43,7 +43,7 @@ import { StringSHA1 } from 'vs/base/common/hash';
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';
import { GestureEvent } from 'vs/base/browser/touch';
import { IPaneCompositePart, IPaneCompositeSelectorPart } from 'vs/workbench/browser/parts/paneCompositePart';
import { IUserDataProfileService, PROFILES_TTILE } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
import { IUserDataProfileService, PROFILES_TTILE, defaultUserDataProfileIcon } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
interface IPlaceholderViewContainer {
@ -618,11 +618,11 @@ export class ActivitybarPart extends Part implements IPaneCompositeSelectorPart
private createProfilesActivity(): IProfileActivity {
const shortName = this.userDataProfileService.getShortName(this.userDataProfileService.currentProfile);
const icon = ThemeIcon.fromString(shortName);
const icon = ThemeIcon.fromString(shortName) ?? defaultUserDataProfileIcon;
return {
id: 'workbench.actions.profiles',
name: icon ? this.userDataProfileService.currentProfile.name : shortName,
cssClass: icon ? `${ThemeIcon.asClassName(icon)} profile-activity-item` : 'profile-activity-item',
cssClass: ThemeIcon.asClassName(icon),
icon: !!icon
};
}

View file

@ -176,26 +176,8 @@
vertical-align: baseline;
}
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-label.profile-activity-item {
height: 20px;
width: 32px;
margin: 14px 8px;
padding: 0px;
justify-content: center;
align-items: center;
font-size: 11px;
font-weight: 600;
border-radius: 10px;
}
/* Right aligned */
.monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .action-label:not(.codicon):not(.profile-activity-item) {
margin-left: 0;
padding: 0 48px 0 0;
background-position: calc(100% - 9px) center;
}
.monaco-workbench .activitybar.right > .content :not(.monaco-menu) > .monaco-action-bar .badge {
left: auto;
right: 0;

View file

@ -639,13 +639,6 @@ export const ACTIVITY_BAR_PROFILE_HOVER_FOREGROUND = registerColor('activityBarI
hcLight: ACTIVITY_BAR_FOREGROUND
}, localize('activityBarItem.profilesHoverForeground', "Foreground color for the profile entry on the activity bar when hovering."));
export const ACTIVITY_BAR_PROFILE_BACKGROUND = registerColor('activityBarItem.profilesBackground', {
dark: lighten(ACTIVITY_BAR_BACKGROUND, 0.5),
light: darken(ACTIVITY_BAR_BACKGROUND, 0.12),
hcDark: null,
hcLight: null
}, localize('activityBarItem.profilesBackground', "Background color for the profile entry on the activity bar."));
// < --- Remote --- >
export const STATUS_BAR_HOST_NAME_BACKGROUND = registerColor('statusBarItem.remoteBackground', {

View file

@ -19,11 +19,9 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { RenameProfileAction } from 'vs/workbench/contrib/userDataProfile/browser/userDataProfileActions';
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { CURRENT_PROFILE_CONTEXT, HAS_PROFILES_CONTEXT, isUserDataProfileTemplate, IS_CURRENT_PROFILE_TRANSIENT_CONTEXT, IS_PROFILE_IMPORT_IN_PROGRESS_CONTEXT, IUserDataProfileImportExportService, IUserDataProfileManagementService, IUserDataProfileService, IUserDataProfileTemplate, ManageProfilesSubMenu, PROFILES_CATEGORY, PROFILES_ENABLEMENT_CONTEXT, PROFILES_TTILE, PROFILE_FILTER, IS_PROFILE_EXPORT_IN_PROGRESS_CONTEXT } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { CURRENT_PROFILE_CONTEXT, HAS_PROFILES_CONTEXT, isUserDataProfileTemplate, IS_CURRENT_PROFILE_TRANSIENT_CONTEXT, IS_PROFILE_IMPORT_IN_PROGRESS_CONTEXT, IUserDataProfileImportExportService, IUserDataProfileManagementService, IUserDataProfileService, IUserDataProfileTemplate, ManageProfilesSubMenu, PROFILES_CATEGORY, PROFILES_ENABLEMENT_CONTEXT, PROFILES_TTILE, PROFILE_FILTER, IS_PROFILE_EXPORT_IN_PROGRESS_CONTEXT, defaultUserDataProfileIcon } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { charCount } from 'vs/base/common/strings';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IDialogService, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { Codicon } from 'vs/base/common/codicons';
import { IFileService } from 'vs/platform/files/common/files';
@ -34,9 +32,22 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceTagsService } from 'vs/workbench/contrib/tags/common/workspaceTags';
import { getErrorMessage } from 'vs/base/common/errors';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
const SelectProfileSubMenu = new MenuId('SelectProfile');
const CREATE_EMPTY_PROFILE_ACTION_ID = 'workbench.profiles.actions.createEmptyProfile';
const CREATE_EMPTY_PROFILE_ACTION_TITLE = {
value: localize('create empty profile', "Create an Empty Profile..."),
original: 'Create an Empty Profile...'
};
const CREATE_FROM_CURRENT_PROFILE_ACTION_ID = 'workbench.profiles.actions.createFromCurrentProfile';
const CREATE_FROM_CURRENT_PROFILE_ACTION_TITLE = {
value: localize('save profile as', "Create from Current Profile..."),
original: 'Create from Current Profile...'
};
export class UserDataProfilesWorkbenchContribution extends Disposable implements IWorkbenchContribution {
private readonly currentProfileContext: IContextKey<string>;
@ -52,6 +63,8 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IWorkspaceTagsService private readonly workspaceTagsService: IWorkspaceTagsService,
@IContextKeyService contextKeyService: IContextKeyService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@INotificationService private readonly notificationService: INotificationService,
@ILifecycleService private readonly lifecycleService: ILifecycleService,
) {
super();
@ -108,6 +121,10 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
this.registerCurrentProfilesActions();
this._register(Event.any(this.userDataProfileService.onDidChangeCurrentProfile, this.userDataProfileService.onDidUpdateCurrentProfile)(() => this.registerCurrentProfilesActions()));
this.registerCreateEmptyProfileAction();
this.registerCreateFromCurrentProfileAction();
this.registerCreateProfileAction();
}
private registerManageProfilesSubMenu(): void {
@ -166,24 +183,22 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
private readonly currentprofileActionsDisposable = this._register(new MutableDisposable<DisposableStore>());
private registerCurrentProfilesActions(): void {
this.currentprofileActionsDisposable.value = new DisposableStore();
this.currentprofileActionsDisposable.value.add(this.registerUpdateCurrentProfileShortNameAction());
this.currentprofileActionsDisposable.value.add(this.registerChangeIconForCurrentProfileAction());
this.currentprofileActionsDisposable.value.add(this.registerRenameCurrentProfileAction());
this.currentprofileActionsDisposable.value.add(this.registerShowCurrentProfileContentsAction());
this.currentprofileActionsDisposable.value.add(this.registerExportCurrentProfileAction());
this.currentprofileActionsDisposable.value.add(this.registerImportProfileAction());
}
private registerUpdateCurrentProfileShortNameAction(): IDisposable {
private registerChangeIconForCurrentProfileAction(): IDisposable {
const that = this;
return registerAction2(class UpdateCurrentProfileShortName extends Action2 {
return registerAction2(class ChangeIconForCurrentProfileAction extends Action2 {
constructor() {
const shortName = that.userDataProfileService.getShortName(that.userDataProfileService.currentProfile);
const themeIcon = ThemeIcon.fromString(shortName);
super({
id: `workbench.profiles.actions.updateCurrentProfileShortName`,
id: `workbench.profiles.actions.changeIconForCurrentProfile`,
title: {
value: localize('change short name profile', "Change Profile Short Name ({0})...", themeIcon?.id ?? shortName),
original: `Change Profile Short Name (${themeIcon?.id ?? shortName})...`
value: localize('change icon', "Change Icon..."),
original: `Change Icon...`
},
menu: [
{
@ -196,35 +211,13 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
});
}
async run(accessor: ServicesAccessor) {
const quickInputService = accessor.get(IQuickInputService);
const notificationService = accessor.get(INotificationService);
const profile = that.userDataProfileService.currentProfile;
const shortName = await quickInputService.input({
value: that.userDataProfileService.getShortName(profile),
title: localize('change short name', "Change Short Name..."),
validateInput: async (value: string) => {
if (profile.shortName === value) {
return undefined;
}
const themeIcon = ThemeIcon.fromString(value);
if (themeIcon) {
if (Codicon.getAll().some(c => c.id === themeIcon.id)) {
return undefined;
}
return localize('invalid codicon', "Invalid codicon. Please use a valid codicon id.");
}
if (charCount(value) > 2) {
return localize('invalid short name', "Short name should be at most 2 characters long.");
}
return undefined;
}
});
const shortName = await that.pickIcon(profile);
if (shortName && shortName !== profile.shortName) {
try {
await that.userDataProfileManagementService.updateProfile(profile, { shortName });
} catch (error) {
notificationService.error(error);
that.notificationService.error(error);
}
}
}
@ -238,8 +231,8 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
super({
id: `workbench.profiles.actions.renameCurrentProfile`,
title: {
value: localize('rename profile', "Rename Profile ({0})...", that.userDataProfileService.currentProfile.name),
original: `Rename Profile (${that.userDataProfileService.currentProfile.name})...`
value: localize('rename profile', "Rename..."),
original: `Rename...`
},
menu: [
{
@ -258,15 +251,14 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
}
private registerShowCurrentProfileContentsAction(): IDisposable {
const that = this;
const id = 'workbench.profiles.actions.showProfileContents';
return registerAction2(class ShowProfileContentsAction extends Action2 {
constructor() {
super({
id,
title: {
value: localize('show profile contents', "Show Profile Contents ({0})...", that.userDataProfileService.currentProfile.name),
original: `Show Profile Contents (${that.userDataProfileService.currentProfile.name})...`
value: localize('show profile contents', "Show Contents..."),
original: `ShowContents...`
},
category: PROFILES_CATEGORY,
menu: [
@ -464,6 +456,124 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
return disposables;
}
private registerCreateFromCurrentProfileAction(): void {
const that = this;
this._register(registerAction2(class CreateFromCurrentProfileAction extends Action2 {
constructor() {
super({
id: CREATE_FROM_CURRENT_PROFILE_ACTION_ID,
title: CREATE_FROM_CURRENT_PROFILE_ACTION_TITLE,
category: PROFILES_CATEGORY,
f1: true,
precondition: PROFILES_ENABLEMENT_CONTEXT
});
}
run(accessor: ServicesAccessor) {
return that.createProfile(true);
}
}));
}
private registerCreateEmptyProfileAction(): void {
const that = this;
this._register(registerAction2(class CreateEmptyProfileAction extends Action2 {
constructor() {
super({
id: CREATE_EMPTY_PROFILE_ACTION_ID,
title: CREATE_EMPTY_PROFILE_ACTION_TITLE,
category: PROFILES_CATEGORY,
f1: true,
precondition: PROFILES_ENABLEMENT_CONTEXT
});
}
run(accessor: ServicesAccessor) {
return that.createProfile(false);
}
}));
}
private async createProfile(fromExisting: boolean): Promise<void> {
const name = await this.quickInputService.input({
placeHolder: localize('name', "Profile name"),
title: fromExisting ? localize('create from current profle', "Create from Current Profile...") : localize('create empty profile', "Create an Empty Profile..."),
validateInput: async (value: string) => {
if (this.userDataProfilesService.profiles.some(p => p.name === value)) {
return localize('profileExists', "Profile with name {0} already exists.", value);
}
return undefined;
}
});
if (!name) {
return;
}
const icon = await this.pickIcon();
if (!icon) {
return;
}
try {
await this.userDataProfileManagementService.createAndEnterProfile(name, { shortName: icon }, fromExisting);
} catch (error) {
this.notificationService.error(error);
}
}
private async pickIcon(profile?: IUserDataProfile): Promise<string | undefined> {
const codiconQuickPicks: Array<IQuickPickItem | IQuickPickSeparator> = [];
codiconQuickPicks.push({ label: `$(${defaultUserDataProfileIcon.id})`, description: localize('default', "Default") });
codiconQuickPicks.push({ label: '', type: 'separator' });
const currentIcon = profile?.shortName ? ThemeIcon.fromString(profile.shortName) : undefined;
for (const codicon of Codicon.getAll()) {
codiconQuickPicks.push({ label: `$(${codicon.id})`, description: `${codicon.id}${currentIcon?.id === codicon.id ? ` (${localize('current', "Current")})` : ''}` });
}
const result = await this.quickInputService.pick(codiconQuickPicks, {
title: profile ? localize('change icon title', "Change icon for {0} Profile", profile.name) : localize('pick icon', "Pick icon..."),
matchOnDescription: true,
});
return result?.label;
}
private registerCreateProfileAction(): void {
this._register(registerAction2(class CreateProfileAction extends Action2 {
constructor() {
super({
id: 'workbench.profiles.actions.createProfile',
title: {
value: localize('create profile', "Create Profile..."),
original: 'Create Profile...'
},
category: PROFILES_CATEGORY,
precondition: PROFILES_ENABLEMENT_CONTEXT,
menu: [
{
id: ManageProfilesSubMenu,
group: '3_manage_profiles',
when: PROFILES_ENABLEMENT_CONTEXT,
order: 1
}
]
});
}
async run(accessor: ServicesAccessor) {
const quickInputService = accessor.get(IQuickInputService);
const commandService = accessor.get(ICommandService);
const pick = await quickInputService.pick(
[{
id: CREATE_EMPTY_PROFILE_ACTION_ID,
label: CREATE_EMPTY_PROFILE_ACTION_TITLE.value,
}, {
id: CREATE_FROM_CURRENT_PROFILE_ACTION_ID,
label: CREATE_FROM_CURRENT_PROFILE_ACTION_TITLE.value,
}], { hideInput: true, canPickMany: false, title: localize('create profile title', "{0}: Create...", PROFILES_CATEGORY.value) });
if (pick?.id) {
return commandService.executeCommand(pick.id);
}
}
}));
}
private async reportWorkspaceProfileInfo(): Promise<void> {
await this.lifecycleService.when(LifecyclePhase.Eventually);
const workspaceId = await this.workspaceTagsService.getTelemetryWorkspaceId(this.workspaceContextService.getWorkspace(), this.workspaceContextService.getWorkbenchState());

View file

@ -17,128 +17,6 @@ import { Codicon } from 'vs/base/common/codicons';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IAction, Separator } from 'vs/base/common/actions';
class CreateFromCurrentProfileAction extends Action2 {
static readonly ID = 'workbench.profiles.actions.createFromCurrentProfile';
static readonly TITLE = {
value: localize('save profile as', "Create from Current Profile..."),
original: 'Create from Current Profile...'
};
constructor() {
super({
id: CreateFromCurrentProfileAction.ID,
title: CreateFromCurrentProfileAction.TITLE,
category: PROFILES_CATEGORY,
f1: true,
precondition: PROFILES_ENABLEMENT_CONTEXT
});
}
async run(accessor: ServicesAccessor) {
const quickInputService = accessor.get(IQuickInputService);
const notificationService = accessor.get(INotificationService);
const userDataProfileManagementService = accessor.get(IUserDataProfileManagementService);
const userDataProfilesService = accessor.get(IUserDataProfilesService);
const name = await quickInputService.input({
placeHolder: localize('name', "Profile name"),
title: localize('save profile as', "Create from Current Profile..."),
validateInput: async (value: string) => {
if (userDataProfilesService.profiles.some(p => p.name === value)) {
return localize('profileExists', "Profile with name {0} already exists.", value);
}
return undefined;
}
});
if (name) {
try {
await userDataProfileManagementService.createAndEnterProfile(name, undefined, true);
} catch (error) {
notificationService.error(error);
}
}
}
}
registerAction2(CreateFromCurrentProfileAction);
class CreateEmptyProfileAction extends Action2 {
static readonly ID = 'workbench.profiles.actions.createEmptyProfile';
static readonly TITLE = {
value: localize('create empty profile', "Create an Empty Profile..."),
original: 'Create an Empty Profile...'
};
constructor() {
super({
id: CreateEmptyProfileAction.ID,
title: CreateEmptyProfileAction.TITLE,
category: PROFILES_CATEGORY,
f1: true,
precondition: PROFILES_ENABLEMENT_CONTEXT
});
}
async run(accessor: ServicesAccessor) {
const quickInputService = accessor.get(IQuickInputService);
const userDataProfileManagementService = accessor.get(IUserDataProfileManagementService);
const notificationService = accessor.get(INotificationService);
const userDataProfilesService = accessor.get(IUserDataProfilesService);
const name = await quickInputService.input({
placeHolder: localize('name', "Profile name"),
title: localize('create and enter empty profile', "Create an Empty Profile..."),
validateInput: async (value: string) => {
if (userDataProfilesService.profiles.some(p => p.name === value)) {
return localize('profileExists', "Profile with name {0} already exists.", value);
}
return undefined;
}
});
if (name) {
try {
await userDataProfileManagementService.createAndEnterProfile(name, undefined, undefined);
} catch (error) {
notificationService.error(error);
}
}
}
}
registerAction2(CreateEmptyProfileAction);
registerAction2(class CreateProfileAction extends Action2 {
constructor() {
super({
id: 'workbench.profiles.actions.createProfile',
title: {
value: localize('create profile', "Create Profile..."),
original: 'Create Profile...'
},
category: PROFILES_CATEGORY,
precondition: PROFILES_ENABLEMENT_CONTEXT,
menu: [
{
id: ManageProfilesSubMenu,
group: '3_manage_profiles',
when: PROFILES_ENABLEMENT_CONTEXT,
order: 1
}
]
});
}
async run(accessor: ServicesAccessor) {
const quickInputService = accessor.get(IQuickInputService);
const commandService = accessor.get(ICommandService);
const pick = await quickInputService.pick(
[{
id: CreateEmptyProfileAction.ID,
label: CreateEmptyProfileAction.TITLE.value,
}, {
id: CreateFromCurrentProfileAction.ID,
label: CreateFromCurrentProfileAction.TITLE.value,
}], { hideInput: true, canPickMany: false, title: localize('create profile title', "{0}: Create...", PROFILES_CATEGORY.value) });
if (pick?.id) {
return commandService.executeCommand(pick.id);
}
}
});
class CreateTransientProfileAction extends Action2 {
static readonly ID = 'workbench.profiles.actions.createTemporaryProfile';
static readonly TITLE = {

View file

@ -6,6 +6,7 @@
import { Promises } from 'vs/base/common/async';
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
import { defaultUserDataProfileIcon, DidChangeUserDataProfileEvent, IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
@ -56,16 +57,10 @@ export class UserDataProfileService extends Disposable implements IUserDataProfi
}
getShortName(profile: IUserDataProfile): string {
if (profile.isDefault) {
return `$(${defaultUserDataProfileIcon.id})`;
}
if (profile.shortName) {
if (!profile.isDefault && profile.shortName && ThemeIcon.fromId(profile.shortName)) {
return profile.shortName;
}
if (profile.isTransient) {
return `T${profile.name.charAt(profile.name.length - 1)}`;
}
return profile.name.substring(0, 2).toUpperCase();
return `$(${defaultUserDataProfileIcon.id})`;
}
}