Merge pull request #156792 from microsoft/sandy081/extensive-sparrow

use the profile from current or last active window
This commit is contained in:
Sandeep Somavarapu
2022-08-02 08:44:49 +02:00
committed by GitHub
7 changed files with 98 additions and 41 deletions
@@ -91,11 +91,14 @@ export interface IUserDataProfilesService {
readonly onDidChangeProfiles: Event<DidChangeProfilesEvent>;
readonly profiles: IUserDataProfile[];
readonly onDidResetWorkspaces: Event<void>;
createProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags, workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile>;
updateProfile(profile: IUserDataProfile, name: string, useDefaultFlags?: UseDefaultProfileFlags): Promise<IUserDataProfile>;
setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: WorkspaceIdentifier): Promise<void>;
getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile;
getProfile(workspaceIdentifier: WorkspaceIdentifier, profileToUseIfNotSet: IUserDataProfile): IUserDataProfile;
removeProfile(profile: IUserDataProfile): Promise<void>;
resetWorkspaces(): Promise<void>;
}
export function reviveProfile(profile: UriDto<IUserDataProfile>, scheme: string): IUserDataProfile {
@@ -171,6 +174,9 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
protected readonly _onWillRemoveProfile = this._register(new Emitter<WillRemoveProfileEvent>());
readonly onWillRemoveProfile = this._onWillRemoveProfile.event;
private readonly _onDidResetWorkspaces = this._register(new Emitter<void>());
readonly onDidResetWorkspaces = this._onDidResetWorkspaces.event;
constructor(
@IEnvironmentService protected readonly environmentService: IEnvironmentService,
@IFileService protected readonly fileService: IFileService,
@@ -194,6 +200,8 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
const profiles = this.enabled ? this.getStoredProfiles().map<IUserDataProfile>(storedProfile => toUserDataProfile(storedProfile.name, storedProfile.location, storedProfile.useDefaultFlags)) : [];
let emptyWindow: IUserDataProfile | undefined;
const workspaces = new ResourceMap<IUserDataProfile>();
const defaultProfile = toUserDataProfile(localize('defaultProfile', "Default"), this.environmentService.userRoamingDataHome);
profiles.unshift({ ...defaultProfile, isDefault: true, extensionsResource: this.defaultProfileShouldIncludeExtensionsResourceAlways || profiles.length > 0 ? defaultProfile.extensionsResource : undefined });
if (profiles.length) {
const profileAssicaitions = this.getStoredProfileAssociations();
if (profileAssicaitions.workspaces) {
@@ -211,17 +219,23 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
emptyWindow = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, emptyWindowProfileLocation));
}
}
const profile = toUserDataProfile(localize('defaultProfile', "Default"), this.environmentService.userRoamingDataHome);
profiles.unshift({ ...profile, isDefault: true, extensionsResource: this.defaultProfileShouldIncludeExtensionsResourceAlways || profiles.length > 0 ? profile.extensionsResource : undefined });
this._profilesObject = { profiles, workspaces, emptyWindow };
}
return this._profilesObject;
}
getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile {
getProfile(workspaceIdentifier: WorkspaceIdentifier, profileToUseIfNotSet: IUserDataProfile): IUserDataProfile {
const workspace = this.getWorkspace(workspaceIdentifier);
const profile = URI.isUri(workspace) ? this.profilesObject.workspaces.get(workspace) : this.profilesObject.emptyWindow;
return profile ?? this.defaultProfile;
let profile = URI.isUri(workspace) ? this.profilesObject.workspaces.get(workspace) : this.profilesObject.emptyWindow;
if (!profile) {
profile = profileToUseIfNotSet;
// Associate the profile to workspace only if there are user profiles
// If there are no profiles, workspaces are associated to default profile by default
if (this.profiles.length > 1) {
this.updateWorkspaceAssociation(workspaceIdentifier, profile);
}
}
return profile;
}
protected getWorkspace(workspaceIdentifier: WorkspaceIdentifier): URI | EmptyWindowWorkspaceIdentifier {
@@ -299,6 +313,13 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
this.updateWorkspaceAssociation(workspaceIdentifier);
}
async resetWorkspaces(): Promise<void> {
this.profilesObject.workspaces.clear();
this.profilesObject.emptyWindow = undefined;
this.updateStoredProfileAssociations();
this._onDidResetWorkspaces.fire();
}
async removeProfile(profileToRemove: IUserDataProfile): Promise<void> {
if (!this.enabled) {
throw new Error(`Settings Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`);
@@ -364,19 +385,19 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
this._onDidChangeProfiles.fire({ added, removed, updated, all: this.profiles });
}
private updateWorkspaceAssociation(workspaceIdentifier: WorkspaceIdentifier, newProfile?: IUserDataProfile) {
private updateWorkspaceAssociation(workspaceIdentifier: WorkspaceIdentifier, newProfile?: IUserDataProfile): void {
const workspace = this.getWorkspace(workspaceIdentifier);
// Folder or Multiroot workspace
if (URI.isUri(workspace)) {
this.profilesObject.workspaces.delete(workspace);
if (newProfile && !newProfile.isDefault) {
if (newProfile) {
this.profilesObject.workspaces.set(workspace, newProfile);
}
}
// Empty Window
else {
this.profilesObject.emptyWindow = !newProfile?.isDefault ? newProfile : undefined;
this.profilesObject.emptyWindow = newProfile;
}
this.updateStoredProfileAssociations();
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { joinPath } from 'vs/base/common/resources';
import { UriDto } from 'vs/base/common/types';
@@ -29,6 +29,8 @@ export class UserDataProfilesNativeService extends Disposable implements IUserDa
private readonly _onDidChangeProfiles = this._register(new Emitter<DidChangeProfilesEvent>());
readonly onDidChangeProfiles = this._onDidChangeProfiles.event;
readonly onDidResetWorkspaces: Event<void>;
constructor(
profiles: UriDto<IUserDataProfile>[],
@IMainProcessService mainProcessService: IMainProcessService,
@@ -45,6 +47,7 @@ export class UserDataProfilesNativeService extends Disposable implements IUserDa
this._profiles = e.all.map(profile => reviveProfile(profile, this.profilesHome.scheme));
this._onDidChangeProfiles.fire({ added, removed, updated, all: this.profiles });
}));
this.onDidResetWorkspaces = this.channel.listen<void>('onDidResetWorkspaces');
}
async createProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> {
@@ -65,6 +68,10 @@ export class UserDataProfilesNativeService extends Disposable implements IUserDa
return reviveProfile(result, this.profilesHome.scheme);
}
getProfile(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile { throw new Error('Not implemented'); }
resetWorkspaces(): Promise<void> {
return this.channel.call('resetWorkspaces');
}
getProfile(workspaceIdentifier: WorkspaceIdentifier, profileToUseIfNotSet: IUserDataProfile): IUserDataProfile { throw new Error('Not implemented'); }
}
@@ -118,8 +118,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
get openedWorkspace(): IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined { return this._config?.workspace; }
private _profile: IUserDataProfile | undefined;
get profile(): IUserDataProfile | undefined { if (!this._profile) { this._profile = revive(this._config?.profiles.current); } return this._profile; }
get profile(): IUserDataProfile | undefined { return this.config ? this.userDataProfilesService.getProfile(this.config.workspace ?? 'empty-window', revive(this.config.profiles.current)) : undefined; }
get remoteAuthority(): string | undefined { return this._config?.remoteAuthority; }
@@ -956,7 +955,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: this.userDataProfilesService.getProfile(configuration.workspace ?? 'empty-window'),
current: this.profile || this.userDataProfilesService.defaultProfile,
};
// Load config
@@ -1326,7 +1326,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
profiles: {
all: this.userDataProfilesService.profiles,
current: this.userDataProfilesService.getProfile(options.workspace ?? 'empty-window'),
current: this.userDataProfilesService.getProfile(options.workspace ?? 'empty-window', (options.windowToUse ?? this.getLastActiveWindow())?.profile ?? this.userDataProfilesService.defaultProfile),
},
homeDir: this.environmentMainService.userHome.fsPath,
+1 -1
View File
@@ -269,7 +269,7 @@ export class BrowserMain extends Disposable {
// User Data Profiles
const userDataProfilesService = new BrowserUserDataProfilesService(environmentService, fileService, uriIdentityService, logService);
serviceCollection.set(IUserDataProfilesService, userDataProfilesService);
const userDataProfileService = new UserDataProfileService(userDataProfilesService.getProfile(isWorkspaceIdentifier(payload) || isSingleFolderWorkspaceIdentifier(payload) ? payload : 'empty-window'), userDataProfilesService);
const userDataProfileService = new UserDataProfileService(userDataProfilesService.getProfile(isWorkspaceIdentifier(payload) || isSingleFolderWorkspaceIdentifier(payload) ? payload : 'empty-window', userDataProfilesService.defaultProfile), userDataProfilesService);
serviceCollection.set(IUserDataProfileService, userDataProfileService);
// Long running services (workspace, config, storage)
@@ -295,31 +295,6 @@ registerAction2(class SwitchProfileAction extends Action2 {
}
});
registerAction2(class CleanupProfilesAction extends Action2 {
constructor() {
super({
id: 'workbench.profiles.actions.cleanupProfiles',
title: {
value: localize('cleanup profile', "Cleanup Settings Profiles"),
original: 'Cleanup Profiles'
},
category: CATEGORIES.Developer,
f1: true,
precondition: PROFILES_ENABLEMENT_CONTEXT,
});
}
async run(accessor: ServicesAccessor) {
const userDataProfilesService = accessor.get(IUserDataProfilesService);
const fileService = accessor.get(IFileService);
const uriIdentityService = accessor.get(IUriIdentityService);
const stat = await fileService.resolve(userDataProfilesService.profilesHome);
await Promise.all((stat.children || [])?.filter(child => child.isDirectory && userDataProfilesService.profiles.every(p => !uriIdentityService.extUri.isEqual(p.location, child.resource)))
.map(child => fileService.del(child.resource, { recursive: true })));
}
});
registerAction2(class ExportProfileAction extends Action2 {
constructor() {
super({
@@ -469,3 +444,50 @@ registerAction2(class ImportProfileAction extends Action2 {
}
});
// Developer Actions
registerAction2(class CleanupProfilesAction extends Action2 {
constructor() {
super({
id: 'workbench.profiles.actions.cleanupProfiles',
title: {
value: localize('cleanup profile', "Cleanup Settings Profiles"),
original: 'Cleanup Profiles'
},
category: CATEGORIES.Developer,
f1: true,
precondition: PROFILES_ENABLEMENT_CONTEXT,
});
}
async run(accessor: ServicesAccessor) {
const userDataProfilesService = accessor.get(IUserDataProfilesService);
const fileService = accessor.get(IFileService);
const uriIdentityService = accessor.get(IUriIdentityService);
const stat = await fileService.resolve(userDataProfilesService.profilesHome);
await Promise.all((stat.children || [])?.filter(child => child.isDirectory && userDataProfilesService.profiles.every(p => !uriIdentityService.extUri.isEqual(p.location, child.resource)))
.map(child => fileService.del(child.resource, { recursive: true })));
}
});
registerAction2(class ResetWorkspacesAction extends Action2 {
constructor() {
super({
id: 'workbench.profiles.actions.resetWorkspaces',
title: {
value: localize('reset workspaces', "Reset Workspace Settings Profiles Associations"),
original: 'Reset Workspace Settings Profiles Associations'
},
category: CATEGORIES.Developer,
f1: true,
precondition: PROFILES_ENABLEMENT_CONTEXT,
});
}
async run(accessor: ServicesAccessor) {
const userDataProfilesService = accessor.get(IUserDataProfilesService);
return userDataProfilesService.resetWorkspaces();
}
});
@@ -28,6 +28,7 @@ export class UserDataProfileManagementService extends Disposable implements IUse
) {
super();
this._register(userDataProfilesService.onDidChangeProfiles(e => this.onDidChangeProfiles(e)));
this._register(userDataProfilesService.onDidResetWorkspaces(() => this.onDidResetWorkspaces()));
}
private onDidChangeProfiles(e: DidChangeProfilesEvent): void {
@@ -37,6 +38,13 @@ export class UserDataProfileManagementService extends Disposable implements IUse
}
}
private onDidResetWorkspaces(): void {
if (!this.userDataProfileService.currentProfile.isDefault) {
this.enterProfile(this.userDataProfilesService.defaultProfile, false, localize('reload message when removed', "The current settings profile has been removed. Please reload to switch back to default settings profile"));
return;
}
}
async createAndEnterProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags, fromExisting?: boolean): Promise<IUserDataProfile> {
const profile = await this.userDataProfilesService.createProfile(name, useDefaultFlags, this.getWorkspaceIdentifier());
await this.enterProfile(profile, !!fromExisting);