diff --git a/src/vs/platform/userDataProfile/common/userDataProfile.ts b/src/vs/platform/userDataProfile/common/userDataProfile.ts index 9e9897e8cdc9b..ede2d98a33e50 100644 --- a/src/vs/platform/userDataProfile/common/userDataProfile.ts +++ b/src/vs/platform/userDataProfile/common/userDataProfile.ts @@ -81,6 +81,9 @@ if (!isWeb) { }); } +export type EmptyWindowWorkspaceIdentifier = 'empty-window'; +export type WorkspaceIdentifier = ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier | EmptyWindowWorkspaceIdentifier; + export type DidChangeProfilesEvent = { readonly added: IUserDataProfile[]; readonly removed: IUserDataProfile[]; readonly all: IUserDataProfile[] }; export const IUserDataProfilesService = createDecorator('IUserDataProfilesService'); @@ -94,9 +97,9 @@ export interface IUserDataProfilesService { readonly profiles: IUserDataProfile[]; newProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags): CustomUserDataProfile; - createProfile(profile: IUserDataProfile, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise; - setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise; - getProfile(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): IUserDataProfile; + createProfile(profile: IUserDataProfile, workspaceIdentifier?: WorkspaceIdentifier): Promise; + setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: WorkspaceIdentifier): Promise; + getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile; removeProfile(profile: IUserDataProfile): Promise; } @@ -163,8 +166,8 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf return { ...profile, isDefault: true, extensionsResource: extensions ? profile.extensionsResource : undefined }; } - createProfile(profile: IUserDataProfile, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise { throw new Error('Not implemented'); } - setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise { throw new Error('Not implemented'); } - getProfile(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): IUserDataProfile { throw new Error('Not implemented'); } + createProfile(profile: IUserDataProfile, workspaceIdentifier?: WorkspaceIdentifier): Promise { throw new Error('Not implemented'); } + setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: WorkspaceIdentifier): Promise { throw new Error('Not implemented'); } + getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile { throw new Error('Not implemented'); } removeProfile(profile: IUserDataProfile): Promise { throw new Error('Not implemented'); } } diff --git a/src/vs/platform/userDataProfile/electron-main/userDataProfile.ts b/src/vs/platform/userDataProfile/electron-main/userDataProfile.ts index b2090d2b62c4f..7073ead9cdac5 100644 --- a/src/vs/platform/userDataProfile/electron-main/userDataProfile.ts +++ b/src/vs/platform/userDataProfile/electron-main/userDataProfile.ts @@ -4,17 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from 'vs/base/common/event'; -import { URI } from 'vs/base/common/uri'; +import { URI, UriComponents } from 'vs/base/common/uri'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IFileService } from 'vs/platform/files/common/files'; import { refineServiceDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateMainService } from 'vs/platform/state/electron-main/state'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; -import { UseDefaultProfileFlags, IUserDataProfile, IUserDataProfilesService, reviveProfile, PROFILES_ENABLEMENT_CONFIG } from 'vs/platform/userDataProfile/common/userDataProfile'; -import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace'; +import { IUserDataProfile, IUserDataProfilesService, reviveProfile, PROFILES_ENABLEMENT_CONFIG, WorkspaceIdentifier } from 'vs/platform/userDataProfile/common/userDataProfile'; import { Promises } from 'vs/base/common/async'; -import { UserDataProfilesService } from 'vs/platform/userDataProfile/node/userDataProfile'; +import { StoredProfileAssociations, StoredUserDataProfile, UserDataProfilesService } from 'vs/platform/userDataProfile/node/userDataProfile'; +import { IStringDictionary } from 'vs/base/common/collections'; export type WillCreateProfileEvent = { profile: IUserDataProfile; @@ -28,22 +28,11 @@ export type WillRemoveProfileEvent = { export const IUserDataProfilesMainService = refineServiceDecorator(IUserDataProfilesService); export interface IUserDataProfilesMainService extends IUserDataProfilesService { - unsetWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise; + unsetWorkspace(workspaceIdentifier: WorkspaceIdentifier): Promise; readonly onWillCreateProfile: Event; readonly onWillRemoveProfile: Event; } -type StoredUserDataProfile = { - name: string; - location: URI; - useDefaultFlags?: UseDefaultProfileFlags; -}; - -type StoredWorkspaceInfo = { - workspace: URI; - profile: URI; -}; - export class UserDataProfilesMainService extends UserDataProfilesService implements IUserDataProfilesMainService { private readonly _onWillCreateProfile = this._register(new Emitter()); @@ -62,7 +51,7 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme super(stateMainService, uriIdentityService, environmentService, fileService, logService); } - override async createProfile(profile: IUserDataProfile, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise { + override async createProfile(profile: IUserDataProfile, workspaceIdentifier?: WorkspaceIdentifier): Promise { if (!this.enabled) { throw new Error(`Settings Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`); } @@ -84,35 +73,32 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme }); await Promises.settled(joiners); - const storedProfile: StoredUserDataProfile = { name: profile.name, location: profile.location, useDefaultFlags: profile.useDefaultFlags }; - const storedProfiles = [...this.getStoredProfiles(), storedProfile]; - this.setStoredProfiles(storedProfiles, [profile], []); + this.updateProfiles([profile], []); + if (workspaceIdentifier) { await this.setProfileForWorkspace(profile, workspaceIdentifier); } - return this.profilesObject.profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, profile.location))!; + + return this.profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, profile.location))!; } - override async setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise { + override async setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: WorkspaceIdentifier): Promise { if (!this.enabled) { throw new Error(`Settings Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`); } + profile = reviveProfile(profile, this.profilesHome.scheme); - const workspace = this.getWorkspace(workspaceIdentifier); - const storedWorkspaceInfos = this.getStoredWorskpaceInfos().filter(info => !this.uriIdentityService.extUri.isEqual(info.workspace, workspace)); - if (!profile.isDefault) { - storedWorkspaceInfos.push({ workspace, profile: profile.location }); - } - this.setStoredWorskpaceInfos(storedWorkspaceInfos); - return this.profilesObject.profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, profile.location))!; + this.updateWorkspaceAssociation(workspaceIdentifier, profile); + + return this.profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, profile.location))!; } - async unsetWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise { + async unsetWorkspace(workspaceIdentifier: WorkspaceIdentifier): Promise { if (!this.enabled) { throw new Error(`Settings Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`); } - const workspace = this.getWorkspace(workspaceIdentifier); - this.setStoredWorskpaceInfos(this.getStoredWorskpaceInfos().filter(info => !this.uriIdentityService.extUri.isEqual(info.workspace, workspace))); + + this.updateWorkspaceAssociation(workspaceIdentifier); } override async removeProfile(profile: IUserDataProfile): Promise { @@ -136,8 +122,17 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme }); await Promises.settled(joiners); - this.setStoredWorskpaceInfos(this.getStoredWorskpaceInfos().filter(p => !this.uriIdentityService.extUri.isEqual(p.profile, profile.location))); - this.setStoredProfiles(this.getStoredProfiles().filter(p => !this.uriIdentityService.extUri.isEqual(p.location, profile.location)), [], [profile]); + if (profile.id === this.profilesObject.emptyWindow?.id) { + this.profilesObject.emptyWindow = undefined; + } + for (const workspace of [...this.profilesObject.workspaces.keys()]) { + if (profile.id === this.profilesObject.workspaces.get(workspace)?.id) { + this.profilesObject.workspaces.delete(workspace); + } + } + this.saveStoredProfileAssociations(); + + this.updateProfiles([], [profile]); try { if (this.profiles.length === 2) { @@ -150,15 +145,62 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme } } - private setStoredProfiles(storedProfiles: StoredUserDataProfile[], added: IUserDataProfile[], removed: IUserDataProfile[]): void { + private updateProfiles(added: IUserDataProfile[], removed: IUserDataProfile[]) { + const storedProfiles: StoredUserDataProfile[] = []; + for (const profile of [...this.profilesObject.profiles, ...added]) { + if (profile.isDefault) { + continue; + } + if (removed.some(p => profile.id === p.id)) { + continue; + } + storedProfiles.push({ location: profile.location, name: profile.name, useDefaultFlags: profile.useDefaultFlags }); + } this.stateMainService.setItem(UserDataProfilesMainService.PROFILES_KEY, storedProfiles); this._profilesObject = undefined; this._onDidChangeProfiles.fire({ added, removed, all: this.profiles }); } - private setStoredWorskpaceInfos(storedWorkspaceInfos: StoredWorkspaceInfo[]) { - this.stateMainService.setItem(UserDataProfilesMainService.WORKSPACE_PROFILE_INFO_KEY, storedWorkspaceInfos); + private updateWorkspaceAssociation(workspaceIdentifier: WorkspaceIdentifier, newProfile?: IUserDataProfile) { + const workspace = this.getWorkspace(workspaceIdentifier); + + // Folder or Multiroot workspace + if (URI.isUri(workspace)) { + this.profilesObject.workspaces.delete(workspace); + if (newProfile && !newProfile.isDefault) { + this.profilesObject.workspaces.set(workspace, newProfile); + } + } + // Empty Window + else { + this.profilesObject.emptyWindow = !newProfile?.isDefault ? newProfile : undefined; + } + + this.saveStoredProfileAssociations(); + } + + private saveStoredProfileAssociations() { + const workspaces: IStringDictionary = {}; + for (const [workspace, profile] of this.profilesObject.workspaces.entries()) { + workspaces[workspace.toString()] = profile.location.toString(); + } + const emptyWindow = this.profilesObject.emptyWindow?.location.toString(); + this.stateMainService.setItem(UserDataProfilesMainService.PROFILE_ASSOCIATIONS_KEY, { workspaces, emptyWindow }); this._profilesObject = undefined; } + protected override getStoredProfileAssociations(): StoredProfileAssociations { + const oldKey = 'workspaceAndProfileInfo'; + const storedWorkspaceInfos = this.stateMainService.getItem<{ workspace: UriComponents; profile: UriComponents }[]>(oldKey, undefined); + if (storedWorkspaceInfos) { + this.stateMainService.removeItem(oldKey); + const workspaces = storedWorkspaceInfos.reduce>((result, { workspace, profile }) => { + result[URI.revive(workspace).toString()] = URI.revive(profile).toString(); + return result; + }, {}); + this.stateMainService.setItem(UserDataProfilesMainService.PROFILE_ASSOCIATIONS_KEY, { workspaces }); + } + return super.getStoredProfileAssociations(); + } + } diff --git a/src/vs/platform/userDataProfile/node/userDataProfile.ts b/src/vs/platform/userDataProfile/node/userDataProfile.ts index 1a7f69d3290c7..a7b7c247891cc 100644 --- a/src/vs/platform/userDataProfile/node/userDataProfile.ts +++ b/src/vs/platform/userDataProfile/node/userDataProfile.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { IStringDictionary } from 'vs/base/common/collections'; import { ResourceMap } from 'vs/base/common/map'; import { revive } from 'vs/base/common/marshalling'; import { UriDto } from 'vs/base/common/types'; @@ -12,29 +13,30 @@ import { IFileService } from 'vs/platform/files/common/files'; import { ILogService } from 'vs/platform/log/common/log'; import { IStateService } from 'vs/platform/state/node/state'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; -import { UseDefaultProfileFlags, IUserDataProfile, IUserDataProfilesService, UserDataProfilesService as BaseUserDataProfilesService, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile'; -import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace'; +import { UseDefaultProfileFlags, IUserDataProfile, IUserDataProfilesService, UserDataProfilesService as BaseUserDataProfilesService, toUserDataProfile, WorkspaceIdentifier, EmptyWindowWorkspaceIdentifier } from 'vs/platform/userDataProfile/common/userDataProfile'; +import { isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace'; -type UserDataProfilesObject = { +export type UserDataProfilesObject = { profiles: IUserDataProfile[]; workspaces: ResourceMap; + emptyWindow?: IUserDataProfile; }; -type StoredUserDataProfile = { +export type StoredUserDataProfile = { name: string; location: URI; useDefaultFlags?: UseDefaultProfileFlags; }; -type StoredWorkspaceInfo = { - workspace: URI; - profile: URI; +export type StoredProfileAssociations = { + workspaces?: IStringDictionary; + emptyWindow?: string; }; export class UserDataProfilesService extends BaseUserDataProfilesService implements IUserDataProfilesService { protected static readonly PROFILES_KEY = 'userDataProfiles'; - protected static readonly WORKSPACE_PROFILE_INFO_KEY = 'workspaceAndProfileInfo'; + protected static readonly PROFILE_ASSOCIATIONS_KEY = 'profileAssociations'; protected enabled: boolean = false; @@ -60,37 +62,55 @@ export class UserDataProfilesService extends BaseUserDataProfilesService impleme } if (!this._profilesObject) { const profiles = this.getStoredProfiles().map(storedProfile => toUserDataProfile(storedProfile.name, storedProfile.location, storedProfile.useDefaultFlags)); + let emptyWindow: IUserDataProfile | undefined; const workspaces = new ResourceMap(); if (profiles.length) { profiles.unshift(this.createDefaultUserDataProfile(true)); - for (const workspaceProfileInfo of this.getStoredWorskpaceInfos()) { - const profile = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, workspaceProfileInfo.profile)); - if (profile) { - workspaces.set(workspaceProfileInfo.workspace, profile); + const profileAssicaitions = this.getStoredProfileAssociations(); + if (profileAssicaitions.workspaces) { + for (const [workspacePath, profilePath] of Object.entries(profileAssicaitions.workspaces)) { + const workspace = URI.parse(workspacePath); + const profileLocation = URI.parse(profilePath); + const profile = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, profileLocation)); + if (profile) { + workspaces.set(workspace, profile); + } } } + if (profileAssicaitions.emptyWindow) { + const emptyWindowProfileLocation = URI.parse(profileAssicaitions.emptyWindow); + emptyWindow = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, emptyWindowProfileLocation)); + } } - this._profilesObject = { profiles, workspaces }; + this._profilesObject = { profiles, workspaces, emptyWindow }; } return this._profilesObject; } override get profiles(): IUserDataProfile[] { return this.profilesObject.profiles; } - override getProfile(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): IUserDataProfile { - return this.profilesObject.workspaces.get(this.getWorkspace(workspaceIdentifier)) ?? this.defaultProfile; + override getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile { + const workspace = this.getWorkspace(workspaceIdentifier); + const profile = URI.isUri(workspace) ? this.profilesObject.workspaces.get(workspace) : this.profilesObject.emptyWindow; + return profile ?? this.defaultProfile; } - protected getWorkspace(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier) { - return isSingleFolderWorkspaceIdentifier(workspaceIdentifier) ? workspaceIdentifier.uri : workspaceIdentifier.configPath; + protected getWorkspace(workspaceIdentifier: WorkspaceIdentifier): URI | EmptyWindowWorkspaceIdentifier { + if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier)) { + return workspaceIdentifier.uri; + } + if (isWorkspaceIdentifier(workspaceIdentifier)) { + return workspaceIdentifier.configPath; + } + return 'empty-window'; } protected getStoredProfiles(): StoredUserDataProfile[] { return revive(this.stateService.getItem[]>(UserDataProfilesService.PROFILES_KEY, [])); } - protected getStoredWorskpaceInfos(): StoredWorkspaceInfo[] { - return revive(this.stateService.getItem[]>(UserDataProfilesService.WORKSPACE_PROFILE_INFO_KEY, [])); + protected getStoredProfileAssociations(): StoredProfileAssociations { + return revive(this.stateService.getItem>(UserDataProfilesService.PROFILE_ASSOCIATIONS_KEY, {})); } } diff --git a/src/vs/platform/windows/electron-main/window.ts b/src/vs/platform/windows/electron-main/window.ts index 02524b2235bf5..63f0629345e21 100644 --- a/src/vs/platform/windows/electron-main/window.ts +++ b/src/vs/platform/windows/electron-main/window.ts @@ -906,7 +906,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { configuration.editSessionId = this.environmentMainService.editSessionId; // set latest edit session id configuration.profiles = { all: this.userDataProfilesService.profiles, - current: configuration.workspace ? this.userDataProfilesService.getProfile(configuration.workspace) : this.userDataProfilesService.defaultProfile, + current: this.userDataProfilesService.getProfile(configuration.workspace ?? 'empty-window'), }; // Load config diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 37cd6b32c6862..0d2cdc09834b4 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -1302,7 +1302,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic profiles: { all: this.userDataProfilesService.profiles, - current: options.workspace ? this.userDataProfilesService.getProfile(options.workspace) : this.userDataProfilesService.defaultProfile, + current: this.userDataProfilesService.getProfile(options.workspace ?? 'empty-window'), }, homeDir: this.environmentMainService.userHome.fsPath, diff --git a/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts b/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts index d2732a121386d..ad74379416584 100644 --- a/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts +++ b/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts @@ -13,8 +13,7 @@ import { ContextKeyExpr, IContextKey, IContextKeyService, RawContextKey } from ' import { registerColor } from 'vs/platform/theme/common/colorRegistry'; import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar'; import { IUserDataProfileManagementService, IUserDataProfileService, ManageProfilesSubMenu, PROFILES_CATEGORY, PROFILES_ENABLEMENT_CONTEXT, PROFILES_TTILE } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; @@ -54,26 +53,25 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements private registerManageProfilesSubMenu(): void { const that = this; - const when = ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')); MenuRegistry.appendMenuItem(MenuId.GlobalActivity, { get title() { return localize('manageProfiles', "{0} ({1})", PROFILES_TTILE.value, that.userDataProfileService.currentProfile.name); }, submenu: ManageProfilesSubMenu, group: '5_profiles', - when, + when: PROFILES_ENABLEMENT_CONTEXT, order: 3 }); MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, { title: PROFILES_TTILE, submenu: ManageProfilesSubMenu, group: '5_profiles', - when, + when: PROFILES_ENABLEMENT_CONTEXT, order: 3 }); MenuRegistry.appendMenuItem(MenuId.AccountsContext, { get title() { return localize('manageProfiles', "{0} ({1})", PROFILES_TTILE.value, that.userDataProfileService.currentProfile.name); }, submenu: ManageProfilesSubMenu, group: '1_profiles', - when, + when: PROFILES_ENABLEMENT_CONTEXT, }); } @@ -89,7 +87,6 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements const that = this; return registerAction2(class ProfileEntryAction extends Action2 { constructor() { - const when = ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')); super({ id: `workbench.profiles.actions.profileEntry.${profile.id}`, title: profile.name, @@ -99,7 +96,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements { id: ManageProfilesSubMenu, group: '0_profiles', - when, + when: PROFILES_ENABLEMENT_CONTEXT, } ] }); @@ -112,7 +109,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements private profileStatusAccessor: IStatusbarEntryAccessor | undefined; private updateStatus(): void { - if (this.userDataProfilesService.profiles.length && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) { + if (this.userDataProfilesService.profiles.length) { const statusBarEntry: IStatusbarEntry = { name: PROFILES_CATEGORY, command: 'workbench.profiles.actions.switchProfile', diff --git a/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts b/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts index 4f9f2ca232872..2761f24f87fe4 100644 --- a/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts +++ b/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts @@ -17,14 +17,11 @@ import { asJson, asText, IRequestService } from 'vs/platform/request/common/requ import { IUserDataProfileTemplate, isUserDataProfileTemplate, IUserDataProfileManagementService, IUserDataProfileWorkbenchService, PROFILES_CATEGORY, PROFILE_EXTENSION, PROFILE_FILTER, ManageProfilesSubMenu, IUserDataProfileService, PROFILES_ENABLEMENT_CONTEXT } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys'; import { CATEGORIES } from 'vs/workbench/common/actions'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; registerAction2(class CreateFromCurrentProfileAction extends Action2 { constructor() { - const when = ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')); super({ id: 'workbench.profiles.actions.createFromCurrentProfile', title: { @@ -33,12 +30,12 @@ registerAction2(class CreateFromCurrentProfileAction extends Action2 { }, category: PROFILES_CATEGORY, f1: true, - precondition: when, + precondition: PROFILES_ENABLEMENT_CONTEXT, menu: [ { id: ManageProfilesSubMenu, group: '1_create_profiles', - when, + when: PROFILES_ENABLEMENT_CONTEXT, order: 1 } ] @@ -60,7 +57,6 @@ registerAction2(class CreateFromCurrentProfileAction extends Action2 { registerAction2(class CreateEmptyProfileAction extends Action2 { constructor() { - const when = ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')); super({ id: 'workbench.profiles.actions.createProfile', title: { @@ -69,12 +65,12 @@ registerAction2(class CreateEmptyProfileAction extends Action2 { }, category: PROFILES_CATEGORY, f1: true, - precondition: when, + precondition: PROFILES_ENABLEMENT_CONTEXT, menu: [ { id: ManageProfilesSubMenu, group: '1_create_profiles', - when, + when: PROFILES_ENABLEMENT_CONTEXT, order: 2 } ] @@ -96,7 +92,6 @@ registerAction2(class CreateEmptyProfileAction extends Action2 { registerAction2(class RemoveProfileAction extends Action2 { constructor() { - const when = ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')); super({ id: 'workbench.profiles.actions.removeProfile', title: { @@ -105,12 +100,12 @@ registerAction2(class RemoveProfileAction extends Action2 { }, category: PROFILES_CATEGORY, f1: true, - precondition: when, + precondition: PROFILES_ENABLEMENT_CONTEXT, menu: [ { id: ManageProfilesSubMenu, group: '2_manage_profiles', - when + when: PROFILES_ENABLEMENT_CONTEXT } ] }); @@ -142,7 +137,7 @@ registerAction2(class SwitchProfileAction extends Action2 { }, category: PROFILES_CATEGORY, f1: true, - precondition: ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')), + precondition: PROFILES_ENABLEMENT_CONTEXT, }); } @@ -202,7 +197,7 @@ registerAction2(class ExportProfileAction extends Action2 { }, category: PROFILES_CATEGORY, f1: true, - precondition: ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')), + precondition: PROFILES_ENABLEMENT_CONTEXT, }); } @@ -239,7 +234,7 @@ registerAction2(class ImportProfileAction extends Action2 { }, category: PROFILES_CATEGORY, f1: true, - precondition: ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, WorkbenchStateContext.notEqualsTo('empty')), + precondition: PROFILES_ENABLEMENT_CONTEXT, }); } diff --git a/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts b/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts index 470a3e571686a..614be3e29446f 100644 --- a/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts +++ b/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts @@ -16,8 +16,8 @@ import { IFileService } from 'vs/platform/files/common/files'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ILogService } from 'vs/platform/log/common/log'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; -import { EXTENSIONS_RESOURCE_NAME, IUserDataProfile, IUserDataProfilesService, UseDefaultProfileFlags } from 'vs/platform/userDataProfile/common/userDataProfile'; -import { ISingleFolderWorkspaceIdentifier, IWorkspaceContextService, IWorkspaceIdentifier, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { EXTENSIONS_RESOURCE_NAME, IUserDataProfile, IUserDataProfilesService, UseDefaultProfileFlags, WorkspaceIdentifier } from 'vs/platform/userDataProfile/common/userDataProfile'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IExtensionManagementServerService, IWorkbenchExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -58,9 +58,6 @@ export class UserDataProfileManagementService extends Disposable implements IUse async createAndEnterProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags, fromExisting?: boolean): Promise { const workspaceIdentifier = this.getWorkspaceIdentifier(); - if (!workspaceIdentifier) { - throw new Error(localize('cannotCreateProfileInEmptyWorkbench', "Cannot create a profile in an empty workspace")); - } const promises: Promise[] = []; const newProfile = this.userDataProfilesService.newProfile(name, useDefaultFlags); await this.fileService.createFolder(newProfile.location); @@ -98,9 +95,6 @@ export class UserDataProfileManagementService extends Disposable implements IUse async switchProfile(profile: IUserDataProfile): Promise { const workspaceIdentifier = this.getWorkspaceIdentifier(); - if (!workspaceIdentifier) { - throw new Error(localize('cannotSwitchProfileInEmptyWorkbench', "Cannot switch a profile in an empty workspace")); - } if (!this.userDataProfilesService.profiles.some(p => p.id === profile.id)) { throw new Error(`Profile ${profile.name} does not exist`); } @@ -113,9 +107,6 @@ export class UserDataProfileManagementService extends Disposable implements IUse async createAndEnterProfileFromTemplate(name: string, template: IUserDataProfileTemplate, useDefaultFlags: UseDefaultProfileFlags): Promise { const workspaceIdentifier = this.getWorkspaceIdentifier(); - if (!workspaceIdentifier) { - throw new Error(localize('cannotCreateProfileInEmptyWorkbench', "Cannot create a profile in an empty workspace")); - } const profile = await this.progressService.withProgress({ location: ProgressLocation.Notification, title: localize('profiles.creating', "{0}: Creating...", PROFILES_CATEGORY), @@ -138,7 +129,7 @@ export class UserDataProfileManagementService extends Disposable implements IUse await this.enterProfile(profile, false); } - private getWorkspaceIdentifier(): ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier | undefined { + private getWorkspaceIdentifier(): WorkspaceIdentifier { const workspace = this.workspaceContextService.getWorkspace(); switch (this.workspaceContextService.getWorkbenchState()) { case WorkbenchState.FOLDER: @@ -146,7 +137,7 @@ export class UserDataProfileManagementService extends Disposable implements IUse case WorkbenchState.WORKSPACE: return { configPath: workspace.configuration!, id: workspace.id }; } - return undefined; + return 'empty-window'; } private async enterProfile(profile: IUserDataProfile, preserveData: boolean): Promise {