mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-29 09:09:03 +01:00
@@ -1326,7 +1326,6 @@ export class QuickInputController extends Disposable {
|
||||
rightActionBar.domNode.classList.add('quick-input-right-action-bar');
|
||||
|
||||
const headerContainer = dom.append(container, $('.quick-input-header'));
|
||||
const description1 = dom.append(container, $('.quick-input-description'));
|
||||
|
||||
const checkAll = <HTMLInputElement>dom.append(headerContainer, $('input.quick-input-check-all'));
|
||||
checkAll.type = 'checkbox';
|
||||
@@ -1379,6 +1378,8 @@ export class QuickInputController extends Disposable {
|
||||
const widget = dom.append(container, $('.quick-input-html-widget'));
|
||||
widget.tabIndex = -1;
|
||||
|
||||
const description1 = dom.append(container, $('.quick-input-description'));
|
||||
|
||||
const listId = this.idPrefix + 'list';
|
||||
const list = this._register(new QuickInputList(container, listId, this.options));
|
||||
inputBox.setAttribute('aria-controls', listId);
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.profile-type-widget {
|
||||
display: flex;
|
||||
margin: 0px 6px 8px 11px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.profile-type-widget>.profile-type-select-container {
|
||||
overflow: hidden;
|
||||
padding-left: 10px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.profile-type-widget>.profile-type-select-container>.monaco-select-box {
|
||||
cursor: pointer;
|
||||
line-height: 17px;
|
||||
padding: 2px 23px 2px 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
@@ -3,20 +3,19 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/userDataProfileCreateWidget';
|
||||
import { Disposable, DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Action2, IMenuService, ISubmenuItem, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IUserDataProfile, IUserDataProfilesService, ProfileResourceType, UseDefaultProfileFlags } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { RenameProfileAction } from 'vs/workbench/contrib/userDataProfile/browser/userDataProfileActions';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { CURRENT_PROFILE_CONTEXT, HAS_PROFILES_CONTEXT, IS_CURRENT_PROFILE_TRANSIENT_CONTEXT, IS_PROFILE_IMPORT_IN_PROGRESS_CONTEXT, IUserDataProfileImportExportService, IUserDataProfileManagementService, IUserDataProfileService, PROFILES_CATEGORY, PROFILE_FILTER, IS_PROFILE_EXPORT_IN_PROGRESS_CONTEXT, ProfilesMenu, PROFILES_ENABLEMENT_CONTEXT, PROFILES_TITLE } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
|
||||
import { IQuickInputService, IQuickPickItem, QuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -31,32 +30,18 @@ import { IRequestService, asJson } from 'vs/platform/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
||||
const CREATE_EMPTY_PROFILE_ACTION_ID = 'workbench.profiles.actions.createEmptyProfile';
|
||||
const CREATE_EMPTY_PROFILE_ACTION_TITLE = {
|
||||
value: localize('create empty profile', "Create an Empty Profile..."),
|
||||
original: 'Create an Empty Profile...'
|
||||
};
|
||||
|
||||
const CREATE_FROM_CURRENT_PROFILE_ACTION_ID = 'workbench.profiles.actions.createFromCurrentProfile';
|
||||
const CREATE_FROM_CURRENT_PROFILE_ACTION_TITLE = {
|
||||
value: localize('save profile as', "Save Current Profile As..."),
|
||||
original: 'Save Current Profile As...'
|
||||
};
|
||||
|
||||
const CREATE_NEW_PROFILE_ACTION_ID = 'workbench.profiles.actions.createNewProfile';
|
||||
const CREATE_NEW_PROFILE_ACTION_TITLE = {
|
||||
value: localize('create new profile', "Create New Profile..."),
|
||||
original: 'Create New Profile...'
|
||||
};
|
||||
import { $, append } from 'vs/base/browser/dom';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ISelectOptionItem, SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { defaultSelectBoxStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
|
||||
interface IProfileTemplateInfo {
|
||||
readonly name: string;
|
||||
readonly url: string;
|
||||
}
|
||||
|
||||
type IProfileTemplateQuickPickItem = IQuickPickItem & IProfileTemplateInfo;
|
||||
|
||||
export class UserDataProfilesWorkbenchContribution extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
private readonly currentProfileContext: IContextKey<string>;
|
||||
@@ -77,6 +62,8 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IRequestService private readonly requestService: IRequestService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
) {
|
||||
super();
|
||||
@@ -115,9 +102,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
this.registerCurrentProfilesActions();
|
||||
this._register(Event.any(this.userDataProfileService.onDidChangeCurrentProfile, this.userDataProfileService.onDidUpdateCurrentProfile)(() => this.registerCurrentProfilesActions()));
|
||||
|
||||
this.registerCreateEmptyProfileAction();
|
||||
this.registerCreateFromCurrentProfileAction();
|
||||
this.registerCreateNewProfileAction();
|
||||
this.registerCreateProfileAction();
|
||||
this.registerDeleteProfileAction();
|
||||
|
||||
@@ -214,21 +199,21 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
private readonly currentprofileActionsDisposable = this._register(new MutableDisposable<DisposableStore>());
|
||||
private registerCurrentProfilesActions(): void {
|
||||
this.currentprofileActionsDisposable.value = new DisposableStore();
|
||||
this.currentprofileActionsDisposable.value.add(this.registerRenameCurrentProfileAction());
|
||||
this.currentprofileActionsDisposable.value.add(this.registerEditCurrentProfileAction());
|
||||
this.currentprofileActionsDisposable.value.add(this.registerShowCurrentProfileContentsAction());
|
||||
this.currentprofileActionsDisposable.value.add(this.registerExportCurrentProfileAction());
|
||||
this.currentprofileActionsDisposable.value.add(this.registerImportProfileAction());
|
||||
}
|
||||
|
||||
private registerRenameCurrentProfileAction(): IDisposable {
|
||||
private registerEditCurrentProfileAction(): IDisposable {
|
||||
const that = this;
|
||||
return registerAction2(class RenameCurrentProfileAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: `workbench.profiles.actions.renameCurrentProfile`,
|
||||
id: `workbench.profiles.actions.editCurrentProfile`,
|
||||
title: {
|
||||
value: localize('rename profile', "Rename..."),
|
||||
original: `Rename...`
|
||||
value: localize('edit profile', "Edit..."),
|
||||
original: `Edit...`
|
||||
},
|
||||
menu: [
|
||||
{
|
||||
@@ -240,8 +225,8 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
]
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ICommandService).executeCommand(RenameProfileAction.ID, that.userDataProfileService.currentProfile);
|
||||
run() {
|
||||
return that.saveProfile(that.userDataProfileService.currentProfile);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -413,8 +398,11 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
this._register(registerAction2(class CreateFromCurrentProfileAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: CREATE_FROM_CURRENT_PROFILE_ACTION_ID,
|
||||
title: CREATE_FROM_CURRENT_PROFILE_ACTION_TITLE,
|
||||
id: 'workbench.profiles.actions.createFromCurrentProfile',
|
||||
title: {
|
||||
value: localize('save profile as', "Save Current Profile As..."),
|
||||
original: 'Save Current Profile As...'
|
||||
},
|
||||
category: PROFILES_CATEGORY,
|
||||
f1: true,
|
||||
precondition: PROFILES_ENABLEMENT_CONTEXT
|
||||
@@ -422,86 +410,35 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
}
|
||||
|
||||
run(accessor: ServicesAccessor) {
|
||||
return that.createFromCurrentProfile();
|
||||
return that.saveProfile(undefined, that.userDataProfileService.currentProfile);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private registerCreateNewProfileAction(): void {
|
||||
const that = this;
|
||||
this._register(registerAction2(class CreateFromCurrentProfileAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: CREATE_NEW_PROFILE_ACTION_ID,
|
||||
title: CREATE_NEW_PROFILE_ACTION_TITLE,
|
||||
category: PROFILES_CATEGORY,
|
||||
f1: true,
|
||||
precondition: PROFILES_ENABLEMENT_CONTEXT
|
||||
});
|
||||
}
|
||||
private async saveProfile(profile: IUserDataProfile): Promise<void>;
|
||||
private async saveProfile(profile?: IUserDataProfile, source?: IUserDataProfile | string): Promise<void>;
|
||||
private async saveProfile(profile?: IUserDataProfile, source?: IUserDataProfile | string): Promise<void> {
|
||||
|
||||
run() {
|
||||
return that.createNewProfile();
|
||||
}
|
||||
}));
|
||||
}
|
||||
type CreateProfileInfoClassification = {
|
||||
owner: 'sandy081';
|
||||
comment: 'Report when profile is about to be created';
|
||||
};
|
||||
this.telemetryService.publicLog2<{}, CreateProfileInfoClassification>('userDataProfile.startCreate');
|
||||
|
||||
private registerCreateEmptyProfileAction(): void {
|
||||
const that = this;
|
||||
this._register(registerAction2(class CreateEmptyProfileAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: CREATE_EMPTY_PROFILE_ACTION_ID,
|
||||
title: CREATE_EMPTY_PROFILE_ACTION_TITLE,
|
||||
category: PROFILES_CATEGORY,
|
||||
f1: true,
|
||||
precondition: PROFILES_ENABLEMENT_CONTEXT
|
||||
});
|
||||
}
|
||||
const disposables = new DisposableStore();
|
||||
const title = profile ? localize('save profile', "Edit Profile...") : localize('create new profle', "Create New Profile...");
|
||||
|
||||
run(accessor: ServicesAccessor) {
|
||||
return that.createEmptyProfile();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private async createEmptyProfile(): Promise<void> {
|
||||
const name = await this.getNameForProfile(localize('create empty profile', "Create an Empty Profile..."));
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.userDataProfileManagementService.createAndEnterProfile(name, undefined);
|
||||
} catch (error) {
|
||||
this.notificationService.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
private async createFromCurrentProfile(): Promise<void> {
|
||||
const name = await this.getNameForProfile(localize('create from current profle', "Create from Current Profile..."));
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.userDataProfileImportExportService.SaveCurrentProfileAs(name);
|
||||
} catch (error) {
|
||||
this.notificationService.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
private async createNewProfile(): Promise<void> {
|
||||
const title = localize('create new profle', "Create New Profile...");
|
||||
|
||||
const settings: IQuickPickItem = { id: ProfileResourceType.Settings, label: localize('settings', "Settings"), picked: true };
|
||||
const keybindings: IQuickPickItem = { id: ProfileResourceType.Keybindings, label: localize('keybindings', "Keyboard Shortcuts"), picked: true };
|
||||
const snippets: IQuickPickItem = { id: ProfileResourceType.Snippets, label: localize('snippets', "User Snippets"), picked: true };
|
||||
const tasks: IQuickPickItem = { id: ProfileResourceType.Tasks, label: localize('tasks', "User Tasks"), picked: true };
|
||||
const extensions: IQuickPickItem = { id: ProfileResourceType.Extensions, label: localize('extensions', "Extensions"), picked: true };
|
||||
const settings: IQuickPickItem & { id: ProfileResourceType } = { id: ProfileResourceType.Settings, label: localize('settings', "Settings"), picked: profile?.useDefaultFlags?.settings };
|
||||
const keybindings: IQuickPickItem & { id: ProfileResourceType } = { id: ProfileResourceType.Keybindings, label: localize('keybindings', "Keyboard Shortcuts"), picked: profile?.useDefaultFlags?.keybindings };
|
||||
const snippets: IQuickPickItem & { id: ProfileResourceType } = { id: ProfileResourceType.Snippets, label: localize('snippets', "User Snippets"), picked: profile?.useDefaultFlags?.snippets };
|
||||
const tasks: IQuickPickItem & { id: ProfileResourceType } = { id: ProfileResourceType.Tasks, label: localize('tasks', "User Tasks"), picked: profile?.useDefaultFlags?.tasks };
|
||||
const extensions: IQuickPickItem & { id: ProfileResourceType } = { id: ProfileResourceType.Extensions, label: localize('extensions', "Extensions"), picked: profile?.useDefaultFlags?.extensions };
|
||||
const resources = [settings, keybindings, snippets, tasks, extensions];
|
||||
|
||||
const quickPick = this.quickInputService.createQuickPick();
|
||||
quickPick.title = title;
|
||||
quickPick.placeholder = localize('name placeholder', "Name the new profile");
|
||||
quickPick.placeholder = localize('name placeholder', "Profile name");
|
||||
quickPick.value = profile?.name ?? '';
|
||||
quickPick.canSelectMany = true;
|
||||
quickPick.matchOnDescription = false;
|
||||
quickPick.matchOnDetail = false;
|
||||
@@ -512,42 +449,109 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
quickPick.customButton = true;
|
||||
quickPick.hideCheckAll = true;
|
||||
quickPick.ignoreFocusOut = true;
|
||||
quickPick.customLabel = localize('create', "Create Profile");
|
||||
quickPick.description = localize('customise the profile', "Choose what to configure in the profile. Unselected items are shared from the default profile.");
|
||||
quickPick.items = resources;
|
||||
quickPick.selectedItems = resources.filter(item => item.picked);
|
||||
quickPick.customLabel = profile ? localize('save', "Save") : localize('create', "Create");
|
||||
quickPick.description = localize('customise the profile', "Select configurations to share from the Default profile:");
|
||||
quickPick.items = [...resources];
|
||||
|
||||
const updateSelection = () => {
|
||||
quickPick.selectedItems = resources.filter(item => item.picked);
|
||||
};
|
||||
updateSelection();
|
||||
|
||||
const validate = () => {
|
||||
if (!profile && this.userDataProfilesService.profiles.some(p => p.name === quickPick.value)) {
|
||||
quickPick.validationMessage = localize('profileExists', "Profile with name {0} already exists.", quickPick.value);
|
||||
quickPick.severity = Severity.Error;
|
||||
return;
|
||||
}
|
||||
if (resources.every(resource => resource.picked)) {
|
||||
quickPick.validationMessage = localize('cannot share all', "Cannot share all configurations from the Default Profile.");
|
||||
quickPick.severity = Severity.Error;
|
||||
return;
|
||||
}
|
||||
quickPick.severity = Severity.Ignore;
|
||||
quickPick.validationMessage = undefined;
|
||||
};
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
disposables.add(quickPick.onDidChangeSelection(items => {
|
||||
for (const resource of resources) {
|
||||
resource.picked = items.includes(resource);
|
||||
}
|
||||
validate();
|
||||
}));
|
||||
|
||||
disposables.add(quickPick.onDidChangeValue(value => {
|
||||
if (this.userDataProfilesService.profiles.some(p => p.name === value)) {
|
||||
quickPick.validationMessage = localize('profileExists', "Profile with name {0} already exists.", value);
|
||||
quickPick.severity = Severity.Error;
|
||||
} else {
|
||||
quickPick.severity = Severity.Ignore;
|
||||
quickPick.validationMessage = undefined;
|
||||
}
|
||||
}));
|
||||
disposables.add(quickPick.onDidChangeValue(validate));
|
||||
|
||||
let result: { name: string; items: ReadonlyArray<IQuickPickItem> } | undefined;
|
||||
disposables.add(quickPick.onDidCustom(async () => {
|
||||
disposables.add(Event.any(quickPick.onDidCustom, quickPick.onDidAccept)(() => {
|
||||
if (!quickPick.value) {
|
||||
quickPick.validationMessage = localize('name required', "Provide a name for the new profile");
|
||||
quickPick.severity = Severity.Error;
|
||||
}
|
||||
if (quickPick.validationMessage) {
|
||||
return;
|
||||
}
|
||||
if (resources.some(resource => quickPick.selectedItems.includes(resource))) {
|
||||
result = { name: quickPick.value, items: quickPick.selectedItems };
|
||||
quickPick.hide();
|
||||
}
|
||||
result = { name: quickPick.value, items: quickPick.selectedItems };
|
||||
quickPick.hide();
|
||||
quickPick.severity = Severity.Ignore;
|
||||
quickPick.validationMessage = undefined;
|
||||
}));
|
||||
|
||||
if (!profile) {
|
||||
const domNode = $('.profile-type-widget');
|
||||
append(domNode, $('.profile-type-create-label', undefined, localize('create from', "Copy from:")));
|
||||
const separator = { text: '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500', isDisabled: true };
|
||||
const profileOptions: (ISelectOptionItem & { id?: string; source?: IUserDataProfile | string })[] = [];
|
||||
profileOptions.push({ text: localize('empty profile', "None") });
|
||||
const templates = await this.getProfileTemplatesFromProduct();
|
||||
if (templates.length) {
|
||||
profileOptions.push({ ...separator, decoratorRight: localize('from templates', "Profile Templates") });
|
||||
for (const template of templates) {
|
||||
profileOptions.push({ text: template.name, id: template.url, source: template.url });
|
||||
}
|
||||
}
|
||||
profileOptions.push({ ...separator, decoratorRight: localize('from existing profiles', "Existing Profiles") });
|
||||
for (const profile of this.userDataProfilesService.profiles) {
|
||||
profileOptions.push({ text: profile.name, id: profile.id, source: profile });
|
||||
}
|
||||
|
||||
const findOptionIndex = () => {
|
||||
const index = profileOptions.findIndex(option => {
|
||||
if (isString(source)) {
|
||||
return option.id === source;
|
||||
} else if (source) {
|
||||
return option.id === source.id;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return index > -1 ? index : 0;
|
||||
};
|
||||
|
||||
const selectBox = disposables.add(this.instantiationService.createInstance(SelectBox, profileOptions, findOptionIndex(), this.contextViewService, defaultSelectBoxStyles, { useCustomDrawn: true }));
|
||||
selectBox.render(append(domNode, $('.profile-type-select-container')));
|
||||
quickPick.widget = domNode;
|
||||
|
||||
const updateOptions = () => {
|
||||
const index = findOptionIndex();
|
||||
if (index <= 0) {
|
||||
return;
|
||||
}
|
||||
const option = profileOptions[index];
|
||||
if (!isString(option.source)) {
|
||||
for (const resource of resources) {
|
||||
resource.picked = option.source?.useDefaultFlags?.[resource.id];
|
||||
}
|
||||
updateSelection();
|
||||
}
|
||||
};
|
||||
|
||||
updateOptions();
|
||||
disposables.add(selectBox.onDidSelect(({ index }) => {
|
||||
source = profileOptions[index].source;
|
||||
updateOptions();
|
||||
}));
|
||||
}
|
||||
|
||||
quickPick.show();
|
||||
|
||||
await new Promise<void>((c, e) => {
|
||||
@@ -558,37 +562,36 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
this.telemetryService.publicLog2<{}, CreateProfileInfoClassification>('userDataProfile.cancelCreate');
|
||||
return;
|
||||
}
|
||||
|
||||
const { name, items } = result;
|
||||
this.telemetryService.publicLog2<{}, CreateProfileInfoClassification>('userDataProfile.successCreate');
|
||||
|
||||
try {
|
||||
const useDefaultFlags: UseDefaultProfileFlags | undefined = items.length !== resources.length ? {
|
||||
settings: !items.includes(settings),
|
||||
keybindings: !items.includes(keybindings),
|
||||
snippets: !items.includes(snippets),
|
||||
tasks: !items.includes(tasks),
|
||||
extensions: !items.includes(extensions)
|
||||
const useDefaultFlags: UseDefaultProfileFlags | undefined = result.items.length ? {
|
||||
settings: result.items.includes(settings),
|
||||
keybindings: result.items.includes(keybindings),
|
||||
snippets: result.items.includes(snippets),
|
||||
tasks: result.items.includes(tasks),
|
||||
extensions: result.items.includes(extensions)
|
||||
} : undefined;
|
||||
await this.userDataProfileManagementService.createAndEnterProfile(name, { useDefaultFlags });
|
||||
if (profile) {
|
||||
await this.userDataProfileManagementService.updateProfile(profile, { name: result.name, useDefaultFlags });
|
||||
} else {
|
||||
if (isString(source)) {
|
||||
await this.userDataProfileImportExportService.importProfile(URI.parse(source), { mode: 'apply', name: result.name, useDefaultFlags });
|
||||
} else if (source) {
|
||||
await this.userDataProfileImportExportService.createFromProfile(source, result.name, { useDefaultFlags });
|
||||
} else {
|
||||
await this.userDataProfileManagementService.createAndEnterProfile(result.name, { useDefaultFlags });
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.notificationService.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
private async getNameForProfile(title: string): Promise<string | undefined> {
|
||||
return this.quickInputService.input({
|
||||
placeHolder: localize('name', "Profile name"),
|
||||
title,
|
||||
validateInput: async (value: string) => {
|
||||
if (this.userDataProfilesService.profiles.some(p => p.name === value)) {
|
||||
return localize('profileExists', "Profile with name {0} already exists.", value);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private registerCreateProfileAction(): void {
|
||||
const that = this;
|
||||
this._register(registerAction2(class CreateProfileAction extends Action2 {
|
||||
@@ -601,6 +604,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
},
|
||||
category: PROFILES_CATEGORY,
|
||||
precondition: PROFILES_ENABLEMENT_CONTEXT,
|
||||
f1: true,
|
||||
menu: [
|
||||
{
|
||||
id: ProfilesMenu,
|
||||
@@ -613,52 +617,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const quickInputService = accessor.get(IQuickInputService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const userDataProfileImportExportService = accessor.get(IUserDataProfileImportExportService);
|
||||
const quickPickItems: QuickPickItem[] = [{
|
||||
id: CREATE_EMPTY_PROFILE_ACTION_ID,
|
||||
label: localize('empty profile', "Empty Profile..."),
|
||||
}, {
|
||||
id: CREATE_NEW_PROFILE_ACTION_ID,
|
||||
label: localize('new profile', "New Profile..."),
|
||||
}, {
|
||||
type: 'separator',
|
||||
}, {
|
||||
id: CREATE_FROM_CURRENT_PROFILE_ACTION_ID,
|
||||
label: localize('using current', "Save Current Profile As..."),
|
||||
}];
|
||||
const profileTemplateQuickPickItems = await that.getProfileTemplatesQuickPickItems();
|
||||
if (profileTemplateQuickPickItems.length) {
|
||||
quickPickItems.push({
|
||||
type: 'separator',
|
||||
label: localize('templates', "Profile Templates")
|
||||
}, ...profileTemplateQuickPickItems);
|
||||
}
|
||||
const pick = await quickInputService.pick(quickPickItems,
|
||||
{
|
||||
hideInput: true,
|
||||
canPickMany: false,
|
||||
title: localize('create profile title', "Create Profile...")
|
||||
});
|
||||
if (pick) {
|
||||
if (pick.id) {
|
||||
return commandService.executeCommand(pick.id);
|
||||
}
|
||||
if ((<IProfileTemplateQuickPickItem>pick).url) {
|
||||
type ProfileCreationFromTemplateActionClassification = {
|
||||
owner: 'sandy081';
|
||||
comment: 'Report profile creation from template action';
|
||||
profileName: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Name of the profile created from template' };
|
||||
};
|
||||
type ProfileCreationFromTemplateActionEvent = {
|
||||
profileName: string;
|
||||
};
|
||||
that.telemetryService.publicLog2<ProfileCreationFromTemplateActionEvent, ProfileCreationFromTemplateActionClassification>('profileCreationAction:builtinTemplate', { profileName: (<IProfileTemplateQuickPickItem>pick).name });
|
||||
const uri = URI.parse((<IProfileTemplateQuickPickItem>pick).url);
|
||||
return userDataProfileImportExportService.importProfile(uri, { mode: 'apply' });
|
||||
}
|
||||
}
|
||||
return that.saveProfile();
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -736,18 +695,6 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
|
||||
}));
|
||||
}
|
||||
|
||||
private async getProfileTemplatesQuickPickItems(): Promise<IProfileTemplateQuickPickItem[]> {
|
||||
const quickPickItems: IProfileTemplateQuickPickItem[] = [];
|
||||
const profileTemplates = await this.getProfileTemplatesFromProduct();
|
||||
for (const template of profileTemplates) {
|
||||
quickPickItems.push({
|
||||
label: template.name,
|
||||
...template
|
||||
});
|
||||
}
|
||||
return quickPickItems;
|
||||
}
|
||||
|
||||
private async getProfileTemplatesFromProduct(): Promise<IProfileTemplateInfo[]> {
|
||||
if (this.productService.profileTemplatesUrl) {
|
||||
try {
|
||||
|
||||
+23
-23
@@ -18,7 +18,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Extensions, ITreeItem, ITreeViewDataProvider, ITreeViewDescriptor, IViewContainersRegistry, IViewDescriptorService, IViewsRegistry, IViewsService, TreeItemCollapsibleState, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { IUserDataProfile, IUserDataProfilesService, ProfileResourceType, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IUserDataProfile, IUserDataProfileOptions, IUserDataProfilesService, ProfileResourceType, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
@@ -209,11 +209,11 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
return;
|
||||
}
|
||||
if (mode === 'preview') {
|
||||
await this.previewProfile(profileTemplate);
|
||||
await this.previewProfile(profileTemplate, options);
|
||||
} else if (mode === 'apply') {
|
||||
await this.createAndSwitch(profileTemplate, false, true, localize('create profile', "Create Profile"));
|
||||
await this.createAndSwitch(profileTemplate, false, true, options, localize('create profile', "Create Profile"));
|
||||
} else if (mode === 'both') {
|
||||
await this.importAndPreviewProfile(uri, profileTemplate);
|
||||
await this.importAndPreviewProfile(uri, profileTemplate, options);
|
||||
}
|
||||
} finally {
|
||||
disposables.dispose();
|
||||
@@ -249,11 +249,11 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
}
|
||||
}
|
||||
|
||||
async SaveCurrentProfileAs(name: string): Promise<void> {
|
||||
const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile);
|
||||
async createFromProfile(profile: IUserDataProfile, name: string, options?: IUserDataProfileOptions): Promise<void> {
|
||||
const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, profile);
|
||||
try {
|
||||
const profileTemplate = await userDataProfilesExportState.getProfileTemplate(name, undefined);
|
||||
await this.createAndSwitch(profileTemplate, false, true, localize('save profile as', "Save Profile As"));
|
||||
await this.createAndSwitch(profileTemplate, false, true, options, localize('create profile', "Create Profile"));
|
||||
} finally {
|
||||
userDataProfilesExportState.dispose();
|
||||
}
|
||||
@@ -269,7 +269,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
sticky: true,
|
||||
}, async progress => {
|
||||
const reportProgress = (message: string) => progress.report({ message: localize('troubleshoot profile progress', "Setting up Troubleshoot Profile: {0}", message) });
|
||||
const profile = await this.createProfile(profileTemplate, true, false, reportProgress);
|
||||
const profile = await this.createProfile(profileTemplate, true, false, { useDefaultFlags: this.userDataProfileService.currentProfile.useDefaultFlags }, reportProgress);
|
||||
if (profile) {
|
||||
reportProgress(localize('progress extensions', "Applying Extensions..."));
|
||||
await this.instantiationService.createInstance(ExtensionsResource).copy(this.userDataProfileService.currentProfile, profile, true);
|
||||
@@ -362,21 +362,21 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
return profileTemplate;
|
||||
}
|
||||
|
||||
private async importAndPreviewProfile(uri: URI, profileTemplate: IUserDataProfileTemplate): Promise<void> {
|
||||
private async importAndPreviewProfile(uri: URI, profileTemplate: IUserDataProfileTemplate, options: IUserDataProfileOptions | undefined): Promise<void> {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
try {
|
||||
const userDataProfileImportState = disposables.add(this.instantiationService.createInstance(UserDataProfileImportState, profileTemplate));
|
||||
profileTemplate = await userDataProfileImportState.getProfileTemplateToImport();
|
||||
|
||||
const importedProfile = await this.createAndSwitch(profileTemplate, true, false, localize('preview profile', "Preview Profile"));
|
||||
const importedProfile = await this.createAndSwitch(profileTemplate, true, false, options, localize('preview profile', "Preview Profile"));
|
||||
|
||||
if (!importedProfile) {
|
||||
return;
|
||||
}
|
||||
|
||||
const barrier = new Barrier();
|
||||
const importAction = this.getCreateAction(barrier, userDataProfileImportState);
|
||||
const importAction = this.getCreateAction(barrier, userDataProfileImportState, options);
|
||||
const primaryAction = isWeb
|
||||
? new Action('importInDesktop', localize('import in desktop', "Create Profile in {0}", this.productService.nameLong), undefined, true, async () => this.openerService.open(uri, { openExternal: true }))
|
||||
: importAction;
|
||||
@@ -435,15 +435,15 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
}
|
||||
}
|
||||
|
||||
private async previewProfile(profileTemplate: IUserDataProfileTemplate): Promise<void> {
|
||||
private async previewProfile(profileTemplate: IUserDataProfileTemplate, options: IUserDataProfileOptions | undefined): Promise<void> {
|
||||
const disposables = new DisposableStore();
|
||||
try {
|
||||
const userDataProfileImportState = disposables.add(this.instantiationService.createInstance(UserDataProfileImportState, profileTemplate));
|
||||
if (userDataProfileImportState.isEmpty()) {
|
||||
await this.createAndSwitch(profileTemplate, false, true, localize('create profile', "Create Profile"));
|
||||
await this.createAndSwitch(profileTemplate, false, true, options, localize('create profile', "Create Profile"));
|
||||
} else {
|
||||
const barrier = new Barrier();
|
||||
const importAction = this.getCreateAction(barrier, userDataProfileImportState);
|
||||
const importAction = this.getCreateAction(barrier, userDataProfileImportState, options);
|
||||
await this.showProfilePreviewView(IMPORT_PROFILE_PREVIEW_VIEW, profileTemplate.name, importAction, new BarrierAction(barrier, new Action('cancel', localize('cancel', "Cancel")), this.notificationService), false, userDataProfileImportState);
|
||||
await barrier.wait();
|
||||
await this.hideProfilePreviewView(IMPORT_PROFILE_PREVIEW_VIEW);
|
||||
@@ -453,16 +453,16 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
}
|
||||
}
|
||||
|
||||
private getCreateAction(barrier: Barrier, userDataProfileImportState: UserDataProfileImportState): IAction {
|
||||
private getCreateAction(barrier: Barrier, userDataProfileImportState: UserDataProfileImportState, options: IUserDataProfileOptions | undefined): IAction {
|
||||
const importAction = new BarrierAction(barrier, new Action('title', localize('import', "Create Profile"), undefined, true, async () => {
|
||||
importAction.enabled = false;
|
||||
const profileTemplate = await userDataProfileImportState.getProfileTemplateToImport();
|
||||
return this.createAndSwitch(profileTemplate, false, true, localize('create profile', "Create Profile"));
|
||||
return this.createAndSwitch(profileTemplate, false, true, options, localize('create profile', "Create Profile"));
|
||||
}), this.notificationService);
|
||||
return importAction;
|
||||
}
|
||||
|
||||
private async createAndSwitch(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, title: string): Promise<IUserDataProfile | undefined> {
|
||||
private async createAndSwitch(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, options: IUserDataProfileOptions | undefined, title: string): Promise<IUserDataProfile | undefined> {
|
||||
return this.progressService.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
delay: 500,
|
||||
@@ -471,7 +471,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
title = `${title} (${profileTemplate.name})`;
|
||||
progress.report({ message: title });
|
||||
const reportProgress = (message: string) => progress.report({ message: `${title}: ${message}` });
|
||||
const profile = await this.createProfile(profileTemplate, temporaryProfile, extensions, reportProgress);
|
||||
const profile = await this.createProfile(profileTemplate, temporaryProfile, extensions, options, reportProgress);
|
||||
if (profile) {
|
||||
reportProgress(localize('switching profile', "Switching Profile..."));
|
||||
await this.userDataProfileManagementService.switchProfile(profile);
|
||||
@@ -480,8 +480,8 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
});
|
||||
}
|
||||
|
||||
private async createProfile(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, progress: (message: string) => void): Promise<IUserDataProfile | undefined> {
|
||||
const profile = await this.getProfileToImport(profileTemplate, temporaryProfile);
|
||||
private async createProfile(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, options: IUserDataProfileOptions | undefined, progress: (message: string) => void): Promise<IUserDataProfile | undefined> {
|
||||
const profile = await this.getProfileToImport(profileTemplate, temporaryProfile, options);
|
||||
if (!profile) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -569,12 +569,12 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
return result?.id;
|
||||
}
|
||||
|
||||
private async getProfileToImport(profileTemplate: IUserDataProfileTemplate, temp: boolean): Promise<IUserDataProfile | undefined> {
|
||||
private async getProfileToImport(profileTemplate: IUserDataProfileTemplate, temp: boolean, options: IUserDataProfileOptions | undefined): Promise<IUserDataProfile | undefined> {
|
||||
const profileName = profileTemplate.name;
|
||||
const profile = this.userDataProfilesService.profiles.find(p => p.name === profileName);
|
||||
if (profile) {
|
||||
if (temp) {
|
||||
return this.userDataProfilesService.createNamedProfile(`${profileName} ${this.getProfileNameIndex(profileName)}`, { shortName: profileTemplate.shortName, transient: temp });
|
||||
return this.userDataProfilesService.createNamedProfile(`${profileName} ${this.getProfileNameIndex(profileName)}`, { ...options, shortName: profileTemplate.shortName, transient: temp });
|
||||
}
|
||||
|
||||
enum ImportProfileChoice {
|
||||
@@ -625,7 +625,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
|
||||
}
|
||||
return this.userDataProfilesService.createNamedProfile(name);
|
||||
} else {
|
||||
return this.userDataProfilesService.createNamedProfile(profileName, { shortName: profileTemplate.shortName, transient: temp });
|
||||
return this.userDataProfilesService.createNamedProfile(profileName, { ...options, shortName: profileTemplate.shortName, transient: temp });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,8 @@ export function toUserDataProfileUri(path: string, productService: IProductServi
|
||||
});
|
||||
}
|
||||
|
||||
export interface IProfileImportOptions {
|
||||
export interface IProfileImportOptions extends IUserDataProfileOptions {
|
||||
readonly name?: string;
|
||||
readonly mode?: 'preview' | 'apply' | 'both';
|
||||
}
|
||||
|
||||
@@ -87,7 +88,7 @@ export interface IUserDataProfileImportExportService {
|
||||
exportProfile(): Promise<void>;
|
||||
importProfile(uri: URI, options?: IProfileImportOptions): Promise<void>;
|
||||
showProfileContents(): Promise<void>;
|
||||
SaveCurrentProfileAs(name: string): Promise<void>;
|
||||
createFromProfile(profile: IUserDataProfile, name: string, options?: IUserDataProfileOptions): Promise<void>;
|
||||
createTroubleshootProfile(): Promise<void>;
|
||||
setProfile(profile: IUserDataProfileTemplate): Promise<void>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user