From d902fec1d2e50ee4c9ec3db109dd54d6aec8a18c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 22 Jul 2022 15:42:52 +0200 Subject: [PATCH] Enhance settings profiles management (#155966) * fix #154178 * - Support renaming profile - Refactor profile actions * fix compilation * fix label --- .../contrib/extensionsCleaner.ts | 2 +- .../browser/userDataProfile.ts | 13 +- .../userDataProfile/common/userDataProfile.ts | 37 ++- .../electron-sandbox/userDataProfile.ts | 8 +- .../browser/userDataProfile.ts | 2 +- .../common/userDataProfileActions.ts | 218 +++++++++++++----- .../browser/userDataProfileManagement.ts | 10 + .../userDataProfile/common/userDataProfile.ts | 2 + .../common/userDataProfileService.ts | 12 +- .../test/browser/workbenchTestServices.ts | 1 + 10 files changed, 228 insertions(+), 77 deletions(-) diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/extensionsCleaner.ts b/src/vs/code/electron-browser/sharedProcess/contrib/extensionsCleaner.ts index 0116d6e8aa8..3de8633f588 100644 --- a/src/vs/code/electron-browser/sharedProcess/contrib/extensionsCleaner.ts +++ b/src/vs/code/electron-browser/sharedProcess/contrib/extensionsCleaner.ts @@ -59,7 +59,7 @@ class ProfileExtensionsCleaner extends Disposable { this.onDidChangeProfiles({ added: this.userDataProfilesService.profiles, removed: [], all: this.userDataProfilesService.profiles }); } - private async onDidChangeProfiles({ added, removed, all }: DidChangeProfilesEvent): Promise { + private async onDidChangeProfiles({ added, removed, all }: Omit): Promise { try { await Promise.all(removed.map(profile => profile.extensionsResource ? this.removeExtensionsFromProfile(profile.extensionsResource) : Promise.resolve())); } catch (error) { diff --git a/src/vs/platform/userDataProfile/browser/userDataProfile.ts b/src/vs/platform/userDataProfile/browser/userDataProfile.ts index b00f89a92b7..782a627770f 100644 --- a/src/vs/platform/userDataProfile/browser/userDataProfile.ts +++ b/src/vs/platform/userDataProfile/browser/userDataProfile.ts @@ -31,7 +31,12 @@ export class BrowserUserDataProfilesService extends UserDataProfilesService impl this._register(this.changesBroadcastChannel.onDidReceiveData(changes => { try { this._profilesObject = undefined; - this._onDidChangeProfiles.fire({ added: changes.added.map(p => reviveProfile(p, this.profilesHome.scheme)), removed: changes.removed.map(p => reviveProfile(p, this.profilesHome.scheme)), all: this.profiles }); + this._onDidChangeProfiles.fire({ + added: changes.added.map(p => reviveProfile(p, this.profilesHome.scheme)), + removed: changes.removed.map(p => reviveProfile(p, this.profilesHome.scheme)), + updated: changes.updated.map(p => reviveProfile(p, this.profilesHome.scheme)), + all: this.profiles + }); } catch (error) {/* ignore */ } })); } @@ -54,9 +59,9 @@ export class BrowserUserDataProfilesService extends UserDataProfilesService impl return []; } - protected override triggerProfilesChanges(added: IUserDataProfile[], removed: IUserDataProfile[]) { - super.triggerProfilesChanges(added, removed); - this.changesBroadcastChannel.postData({ added, removed }); + protected override triggerProfilesChanges(added: IUserDataProfile[], removed: IUserDataProfile[], updated: IUserDataProfile[]) { + super.triggerProfilesChanges(added, removed, updated); + this.changesBroadcastChannel.postData({ added, removed, updated }); } protected override saveStoredProfiles(storedProfiles: StoredUserDataProfile[]): void { diff --git a/src/vs/platform/userDataProfile/common/userDataProfile.ts b/src/vs/platform/userDataProfile/common/userDataProfile.ts index 3bc2eb4ea3d..3d0c1ba1b4c 100644 --- a/src/vs/platform/userDataProfile/common/userDataProfile.ts +++ b/src/vs/platform/userDataProfile/common/userDataProfile.ts @@ -19,6 +19,7 @@ import { ResourceMap } from 'vs/base/common/map'; import { IStringDictionary } from 'vs/base/common/collections'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { Promises } from 'vs/base/common/async'; +import { generateUuid } from 'vs/base/common/uuid'; /** * Flags to indicate whether to use the default profile or not. @@ -68,7 +69,7 @@ export const PROFILES_ENABLEMENT_CONFIG = 'workbench.experimental.settingsProfil export type EmptyWindowWorkspaceIdentifier = 'empty-window'; export type WorkspaceIdentifier = ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier | EmptyWindowWorkspaceIdentifier; -export type DidChangeProfilesEvent = { readonly added: IUserDataProfile[]; readonly removed: IUserDataProfile[]; readonly all: IUserDataProfile[] }; +export type DidChangeProfilesEvent = { readonly added: IUserDataProfile[]; readonly removed: IUserDataProfile[]; readonly updated: IUserDataProfile[]; readonly all: IUserDataProfile[] }; export type WillCreateProfileEvent = { profile: IUserDataProfile; @@ -91,6 +92,7 @@ export interface IUserDataProfilesService { readonly profiles: IUserDataProfile[]; createProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags, workspaceIdentifier?: WorkspaceIdentifier): Promise; + updateProfile(profile: IUserDataProfile, name: string, useDefaultFlags?: UseDefaultProfileFlags): Promise; setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: WorkspaceIdentifier): Promise; getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile; removeProfile(profile: IUserDataProfile): Promise; @@ -240,7 +242,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf throw new Error(`Profile with name ${name} already exists`); } - const profile = toUserDataProfile(name, joinPath(this.profilesHome, hash(name).toString(16)), useDefaultFlags); + const profile = toUserDataProfile(name, joinPath(this.profilesHome, hash(generateUuid()).toString(16)), useDefaultFlags); await this.fileService.createFolder(profile.location); const joiners: Promise[] = []; @@ -252,7 +254,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf }); await Promises.settled(joiners); - this.updateProfiles([profile], []); + this.updateProfiles([profile], [], []); if (workspaceIdentifier) { await this.setProfileForWorkspace(profile, workspaceIdentifier); @@ -261,6 +263,22 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf return profile; } + async updateProfile(profileToUpdate: IUserDataProfile, name: string, useDefaultFlags?: UseDefaultProfileFlags): Promise { + if (!this.enabled) { + throw new Error(`Settings Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`); + } + + let profile = this.profiles.find(p => p.id === profileToUpdate.id); + if (!profile) { + throw new Error(`Profile '${profileToUpdate.name}' does not exist`); + } + + profile = toUserDataProfile(name, profile.location, useDefaultFlags); + this.updateProfiles([], [], [profile]); + + return profile; + } + async setProfileForWorkspace(profileToSet: IUserDataProfile, workspaceIdentifier: WorkspaceIdentifier): Promise { if (!this.enabled) { throw new Error(`Settings Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`); @@ -312,7 +330,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf } this.updateStoredProfileAssociations(); - this.updateProfiles([], [profile]); + this.updateProfiles([], [profile], []); try { if (this.profiles.length === 1) { @@ -325,24 +343,25 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf } } - private updateProfiles(added: IUserDataProfile[], removed: IUserDataProfile[]) { + private updateProfiles(added: IUserDataProfile[], removed: IUserDataProfile[], updated: IUserDataProfile[]) { const storedProfiles: StoredUserDataProfile[] = []; - for (const profile of [...this.profilesObject.profiles, ...added]) { + for (let profile of [...this.profilesObject.profiles, ...added]) { if (profile.isDefault) { continue; } if (removed.some(p => profile.id === p.id)) { continue; } + profile = updated.find(p => profile.id === p.id) ?? profile; storedProfiles.push({ location: profile.location, name: profile.name, useDefaultFlags: profile.useDefaultFlags }); } this.saveStoredProfiles(storedProfiles); this._profilesObject = undefined; - this.triggerProfilesChanges(added, removed); + this.triggerProfilesChanges(added, removed, updated); } - protected triggerProfilesChanges(added: IUserDataProfile[], removed: IUserDataProfile[]) { - this._onDidChangeProfiles.fire({ added, removed, all: this.profiles }); + protected triggerProfilesChanges(added: IUserDataProfile[], removed: IUserDataProfile[], updated: IUserDataProfile[]) { + this._onDidChangeProfiles.fire({ added, removed, updated, all: this.profiles }); } private updateWorkspaceAssociation(workspaceIdentifier: WorkspaceIdentifier, newProfile?: IUserDataProfile) { diff --git a/src/vs/platform/userDataProfile/electron-sandbox/userDataProfile.ts b/src/vs/platform/userDataProfile/electron-sandbox/userDataProfile.ts index 085e035b676..eb662f36339 100644 --- a/src/vs/platform/userDataProfile/electron-sandbox/userDataProfile.ts +++ b/src/vs/platform/userDataProfile/electron-sandbox/userDataProfile.ts @@ -41,8 +41,9 @@ export class UserDataProfilesNativeService extends Disposable implements IUserDa this._register(this.channel.listen('onDidChangeProfiles')(e => { const added = e.added.map(profile => reviveProfile(profile, this.profilesHome.scheme)); const removed = e.removed.map(profile => reviveProfile(profile, this.profilesHome.scheme)); + const updated = e.updated.map(profile => reviveProfile(profile, this.profilesHome.scheme)); this._profiles = e.all.map(profile => reviveProfile(profile, this.profilesHome.scheme)); - this._onDidChangeProfiles.fire({ added, removed, all: this.profiles }); + this._onDidChangeProfiles.fire({ added, removed, updated, all: this.profiles }); })); } @@ -59,6 +60,11 @@ export class UserDataProfilesNativeService extends Disposable implements IUserDa return this.channel.call('removeProfile', [profile]); } + async updateProfile(profile: IUserDataProfile, name: string, useDefaultFlags?: UseDefaultProfileFlags): Promise { + const result = await this.channel.call>('updateProfile', [profile, name, useDefaultFlags]); + return reviveProfile(result, this.profilesHome.scheme); + } + getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile { throw new Error('Not implemented'); } } diff --git a/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts b/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts index 1a9933261f6..324069eb10a 100644 --- a/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts +++ b/src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts @@ -52,7 +52,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements this._register(this.userDataProfilesService.onDidChangeProfiles(e => this.hasProfilesContext.set(this.userDataProfilesService.profiles.length > 1))); this.updateStatus(); - this._register(Event.any(this.workspaceContextService.onDidChangeWorkbenchState, this.userDataProfileService.onDidChangeCurrentProfile, this.userDataProfilesService.onDidChangeProfiles)(() => this.updateStatus())); + this._register(Event.any(this.workspaceContextService.onDidChangeWorkbenchState, this.userDataProfileService.onDidChangeCurrentProfile, this.userDataProfileService.onDidUpdateCurrentProfile, this.userDataProfilesService.onDidChangeProfiles)(() => this.updateStatus())); this.registerActions(); } diff --git a/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts b/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts index 80e2c378893..f1d27222b50 100644 --- a/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts +++ b/src/vs/workbench/contrib/userDataProfile/common/userDataProfileActions.ts @@ -20,14 +20,85 @@ import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userData import { CATEGORIES } from 'vs/workbench/common/actions'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ICommandService } from 'vs/platform/commands/common/commands'; -registerAction2(class CreateFromCurrentProfileAction extends Action2 { +class CreateFromCurrentProfileAction extends Action2 { + static readonly ID = 'workbench.profiles.actions.createFromCurrentProfile'; + static readonly TITLE = { + value: localize('save profile as', "Create from Current Settings Profile..."), + original: 'Create from Current Profile...' + }; constructor() { super({ - id: 'workbench.profiles.actions.createFromCurrentProfile', + 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 name = await quickInputService.input({ + placeHolder: localize('name', "Profile name"), + title: localize('save profile as', "Create from Current Settings Profile..."), + }); + 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 Settings Profile..."), + original: 'Create an Empty Settings 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 name = await quickInputService.input({ + placeHolder: localize('name', "Profile name"), + title: localize('create and enter empty profile', "Create an Empty Profile..."), + }); + if (name) { + try { + await userDataProfileManagementService.createAndEnterProfile(name); + } catch (error) { + notificationService.error(error); + } + } + } +} +registerAction2(CreateEmptyProfileAction); + +registerAction2(class CreateProfileAction extends Action2 { + constructor() { + super({ + id: 'workbench.profiles.actions.createProfile', title: { - value: localize('save profile as', "Create from Current Settings Profile..."), - original: 'Create from Current Profile...' + value: localize('create profile', "Create..."), + original: 'Create...' }, category: PROFILES_CATEGORY, f1: true, @@ -35,7 +106,7 @@ registerAction2(class CreateFromCurrentProfileAction extends Action2 { menu: [ { id: ManageProfilesSubMenu, - group: '1_create_profiles', + group: '2_manage_profiles', when: PROFILES_ENABLEMENT_CONTEXT, order: 1 } @@ -45,59 +116,28 @@ registerAction2(class CreateFromCurrentProfileAction extends Action2 { async run(accessor: ServicesAccessor) { const quickInputService = accessor.get(IQuickInputService); - const userDataProfileManagementService = accessor.get(IUserDataProfileManagementService); - const name = await quickInputService.input({ - placeHolder: localize('name', "Profile name"), - title: localize('save profile as', "Create from Current Settings Profile..."), - }); - if (name) { - await userDataProfileManagementService.createAndEnterProfile(name, undefined, true); + const commandService = accessor.get(ICommandService); + const pick = await quickInputService.pick( + [{ + id: CreateFromCurrentProfileAction.ID, + label: CreateFromCurrentProfileAction.TITLE.value, + }, { + id: CreateEmptyProfileAction.ID, + label: CreateEmptyProfileAction.TITLE.value, + }], { canPickMany: false, title: localize('create settings profile', "{0}: Create...", PROFILES_CATEGORY) }); + if (pick) { + return commandService.executeCommand(pick.id); } } }); -registerAction2(class CreateEmptyProfileAction extends Action2 { +registerAction2(class RenameProfileAction extends Action2 { constructor() { super({ - id: 'workbench.profiles.actions.createProfile', + id: 'workbench.profiles.actions.renameProfile', title: { - value: localize('create profile', "Create an Empty Settings Profile..."), - original: 'Create an Empty Profile...' - }, - category: PROFILES_CATEGORY, - f1: true, - precondition: PROFILES_ENABLEMENT_CONTEXT, - menu: [ - { - id: ManageProfilesSubMenu, - group: '1_create_profiles', - when: PROFILES_ENABLEMENT_CONTEXT, - order: 2 - } - ] - }); - } - - async run(accessor: ServicesAccessor) { - const quickInputService = accessor.get(IQuickInputService); - const userDataProfileManagementService = accessor.get(IUserDataProfileManagementService); - const name = await quickInputService.input({ - placeHolder: localize('name', "Profile name"), - title: localize('create and enter empty profile', "Create an Empty Profile..."), - }); - if (name) { - await userDataProfileManagementService.createAndEnterProfile(name); - } - } -}); - -registerAction2(class RemoveProfileAction extends Action2 { - constructor() { - super({ - id: 'workbench.profiles.actions.removeProfile', - title: { - value: localize('remove profile', "Remove Settings Profile..."), - original: 'Remove Profile...' + value: localize('rename profile', "Rename..."), + original: 'Rename...' }, category: PROFILES_CATEGORY, f1: true, @@ -106,7 +146,65 @@ registerAction2(class RemoveProfileAction extends Action2 { { id: ManageProfilesSubMenu, group: '2_manage_profiles', - when: PROFILES_ENABLEMENT_CONTEXT + when: PROFILES_ENABLEMENT_CONTEXT, + order: 1 + } + ] + }); + } + + async run(accessor: ServicesAccessor) { + const quickInputService = accessor.get(IQuickInputService); + const userDataProfileService = accessor.get(IUserDataProfileService); + const userDataProfilesService = accessor.get(IUserDataProfilesService); + const userDataProfileManagementService = accessor.get(IUserDataProfileManagementService); + const notificationService = accessor.get(INotificationService); + + const profiles = userDataProfilesService.profiles.filter(p => !p.isDefault); + if (profiles.length) { + const pick = await quickInputService.pick( + profiles.map(profile => ({ + label: profile.name, + description: profile.id === userDataProfileService.currentProfile.id ? localize('current', "Current") : undefined, + profile + })), + { + placeHolder: localize('pick profile to rename', "Select Settings Profile to Rename"), + }); + if (pick) { + const name = await quickInputService.input({ + value: pick.profile.name, + title: localize('edit settings profile', "Rename Settings Profile..."), + }); + if (name && name !== pick.profile.name) { + try { + await userDataProfileManagementService.renameProfile(pick.profile, name); + } catch (error) { + notificationService.error(error); + } + } + } + } + } +}); + +registerAction2(class DeleteProfileAction extends Action2 { + constructor() { + super({ + id: 'workbench.profiles.actions.deleteProfile', + title: { + value: localize('delete profile', "Delete..."), + original: 'Delete...' + }, + category: PROFILES_CATEGORY, + f1: true, + precondition: ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, HAS_PROFILES_CONTEXT), + menu: [ + { + id: ManageProfilesSubMenu, + group: '2_manage_profiles', + when: PROFILES_ENABLEMENT_CONTEXT, + order: 2 } ] }); @@ -128,7 +226,7 @@ registerAction2(class RemoveProfileAction extends Action2 { profile })), { - placeHolder: localize('pick profile', "Select Settings Profile"), + placeHolder: localize('pick profile to delete', "Select Settings Profiles to Delete"), canPickMany: true }); if (picks) { @@ -147,12 +245,12 @@ registerAction2(class SwitchProfileAction extends Action2 { super({ id: 'workbench.profiles.actions.switchProfile', title: { - value: localize('switch profile', "Switch Settings Profile..."), - original: 'Switch Settings Profile...' + value: localize('switch profile', "Switch..."), + original: 'Switch...' }, category: PROFILES_CATEGORY, f1: true, - precondition: PROFILES_ENABLEMENT_CONTEXT, + precondition: ContextKeyExpr.and(PROFILES_ENABLEMENT_CONTEXT, HAS_PROFILES_CONTEXT), }); } @@ -207,8 +305,8 @@ registerAction2(class ExportProfileAction extends Action2 { super({ id: 'workbench.profiles.actions.exportProfile', title: { - value: localize('export profile', "Export Settings Profile..."), - original: 'Export Settings Profile...' + value: localize('export profile', "Export..."), + original: 'Export...' }, category: PROFILES_CATEGORY, menu: [ @@ -252,8 +350,8 @@ registerAction2(class ImportProfileAction extends Action2 { super({ id: 'workbench.profiles.actions.importProfile', title: { - value: localize('import profile', "Import Settings Profile..."), - original: 'Import Settings Profile...' + value: localize('import profile', "Import..."), + original: 'Import...' }, category: PROFILES_CATEGORY, menu: [ diff --git a/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts b/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts index ce1983fec64..5fab982a11c 100644 --- a/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts +++ b/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.ts @@ -43,6 +43,16 @@ export class UserDataProfileManagementService extends Disposable implements IUse return profile; } + async renameProfile(profile: IUserDataProfile, name: string): Promise { + if (!this.userDataProfilesService.profiles.some(p => p.id === profile.id)) { + throw new Error(`Settings profile ${profile.name} does not exist`); + } + if (profile.isDefault) { + throw new Error(localize('cannotRenameDefaultProfile', "Cannot rename the default settings profile")); + } + await this.userDataProfilesService.updateProfile(profile, name); + } + async removeProfile(profile: IUserDataProfile): Promise { if (!this.userDataProfilesService.profiles.some(p => p.id === profile.id)) { throw new Error(`Settings profile ${profile.name} does not exist`); diff --git a/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts b/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts index 3db887030d9..054bf392034 100644 --- a/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts +++ b/src/vs/workbench/services/userDataProfile/common/userDataProfile.ts @@ -22,6 +22,7 @@ export interface DidChangeUserDataProfileEvent { export const IUserDataProfileService = createDecorator('IUserDataProfileService'); export interface IUserDataProfileService { readonly _serviceBrand: undefined; + readonly onDidUpdateCurrentProfile: Event; readonly onDidChangeCurrentProfile: Event; readonly currentProfile: IUserDataProfile; updateCurrentProfile(currentProfile: IUserDataProfile, preserveData: boolean): Promise; @@ -33,6 +34,7 @@ export interface IUserDataProfileManagementService { createAndEnterProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags, fromExisting?: boolean): Promise; removeProfile(profile: IUserDataProfile): Promise; + renameProfile(profile: IUserDataProfile, name: string): Promise; switchProfile(profile: IUserDataProfile): Promise; } diff --git a/src/vs/workbench/services/userDataProfile/common/userDataProfileService.ts b/src/vs/workbench/services/userDataProfile/common/userDataProfileService.ts index e03387a0b29..8dc5549e0e9 100644 --- a/src/vs/workbench/services/userDataProfile/common/userDataProfileService.ts +++ b/src/vs/workbench/services/userDataProfile/common/userDataProfileService.ts @@ -16,6 +16,9 @@ export class UserDataProfileService extends Disposable implements IUserDataProfi private readonly _onDidChangeCurrentProfile = this._register(new Emitter()); readonly onDidChangeCurrentProfile = this._onDidChangeCurrentProfile.event; + private readonly _onDidUpdateCurrentProfile = this._register(new Emitter()); + readonly onDidUpdateCurrentProfile = this._onDidUpdateCurrentProfile.event; + private _currentProfile: IUserDataProfile; get currentProfile(): IUserDataProfile { return this._currentProfile; } @@ -25,13 +28,20 @@ export class UserDataProfileService extends Disposable implements IUserDataProfi ) { super(); this._currentProfile = currentProfile; - this._register(userDataProfilesService.onDidChangeProfiles(() => { + this._register(userDataProfilesService.onDidChangeProfiles(e => { /** * If the current profile is default profile, then reset it because, * In Desktop the extensions resource will be set/unset in the default profile when profiles are changed. */ if (this._currentProfile.isDefault) { this._currentProfile = userDataProfilesService.defaultProfile; + return; + } + + const updatedCurrentProfile = e.updated.find(p => this._currentProfile.id === p.id); + if (updatedCurrentProfile) { + this._currentProfile = updatedCurrentProfile; + this._onDidUpdateCurrentProfile.fire(); } })); } diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index ff291f79a9f..de310cbfb0d 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -2009,6 +2009,7 @@ export class TestWorkbenchExtensionManagementService implements IWorkbenchExtens export class TestUserDataProfileService implements IUserDataProfileService { readonly _serviceBrand: undefined; + readonly onDidUpdateCurrentProfile = Event.None; readonly onDidChangeCurrentProfile = Event.None; readonly currentProfile = toUserDataProfile('test', URI.file('tests').with({ scheme: 'vscode-tests' })); async updateCurrentProfile(): Promise { }