mirror of
https://github.com/microsoft/vscode.git
synced 2026-06-03 06:04:37 +01:00
* fix #168976 * code formatting * review feedback * clean up empty window associations * use `instanceof` check for `Promise` Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
4d4e903f2b
commit
fef6e86202
@@ -105,7 +105,7 @@ import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { ExtensionsProfileScannerService, IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
|
||||
import { IExtensionsScannerService } from 'vs/platform/extensionManagement/common/extensionsScannerService';
|
||||
import { ExtensionsScannerService } from 'vs/platform/extensionManagement/node/extensionsScannerService';
|
||||
import { UserDataTransientProfilesHandler } from 'vs/platform/userDataProfile/electron-main/userDataTransientProfilesHandler';
|
||||
import { UserDataProfilesHandler } from 'vs/platform/userDataProfile/electron-main/userDataProfilesHandler';
|
||||
import { ProfileStorageChangesListenerChannel } from 'vs/platform/userDataProfile/electron-main/userDataProfileStorageIpc';
|
||||
import { Promises, RunOnceScheduler, runWhenIdle } from 'vs/base/common/async';
|
||||
import { resolveMachineId } from 'vs/platform/telemetry/electron-main/telemetryUtils';
|
||||
@@ -558,7 +558,7 @@ export class CodeApplication extends Disposable {
|
||||
this._register(instantiationService.createInstance(ProxyAuthHandler));
|
||||
|
||||
// Transient profiles handler
|
||||
this._register(instantiationService.createInstance(UserDataTransientProfilesHandler));
|
||||
this._register(instantiationService.createInstance(UserDataProfilesHandler));
|
||||
}
|
||||
|
||||
private setupSharedProcess(machineId: string): { sharedProcess: SharedProcess; sharedProcessReady: Promise<MessagePortClient>; sharedProcessClient: Promise<MessagePortClient> } {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { IAnyWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
@@ -69,9 +69,6 @@ export function isUserDataProfile(thing: unknown): thing is IUserDataProfile {
|
||||
|
||||
export const PROFILES_ENABLEMENT_CONFIG = 'workbench.experimental.settingsProfiles.enabled';
|
||||
|
||||
export type EmptyWindowWorkspaceIdentifier = 'empty-window';
|
||||
export type WorkspaceIdentifier = ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier | EmptyWindowWorkspaceIdentifier;
|
||||
|
||||
export type DidChangeProfilesEvent = { readonly added: readonly IUserDataProfile[]; readonly removed: readonly IUserDataProfile[]; readonly updated: readonly IUserDataProfile[]; readonly all: readonly IUserDataProfile[] };
|
||||
|
||||
export type WillCreateProfileEvent = {
|
||||
@@ -107,13 +104,13 @@ export interface IUserDataProfilesService {
|
||||
readonly onDidResetWorkspaces: Event<void>;
|
||||
|
||||
isEnabled(): boolean;
|
||||
createNamedProfile(name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
createTransientProfile(workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
createProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
createNamedProfile(name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
createTransientProfile(workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
createProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile>;
|
||||
updateProfile(profile: IUserDataProfile, options?: IUserDataProfileUpdateOptions,): Promise<IUserDataProfile>;
|
||||
removeProfile(profile: IUserDataProfile): Promise<void>;
|
||||
|
||||
setProfileForWorkspace(workspaceIdentifier: WorkspaceIdentifier, profile: IUserDataProfile): Promise<void>;
|
||||
setProfileForWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier, profile: IUserDataProfile): Promise<void>;
|
||||
resetWorkspaces(): Promise<void>;
|
||||
|
||||
cleanUp(): Promise<void>;
|
||||
@@ -159,7 +156,7 @@ export function toUserDataProfile(id: string, name: string, location: URI, optio
|
||||
export type UserDataProfilesObject = {
|
||||
profiles: IUserDataProfile[];
|
||||
workspaces: ResourceMap<IUserDataProfile>;
|
||||
emptyWindow?: IUserDataProfile;
|
||||
emptyWindows: Map<string, IUserDataProfile>;
|
||||
};
|
||||
|
||||
export type StoredUserDataProfile = {
|
||||
@@ -171,7 +168,7 @@ export type StoredUserDataProfile = {
|
||||
|
||||
export type StoredProfileAssociations = {
|
||||
workspaces?: IStringDictionary<string>;
|
||||
emptyWindow?: string;
|
||||
emptyWindows?: IStringDictionary<string>;
|
||||
};
|
||||
|
||||
export class UserDataProfilesService extends Disposable implements IUserDataProfilesService {
|
||||
@@ -203,7 +200,8 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
|
||||
protected readonly transientProfilesObject: UserDataProfilesObject = {
|
||||
profiles: [],
|
||||
workspaces: new ResourceMap()
|
||||
workspaces: new ResourceMap(),
|
||||
emptyWindows: new Map()
|
||||
};
|
||||
|
||||
constructor(
|
||||
@@ -240,14 +238,14 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
profiles.push(toUserDataProfile(basename(storedProfile.location), storedProfile.name, storedProfile.location, { shortName: storedProfile.shortName, useDefaultFlags: storedProfile.useDefaultFlags }));
|
||||
}
|
||||
}
|
||||
let emptyWindow: IUserDataProfile | undefined;
|
||||
const workspaces = new ResourceMap<IUserDataProfile>();
|
||||
const emptyWindows = new Map<string, IUserDataProfile>();
|
||||
const defaultProfile = toUserDataProfile(hash(this.environmentService.userRoamingDataHome.path).toString(16), localize('defaultProfile', "Default"), this.environmentService.userRoamingDataHome);
|
||||
profiles.unshift({ ...defaultProfile, extensionsResource: this.getDefaultProfileExtensionsLocation() ?? defaultProfile.extensionsResource, isDefault: true });
|
||||
if (profiles.length) {
|
||||
const profileAssicaitions = this.getStoredProfileAssociations();
|
||||
if (profileAssicaitions.workspaces) {
|
||||
for (const [workspacePath, profilePath] of Object.entries(profileAssicaitions.workspaces)) {
|
||||
const profileAssociaitions = this.getStoredProfileAssociations();
|
||||
if (profileAssociaitions.workspaces) {
|
||||
for (const [workspacePath, profilePath] of Object.entries(profileAssociaitions.workspaces)) {
|
||||
const workspace = URI.parse(workspacePath);
|
||||
const profileLocation = URI.parse(profilePath);
|
||||
const profile = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, profileLocation));
|
||||
@@ -256,17 +254,22 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
}
|
||||
}
|
||||
}
|
||||
if (profileAssicaitions.emptyWindow) {
|
||||
const emptyWindowProfileLocation = URI.parse(profileAssicaitions.emptyWindow);
|
||||
emptyWindow = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, emptyWindowProfileLocation));
|
||||
if (profileAssociaitions.emptyWindows) {
|
||||
for (const [windowId, profilePath] of Object.entries(profileAssociaitions.emptyWindows)) {
|
||||
const profileLocation = URI.parse(profilePath);
|
||||
const profile = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, profileLocation));
|
||||
if (profile) {
|
||||
emptyWindows.set(windowId, profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._profilesObject = { profiles, workspaces, emptyWindow };
|
||||
this._profilesObject = { profiles, workspaces, emptyWindows };
|
||||
}
|
||||
return this._profilesObject;
|
||||
}
|
||||
|
||||
async createTransientProfile(workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
async createTransientProfile(workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
const namePrefix = `Temp`;
|
||||
const nameRegEx = new RegExp(`${escapeRegExpCharacters(namePrefix)}\\s(\\d+)`);
|
||||
let nameIndex = 0;
|
||||
@@ -279,11 +282,11 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
return this.createProfile(hash(generateUuid()).toString(16), name, { transient: true }, workspaceIdentifier);
|
||||
}
|
||||
|
||||
async createNamedProfile(name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
async createNamedProfile(name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
return this.createProfile(hash(generateUuid()).toString(16), name, options, workspaceIdentifier);
|
||||
}
|
||||
|
||||
async createProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
async createProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
if (!this.enabled) {
|
||||
throw new Error(`Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`);
|
||||
}
|
||||
@@ -375,8 +378,10 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
this.logService.error(error);
|
||||
}
|
||||
|
||||
if (profile.id === this.profilesObject.emptyWindow?.id) {
|
||||
this.profilesObject.emptyWindow = undefined;
|
||||
for (const windowId of [...this.profilesObject.emptyWindows.keys()]) {
|
||||
if (profile.id === this.profilesObject.emptyWindows.get(windowId)?.id) {
|
||||
this.profilesObject.emptyWindows.delete(windowId);
|
||||
}
|
||||
}
|
||||
for (const workspace of [...this.profilesObject.workspaces.keys()]) {
|
||||
if (profile.id === this.profilesObject.workspaces.get(workspace)?.id) {
|
||||
@@ -398,28 +403,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
}
|
||||
}
|
||||
|
||||
getOrSetProfileForWorkspace(workspaceIdentifier: WorkspaceIdentifier, profileToSet: IUserDataProfile = this.defaultProfile): IUserDataProfile {
|
||||
if (!this.enabled) {
|
||||
return this.defaultProfile;
|
||||
}
|
||||
|
||||
let profile = this.getProfileForWorkspace(workspaceIdentifier);
|
||||
if (!profile) {
|
||||
profile = profileToSet;
|
||||
// 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.setProfileForWorkspaceSync(workspaceIdentifier, profile);
|
||||
}
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
async setProfileForWorkspace(workspaceIdentifier: WorkspaceIdentifier, profileToSet: IUserDataProfile): Promise<void> {
|
||||
this.setProfileForWorkspaceSync(workspaceIdentifier, profileToSet);
|
||||
}
|
||||
|
||||
setProfileForWorkspaceSync(workspaceIdentifier: WorkspaceIdentifier, profileToSet: IUserDataProfile): void {
|
||||
async setProfileForWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier, profileToSet: IUserDataProfile): Promise<void> {
|
||||
if (!this.enabled) {
|
||||
throw new Error(`Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`);
|
||||
}
|
||||
@@ -432,7 +416,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
this.updateWorkspaceAssociation(workspaceIdentifier, profile);
|
||||
}
|
||||
|
||||
unsetWorkspace(workspaceIdentifier: WorkspaceIdentifier, transient?: boolean): void {
|
||||
unsetWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier, transient?: boolean): void {
|
||||
if (!this.enabled) {
|
||||
throw new Error(`Profiles are disabled. Enable them via the '${PROFILES_ENABLEMENT_CONFIG}' setting.`);
|
||||
}
|
||||
@@ -442,9 +426,9 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
|
||||
async resetWorkspaces(): Promise<void> {
|
||||
this.transientProfilesObject.workspaces.clear();
|
||||
this.transientProfilesObject.emptyWindow = undefined;
|
||||
this.transientProfilesObject.emptyWindows.clear();
|
||||
this.profilesObject.workspaces.clear();
|
||||
this.profilesObject.emptyWindow = undefined;
|
||||
this.profilesObject.emptyWindows.clear();
|
||||
this.updateStoredProfileAssociations();
|
||||
this._onDidResetWorkspaces.fire();
|
||||
}
|
||||
@@ -469,29 +453,29 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
await Promise.allSettled(unAssociatedTransientProfiles.map(p => this.removeProfile(p)));
|
||||
}
|
||||
|
||||
private getProfileForWorkspace(workspaceIdentifier: WorkspaceIdentifier): IUserDataProfile | undefined {
|
||||
getProfileForWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier): IUserDataProfile | undefined {
|
||||
const workspace = this.getWorkspace(workspaceIdentifier);
|
||||
return URI.isUri(workspace) ? this.transientProfilesObject.workspaces.get(workspace) ?? this.profilesObject.workspaces.get(workspace) : this.transientProfilesObject.emptyWindow ?? this.profilesObject.emptyWindow;
|
||||
return URI.isUri(workspace) ? this.transientProfilesObject.workspaces.get(workspace) ?? this.profilesObject.workspaces.get(workspace) : this.transientProfilesObject.emptyWindows.get(workspace) ?? this.profilesObject.emptyWindows.get(workspace);
|
||||
}
|
||||
|
||||
protected getWorkspace(workspaceIdentifier: WorkspaceIdentifier): URI | EmptyWindowWorkspaceIdentifier {
|
||||
protected getWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier): URI | string {
|
||||
if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier)) {
|
||||
return workspaceIdentifier.uri;
|
||||
}
|
||||
if (isWorkspaceIdentifier(workspaceIdentifier)) {
|
||||
return workspaceIdentifier.configPath;
|
||||
}
|
||||
return 'empty-window';
|
||||
return workspaceIdentifier.id;
|
||||
}
|
||||
|
||||
private isProfileAssociatedToWorkspace(profile: IUserDataProfile): boolean {
|
||||
if (this.uriIdentityService.extUri.isEqual(this.transientProfilesObject.emptyWindow?.location, profile.location)) {
|
||||
if ([...this.transientProfilesObject.emptyWindows.values()].some(windowProfile => this.uriIdentityService.extUri.isEqual(windowProfile.location, profile.location))) {
|
||||
return true;
|
||||
}
|
||||
if ([...this.transientProfilesObject.workspaces.values()].some(workspaceProfile => this.uriIdentityService.extUri.isEqual(workspaceProfile.location, profile.location))) {
|
||||
return true;
|
||||
}
|
||||
if (this.uriIdentityService.extUri.isEqual(this.profilesObject.emptyWindow?.location, profile.location)) {
|
||||
if ([...this.profilesObject.emptyWindows.values()].some(windowProfile => this.uriIdentityService.extUri.isEqual(windowProfile.location, profile.location))) {
|
||||
return true;
|
||||
}
|
||||
if ([...this.profilesObject.workspaces.values()].some(workspaceProfile => this.uriIdentityService.extUri.isEqual(workspaceProfile.location, profile.location))) {
|
||||
@@ -527,7 +511,7 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
this._onDidChangeProfiles.fire({ added, removed, updated, all: this.profiles });
|
||||
}
|
||||
|
||||
private updateWorkspaceAssociation(workspaceIdentifier: WorkspaceIdentifier, newProfile?: IUserDataProfile, transient?: boolean): void {
|
||||
private updateWorkspaceAssociation(workspaceIdentifier: IAnyWorkspaceIdentifier, newProfile?: IUserDataProfile, transient?: boolean): void {
|
||||
// Force transient if the new profile to associate is transient
|
||||
transient = newProfile?.isTransient ? true : transient;
|
||||
|
||||
@@ -548,7 +532,10 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
}
|
||||
// Empty Window
|
||||
else {
|
||||
profilesObject.emptyWindow = newProfile;
|
||||
profilesObject.emptyWindows.delete(workspace);
|
||||
if (newProfile) {
|
||||
profilesObject.emptyWindows.set(workspace, newProfile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!transient) {
|
||||
@@ -561,8 +548,11 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
|
||||
for (const [workspace, profile] of this.profilesObject.workspaces.entries()) {
|
||||
workspaces[workspace.toString()] = profile.location.toString();
|
||||
}
|
||||
const emptyWindow = this.profilesObject.emptyWindow?.location.toString();
|
||||
this.saveStoredProfileAssociations({ workspaces, emptyWindow });
|
||||
const emptyWindows: IStringDictionary<string> = {};
|
||||
for (const [windowId, profile] of this.profilesObject.emptyWindows.entries()) {
|
||||
emptyWindows[windowId.toString()] = profile.location.toString();
|
||||
}
|
||||
this.saveStoredProfileAssociations({ workspaces, emptyWindows });
|
||||
this._profilesObject = undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,15 +11,16 @@ import { refineServiceDecorator } from 'vs/platform/instantiation/common/instant
|
||||
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 { IUserDataProfilesService, WorkspaceIdentifier, StoredUserDataProfile, StoredProfileAssociations, WillCreateProfileEvent, WillRemoveProfileEvent, IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IUserDataProfilesService, StoredUserDataProfile, StoredProfileAssociations, WillCreateProfileEvent, WillRemoveProfileEvent, IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { UserDataProfilesService } from 'vs/platform/userDataProfile/node/userDataProfile';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { IAnyWorkspaceIdentifier, IEmptyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
export const IUserDataProfilesMainService = refineServiceDecorator<IUserDataProfilesService, IUserDataProfilesMainService>(IUserDataProfilesService);
|
||||
export interface IUserDataProfilesMainService extends IUserDataProfilesService {
|
||||
getOrSetProfileForWorkspace(workspaceIdentifier: WorkspaceIdentifier, profileToSet?: IUserDataProfile): IUserDataProfile;
|
||||
setProfileForWorkspaceSync(workspaceIdentifier: WorkspaceIdentifier, profileToSet: IUserDataProfile): void;
|
||||
unsetWorkspace(workspaceIdentifier: WorkspaceIdentifier, transient?: boolean): void;
|
||||
getProfileForWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier): IUserDataProfile | undefined;
|
||||
unsetWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier, transient?: boolean): void;
|
||||
getAssociatedEmptyWindows(): IEmptyWorkspaceIdentifier[];
|
||||
readonly onWillCreateProfile: Event<WillCreateProfileEvent>;
|
||||
readonly onWillRemoveProfile: Event<WillRemoveProfileEvent>;
|
||||
}
|
||||
@@ -45,6 +46,14 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme
|
||||
}
|
||||
}
|
||||
|
||||
getAssociatedEmptyWindows(): IEmptyWorkspaceIdentifier[] {
|
||||
const emptyWindows: IEmptyWorkspaceIdentifier[] = [];
|
||||
for (const id of this.profilesObject.emptyWindows.keys()) {
|
||||
emptyWindows.push({ id });
|
||||
}
|
||||
return emptyWindows;
|
||||
}
|
||||
|
||||
protected override saveStoredProfiles(storedProfiles: StoredUserDataProfile[]): void {
|
||||
if (storedProfiles.length) {
|
||||
this.stateMainService.setItem(UserDataProfilesMainService.PROFILES_KEY, storedProfiles);
|
||||
@@ -54,7 +63,7 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme
|
||||
}
|
||||
|
||||
protected override saveStoredProfileAssociations(storedProfileAssociations: StoredProfileAssociations): void {
|
||||
if (storedProfileAssociations.emptyWindow || storedProfileAssociations.workspaces) {
|
||||
if (storedProfileAssociations.emptyWindows || storedProfileAssociations.workspaces) {
|
||||
this.stateMainService.setItem(UserDataProfilesMainService.PROFILE_ASSOCIATIONS_KEY, storedProfileAssociations);
|
||||
} else {
|
||||
this.stateMainService.removeItem(UserDataProfilesMainService.PROFILE_ASSOCIATIONS_KEY);
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ILifecycleMainService, } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { ICodeWindow, LoadReason } from 'vs/platform/window/electron-main/window';
|
||||
import { IUserDataProfilesMainService } from 'vs/platform/userDataProfile/electron-main/userDataProfile';
|
||||
import { IAnyWorkspaceIdentifier, isEmptyWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
|
||||
|
||||
export class UserDataProfilesHandler extends Disposable {
|
||||
|
||||
constructor(
|
||||
@ILifecycleMainService lifecycleMainService: ILifecycleMainService,
|
||||
@IUserDataProfilesMainService private readonly userDataProfilesService: IUserDataProfilesMainService,
|
||||
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
|
||||
) {
|
||||
super();
|
||||
this._register(lifecycleMainService.onWillLoadWindow(e => {
|
||||
if (e.reason === LoadReason.LOAD) {
|
||||
this.unsetProfileForWorkspace(e.window);
|
||||
}
|
||||
}));
|
||||
this._register(lifecycleMainService.onBeforeCloseWindow(window => this.unsetProfileForWorkspace(window)));
|
||||
this._register(new RunOnceScheduler(() => this.cleanUpEmptyWindowAssociations(), 30 * 1000 /* after 30s */)).schedule();
|
||||
}
|
||||
|
||||
private async unsetProfileForWorkspace(window: ICodeWindow): Promise<void> {
|
||||
const workspace = this.getWorkspace(window);
|
||||
const profile = this.userDataProfilesService.getProfileForWorkspace(workspace);
|
||||
if (profile && (isEmptyWorkspaceIdentifier(workspace) || profile.isTransient)) {
|
||||
this.userDataProfilesService.unsetWorkspace(workspace, profile.isTransient);
|
||||
if (profile.isTransient) {
|
||||
await this.userDataProfilesService.cleanUpTransientProfiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getWorkspace(window: ICodeWindow): IAnyWorkspaceIdentifier {
|
||||
return window.openedWorkspace ?? toWorkspaceIdentifier(window.backupPath, window.isExtensionDevelopmentHost);
|
||||
}
|
||||
|
||||
private cleanUpEmptyWindowAssociations(): void {
|
||||
const associatedEmptyWindows = this.userDataProfilesService.getAssociatedEmptyWindows();
|
||||
if (associatedEmptyWindows.length === 0) {
|
||||
return;
|
||||
}
|
||||
const openedWorkspaces = this.windowsMainService.getWindows().map(window => this.getWorkspace(window));
|
||||
for (const associatedEmptyWindow of associatedEmptyWindows) {
|
||||
if (openedWorkspaces.some(openedWorkspace => openedWorkspace.id === associatedEmptyWindow.id)) {
|
||||
continue;
|
||||
}
|
||||
this.userDataProfilesService.unsetWorkspace(associatedEmptyWindow, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { WorkspaceIdentifier } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ILifecycleMainService, } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { LoadReason } from 'vs/platform/window/electron-main/window';
|
||||
import { IUserDataProfilesMainService } from 'vs/platform/userDataProfile/electron-main/userDataProfile';
|
||||
|
||||
export class UserDataTransientProfilesHandler extends Disposable {
|
||||
|
||||
constructor(
|
||||
@ILifecycleMainService lifecycleMainService: ILifecycleMainService,
|
||||
@IUserDataProfilesMainService private readonly userDataProfilesService: IUserDataProfilesMainService,
|
||||
) {
|
||||
super();
|
||||
this._register(lifecycleMainService.onWillLoadWindow(e => {
|
||||
if (e.reason === LoadReason.LOAD) {
|
||||
this.unsetTransientProfileForWorkspace(e.window.openedWorkspace ?? 'empty-window');
|
||||
}
|
||||
}));
|
||||
this._register(lifecycleMainService.onBeforeCloseWindow(window => this.unsetTransientProfileForWorkspace(window.openedWorkspace ?? 'empty-window')));
|
||||
}
|
||||
|
||||
private async unsetTransientProfileForWorkspace(workspace: WorkspaceIdentifier): Promise<void> {
|
||||
const profile = this.userDataProfilesService.getOrSetProfileForWorkspace(workspace);
|
||||
if (profile.isTransient) {
|
||||
this.userDataProfilesService.unsetWorkspace(workspace, true);
|
||||
await this.userDataProfilesService.cleanUpTransientProfiles();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,8 @@ import { URI, UriDto } from 'vs/base/common/uri';
|
||||
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/services';
|
||||
import { DidChangeProfilesEvent, IUserDataProfile, IUserDataProfileOptions, IUserDataProfilesService, IUserDataProfileUpdateOptions, reviveProfile, WorkspaceIdentifier } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { DidChangeProfilesEvent, IUserDataProfile, IUserDataProfileOptions, IUserDataProfilesService, IUserDataProfileUpdateOptions, reviveProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IAnyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
export class UserDataProfilesNativeService extends Disposable implements IUserDataProfilesService {
|
||||
|
||||
@@ -58,22 +59,22 @@ export class UserDataProfilesNativeService extends Disposable implements IUserDa
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
async createNamedProfile(name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
async createNamedProfile(name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
const result = await this.channel.call<UriDto<IUserDataProfile>>('createNamedProfile', [name, options, workspaceIdentifier]);
|
||||
return reviveProfile(result, this.profilesHome.scheme);
|
||||
}
|
||||
|
||||
async createProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
async createProfile(id: string, name: string, options?: IUserDataProfileOptions, workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
const result = await this.channel.call<UriDto<IUserDataProfile>>('createProfile', [id, name, options, workspaceIdentifier]);
|
||||
return reviveProfile(result, this.profilesHome.scheme);
|
||||
}
|
||||
|
||||
async createTransientProfile(workspaceIdentifier?: WorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
async createTransientProfile(workspaceIdentifier?: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> {
|
||||
const result = await this.channel.call<UriDto<IUserDataProfile>>('createTransientProfile', [workspaceIdentifier]);
|
||||
return reviveProfile(result, this.profilesHome.scheme);
|
||||
}
|
||||
|
||||
async setProfileForWorkspace(workspaceIdentifier: WorkspaceIdentifier, profile: IUserDataProfile): Promise<void> {
|
||||
async setProfileForWorkspace(workspaceIdentifier: IAnyWorkspaceIdentifier, profile: IUserDataProfile): Promise<void> {
|
||||
await this.channel.call<UriDto<IUserDataProfile>>('setProfileForWorkspace', [workspaceIdentifier, profile]);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,4 +70,39 @@ suite('UserDataProfileMainService', () => {
|
||||
assert.strictEqual(testObject.defaultProfile.isDefault, true);
|
||||
});
|
||||
|
||||
test('when no profile is set', async () => {
|
||||
await testObject.createNamedProfile('profile1');
|
||||
|
||||
assert.equal(testObject.getProfileForWorkspace({ id: 'id' }), undefined);
|
||||
assert.equal(testObject.getProfileForWorkspace({ id: 'id', configPath: environmentService.userRoamingDataHome }), undefined);
|
||||
assert.equal(testObject.getProfileForWorkspace({ id: 'id', uri: environmentService.userRoamingDataHome }), undefined);
|
||||
});
|
||||
|
||||
test('set profile to a workspace', async () => {
|
||||
const workspace = { id: 'id', configPath: environmentService.userRoamingDataHome };
|
||||
const profile = await testObject.createNamedProfile('profile1');
|
||||
|
||||
testObject.setProfileForWorkspace(workspace, profile);
|
||||
|
||||
assert.deepStrictEqual(testObject.getProfileForWorkspace(workspace), profile);
|
||||
});
|
||||
|
||||
test('set profile to a folder', async () => {
|
||||
const workspace = { id: 'id', uri: environmentService.userRoamingDataHome };
|
||||
const profile = await testObject.createNamedProfile('profile1');
|
||||
|
||||
testObject.setProfileForWorkspace(workspace, profile);
|
||||
|
||||
assert.deepStrictEqual(testObject.getProfileForWorkspace(workspace), profile);
|
||||
});
|
||||
|
||||
test('set profile to a window', async () => {
|
||||
const workspace = { id: 'id' };
|
||||
const profile = await testObject.createNamedProfile('profile1');
|
||||
|
||||
testObject.setProfileForWorkspace(workspace, profile);
|
||||
|
||||
assert.deepStrictEqual(testObject.getProfileForWorkspace(workspace), profile);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -35,7 +35,7 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService';
|
||||
import { getMenuBarVisibility, getTitleBarStyle, IFolderToOpen, INativeWindowConfiguration, IWindowSettings, IWorkspaceToOpen, MenuBarVisibility, useWindowControlsOverlay, WindowMinimumSize, zoomLevelToZoomFactor } from 'vs/platform/window/common/window';
|
||||
import { IWindowsMainService, OpenContext } from 'vs/platform/windows/electron-main/windows';
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
|
||||
import { IWindowState, ICodeWindow, ILoadEvent, WindowMode, WindowError, LoadReason, defaultWindowState } from 'vs/platform/window/electron-main/window';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
@@ -139,7 +139,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
return profile;
|
||||
}
|
||||
|
||||
return this.userDataProfilesService.getOrSetProfileForWorkspace(this.config.workspace ?? 'empty-window', this.userDataProfilesService.defaultProfile);
|
||||
return this.userDataProfilesService.getProfileForWorkspace(this.config.workspace ?? toWorkspaceIdentifier(this.backupPath, this.isExtensionDevelopmentHost)) ?? this.userDataProfilesService.defaultProfile;
|
||||
}
|
||||
|
||||
get remoteAuthority(): string | undefined { return this._config?.remoteAuthority; }
|
||||
|
||||
@@ -44,7 +44,7 @@ import { IOpenConfiguration, IOpenEmptyConfiguration, IWindowsCountChangedEvent,
|
||||
import { findWindowOnExtensionDevelopmentPath, findWindowOnFile, findWindowOnWorkspaceOrFolder } from 'vs/platform/windows/electron-main/windowsFinder';
|
||||
import { IWindowState, WindowsStateHandler } from 'vs/platform/windows/electron-main/windowsStateHandler';
|
||||
import { IRecent } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { hasWorkspaceFileExtension, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { hasWorkspaceFileExtension, IAnyWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { createEmptyWorkspaceIdentifier, getSingleFolderWorkspaceIdentifier, getWorkspaceIdentifier } from 'vs/platform/workspaces/node/workspaces';
|
||||
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
|
||||
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService';
|
||||
@@ -1350,7 +1350,10 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
|
||||
profiles: {
|
||||
all: this.userDataProfilesMainService.profiles,
|
||||
profile: window?.isExtensionDevelopmentHost && window?.profile ? window.profile : await this.resolveProfileForBrowserWindow(options)
|
||||
// Set to default profile first and resolve and update the profile
|
||||
// only after the workspace-backup is registered.
|
||||
// Because, workspace identifier of an empty window is known only then.
|
||||
profile: this.userDataProfilesMainService.defaultProfile
|
||||
},
|
||||
|
||||
homeDir: this.environmentMainService.userHome.fsPath,
|
||||
@@ -1453,19 +1456,19 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
// first and only load the new configuration if that was
|
||||
// not vetoed
|
||||
if (window.isReady) {
|
||||
this.lifecycleMainService.unload(window, UnloadReason.LOAD).then(veto => {
|
||||
this.lifecycleMainService.unload(window, UnloadReason.LOAD).then(async veto => {
|
||||
if (!veto) {
|
||||
this.doOpenInBrowserWindow(window!, configuration, options);
|
||||
await this.doOpenInBrowserWindow(window!, configuration, options);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.doOpenInBrowserWindow(window, configuration, options);
|
||||
await this.doOpenInBrowserWindow(window, configuration, options);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
private doOpenInBrowserWindow(window: ICodeWindow, configuration: INativeWindowConfiguration, options: IOpenBrowserWindowOptions): void {
|
||||
private async doOpenInBrowserWindow(window: ICodeWindow, configuration: INativeWindowConfiguration, options: IOpenBrowserWindowOptions): Promise<void> {
|
||||
|
||||
// Register window for backups unless the window
|
||||
// is for extension development, where we do not
|
||||
@@ -1498,27 +1501,34 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
}
|
||||
}
|
||||
|
||||
if (this.userDataProfilesMainService.isEnabled()) {
|
||||
const workspace = configuration.workspace ?? toWorkspaceIdentifier(configuration.backupPath, false);
|
||||
const profilePromise = this.resolveProfileForBrowserWindow(options, workspace);
|
||||
const profile = profilePromise instanceof Promise ? await profilePromise : profilePromise;
|
||||
configuration.profiles.profile = profile;
|
||||
|
||||
if (!configuration.extensionDevelopmentPath) {
|
||||
// Associate the configured profile to the workspace
|
||||
// unless the window is for extension development,
|
||||
// where we do not persist the associations
|
||||
await this.userDataProfilesMainService.setProfileForWorkspace(workspace, profile);
|
||||
}
|
||||
}
|
||||
|
||||
// Load it
|
||||
window.load(configuration);
|
||||
}
|
||||
|
||||
private async resolveProfileForBrowserWindow(options: IOpenBrowserWindowOptions): Promise<IUserDataProfile> {
|
||||
let profile: IUserDataProfile | undefined;
|
||||
if (this.userDataProfilesMainService.isEnabled()) {
|
||||
if (options.forceProfile) {
|
||||
profile = this.userDataProfilesMainService.profiles.find(p => p.name === options.forceProfile) ?? await this.userDataProfilesMainService.createNamedProfile(options.forceProfile);
|
||||
} else if (options.forceTempProfile) {
|
||||
profile = await this.userDataProfilesMainService.createTransientProfile();
|
||||
}
|
||||
private resolveProfileForBrowserWindow(options: IOpenBrowserWindowOptions, workspace: IAnyWorkspaceIdentifier): Promise<IUserDataProfile> | IUserDataProfile {
|
||||
if (options.forceProfile) {
|
||||
return this.userDataProfilesMainService.profiles.find(p => p.name === options.forceProfile) ?? this.userDataProfilesMainService.createNamedProfile(options.forceProfile);
|
||||
}
|
||||
if (profile) {
|
||||
if (!options.cli?.extensionDevelopmentPath) {
|
||||
this.userDataProfilesMainService.setProfileForWorkspaceSync(options.workspace ?? 'empty-window', profile);
|
||||
}
|
||||
} else {
|
||||
profile = this.userDataProfilesMainService.getOrSetProfileForWorkspace(options.workspace ?? 'empty-window', this.userDataProfilesMainService.defaultProfile);
|
||||
|
||||
if (options.forceTempProfile) {
|
||||
return this.userDataProfilesMainService.createTransientProfile();
|
||||
}
|
||||
return profile;
|
||||
|
||||
return this.userDataProfilesMainService.getProfileForWorkspace(workspace) ?? this.userDataProfilesMainService.defaultProfile;
|
||||
}
|
||||
|
||||
private onWindowClosed(window: ICodeWindow): void {
|
||||
|
||||
@@ -140,6 +140,13 @@ export function isSingleFolderWorkspaceIdentifier(obj: unknown): obj is ISingleF
|
||||
return typeof singleFolderIdentifier?.id === 'string' && URI.isUri(singleFolderIdentifier.uri);
|
||||
}
|
||||
|
||||
export function isEmptyWorkspaceIdentifier(obj: unknown): obj is IEmptyWorkspaceIdentifier {
|
||||
const emptyWorkspaceIdentifier = obj as IEmptyWorkspaceIdentifier | undefined;
|
||||
return typeof emptyWorkspaceIdentifier?.id === 'string'
|
||||
&& !isSingleFolderWorkspaceIdentifier(obj)
|
||||
&& !isWorkspaceIdentifier(obj);
|
||||
}
|
||||
|
||||
export const EXTENSION_DEVELOPMENT_EMPTY_WINDOW_WORKSPACE: IEmptyWorkspaceIdentifier = { id: 'ext-dev' };
|
||||
|
||||
export function toWorkspaceIdentifier(workspace: IWorkspace): IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined;
|
||||
|
||||
@@ -22,7 +22,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA
|
||||
import { IWorkbenchFileService } from 'vs/workbench/services/files/common/files';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { Schemas, connectionTokenCookieName } from 'vs/base/common/network';
|
||||
import { IAnyWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IAnyWorkspaceIdentifier, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { setFullscreen } from 'vs/base/browser/browser';
|
||||
@@ -297,8 +297,7 @@ export class BrowserMain extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
const lastActiveProfile = environmentService.lastActiveProfile ? userDataProfilesService.profiles.find(p => p.id === environmentService.lastActiveProfile) : undefined;
|
||||
const currentProfile = userDataProfilesService.getOrSetProfileForWorkspace(isWorkspaceIdentifier(workspace) || isSingleFolderWorkspaceIdentifier(workspace) ? workspace : 'empty-window', lastActiveProfile ?? userDataProfilesService.defaultProfile);
|
||||
const currentProfile = userDataProfilesService.getProfileForWorkspace(workspace) ?? userDataProfilesService.defaultProfile;
|
||||
const userDataProfileService = new UserDataProfileService(currentProfile, userDataProfilesService);
|
||||
serviceCollection.set(IUserDataProfileService, userDataProfileService);
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import { localize } from 'vs/nls';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { DidChangeProfilesEvent, IUserDataProfile, IUserDataProfileOptions, IUserDataProfilesService, IUserDataProfileUpdateOptions, WorkspaceIdentifier } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { DidChangeProfilesEvent, IUserDataProfile, IUserDataProfileOptions, IUserDataProfilesService, IUserDataProfileUpdateOptions } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IAnyWorkspaceIdentifier, IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
@@ -113,7 +113,7 @@ export class UserDataProfileManagementService extends Disposable implements IUse
|
||||
this.telemetryService.publicLog2<ProfileManagementActionExecutedEvent, ProfileManagementActionExecutedClassification>('profileManagementActionExecuted', { id: 'switchProfile' });
|
||||
}
|
||||
|
||||
private getWorkspaceIdentifier(): WorkspaceIdentifier {
|
||||
private getWorkspaceIdentifier(): IAnyWorkspaceIdentifier {
|
||||
const workspace = this.workspaceContextService.getWorkspace();
|
||||
switch (this.workspaceContextService.getWorkbenchState()) {
|
||||
case WorkbenchState.FOLDER:
|
||||
@@ -121,7 +121,7 @@ export class UserDataProfileManagementService extends Disposable implements IUse
|
||||
case WorkbenchState.WORKSPACE:
|
||||
return { configPath: workspace.configuration!, id: workspace.id };
|
||||
}
|
||||
return 'empty-window';
|
||||
return { id: workspace.id };
|
||||
}
|
||||
|
||||
private async enterProfile(profile: IUserDataProfile, preserveData: boolean, reloadMessage?: string): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user