Skip to content

Commit 23cd53c

Browse files
authored
move create from profile template action to export group (microsoft#165939)
1 parent 534c691 commit 23cd53c

File tree

2 files changed

+127
-137
lines changed

2 files changed

+127
-137
lines changed

src/vs/workbench/contrib/userDataProfile/browser/userDataProfile.ts

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
1919
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
2020
import { RenameProfileAction } from 'vs/workbench/contrib/userDataProfile/browser/userDataProfileActions';
2121
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
22-
import { CURRENT_PROFILE_CONTEXT, HAS_PROFILES_CONTEXT, IS_CURRENT_PROFILE_TRANSIENT_CONTEXT, IUserDataProfileImportExportService, IUserDataProfileManagementService, IUserDataProfileService, ManageProfilesSubMenu, PROFILES_CATEGORY, PROFILES_ENABLEMENT_CONTEXT, PROFILES_TTILE, PROFILE_EXTENSION, PROFILE_FILTER } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
23-
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
22+
import { CURRENT_PROFILE_CONTEXT, HAS_PROFILES_CONTEXT, isUserDataProfileTemplate, IS_CURRENT_PROFILE_TRANSIENT_CONTEXT, IUserDataProfileImportExportService, IUserDataProfileManagementService, IUserDataProfileService, IUserDataProfileTemplate, ManageProfilesSubMenu, PROFILES_CATEGORY, PROFILES_ENABLEMENT_CONTEXT, PROFILES_TTILE, PROFILE_EXTENSION, PROFILE_FILTER } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
23+
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
2424
import { INotificationService } from 'vs/platform/notification/common/notification';
2525
import { charCount } from 'vs/base/common/strings';
2626
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
2727
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
28-
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
28+
import { IDialogService, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
2929
import { joinPath } from 'vs/base/common/resources';
3030
import { Codicon } from 'vs/base/common/codicons';
31+
import { IFileService } from 'vs/platform/files/common/files';
32+
import { asJson, asText, IRequestService } from 'vs/platform/request/common/request';
33+
import { CancellationToken } from 'vs/base/common/cancellation';
3134

3235
export class UserDataProfilesWorkbenchContribution extends Disposable implements IWorkbenchContribution {
3336

@@ -159,6 +162,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
159162
this.currentprofileActionsDisposable.value.add(this.registerUpdateCurrentProfileShortNameAction());
160163
this.currentprofileActionsDisposable.value.add(this.registerRenameCurrentProfileAction());
161164
this.currentprofileActionsDisposable.value.add(this.registerExportCurrentProfileAction());
165+
this.currentprofileActionsDisposable.value.add(this.registerImportProfileAction());
162166
}
163167

164168
private registerUpdateCurrentProfileShortNameAction(): IDisposable {
@@ -299,10 +303,128 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
299303
title: {
300304
value: localize('export settings profile', "Export Settings Profile ({0})...", that.userDataProfileService.currentProfile.name),
301305
original: `Export Settings Profile (${that.userDataProfileService.currentProfile.name})...`
302-
}
306+
},
307+
precondition: PROFILES_ENABLEMENT_CONTEXT,
303308
},
304309
}));
305310
return disposables;
306311
}
307312

313+
private registerImportProfileAction(): IDisposable {
314+
const disposables = new DisposableStore();
315+
const id = 'workbench.profiles.actions.importProfile';
316+
disposables.add(registerAction2(class ImportProfileAction extends Action2 {
317+
constructor() {
318+
super({
319+
id,
320+
title: {
321+
value: localize('import profile', "Import..."),
322+
original: 'Import...'
323+
},
324+
category: PROFILES_CATEGORY,
325+
f1: true,
326+
menu: [
327+
{
328+
id: ManageProfilesSubMenu,
329+
group: '4_import_export_profiles',
330+
when: PROFILES_ENABLEMENT_CONTEXT,
331+
order: 2
332+
}
333+
]
334+
});
335+
}
336+
337+
async run(accessor: ServicesAccessor) {
338+
const fileDialogService = accessor.get(IFileDialogService);
339+
const quickInputService = accessor.get(IQuickInputService);
340+
const fileService = accessor.get(IFileService);
341+
const requestService = accessor.get(IRequestService);
342+
const userDataProfileImportExportService = accessor.get(IUserDataProfileImportExportService);
343+
const dialogService = accessor.get(IDialogService);
344+
const contextKeyService = accessor.get(IContextKeyService);
345+
const notificationService = accessor.get(INotificationService);
346+
347+
const isSettingProfilesEnabled = contextKeyService.contextMatchesRules(PROFILES_ENABLEMENT_CONTEXT);
348+
349+
if (!isSettingProfilesEnabled) {
350+
if (!(await dialogService.confirm({
351+
title: localize('import profile title', "Import Settings from a Profile"),
352+
message: localize('confiirmation message', "This will replace your current settings. Are you sure you want to continue?"),
353+
})).confirmed) {
354+
return;
355+
}
356+
}
357+
358+
const disposables = new DisposableStore();
359+
const quickPick = disposables.add(quickInputService.createQuickPick());
360+
const updateQuickPickItems = (value?: string) => {
361+
const selectFromFileItem: IQuickPickItem = { label: isSettingProfilesEnabled ? localize('select from file', "Select Settings Profile template file") : localize('import from file', "Import from profile file") };
362+
quickPick.items = value ? [{ label: isSettingProfilesEnabled ? localize('select from url', "Create from template URL") : localize('import from url', "Import from URL"), description: quickPick.value }, selectFromFileItem] : [selectFromFileItem];
363+
};
364+
quickPick.title = isSettingProfilesEnabled ? localize('create from profile template quick pick title', "Create from Settings Profile Template") : localize('import profile quick pick title', "Import Settings from a Profile");
365+
quickPick.placeholder = isSettingProfilesEnabled ? localize('create from profile template placeholder', "Provide a template URL or Select a template file") : localize('import profile placeholder', "Provide profile URL or select profile file to import");
366+
quickPick.ignoreFocusOut = true;
367+
disposables.add(quickPick.onDidChangeValue(updateQuickPickItems));
368+
updateQuickPickItems();
369+
quickPick.matchOnLabel = false;
370+
quickPick.matchOnDescription = false;
371+
disposables.add(quickPick.onDidAccept(async () => {
372+
try {
373+
quickPick.hide();
374+
const profile = quickPick.selectedItems[0].description ? await this.getProfileFromURL(quickPick.value, requestService) : await this.getProfileFromFileSystem(fileDialogService, fileService);
375+
if (profile) {
376+
if (isSettingProfilesEnabled) {
377+
await userDataProfileImportExportService.importProfile(profile);
378+
} else {
379+
await userDataProfileImportExportService.setProfile(profile);
380+
}
381+
}
382+
} catch (error) {
383+
notificationService.error(error);
384+
}
385+
}));
386+
disposables.add(quickPick.onDidHide(() => disposables.dispose()));
387+
quickPick.show();
388+
}
389+
390+
private async getProfileFromFileSystem(fileDialogService: IFileDialogService, fileService: IFileService): Promise<IUserDataProfileTemplate | null> {
391+
const profileLocation = await fileDialogService.showOpenDialog({
392+
canSelectFolders: false,
393+
canSelectFiles: true,
394+
canSelectMany: false,
395+
filters: PROFILE_FILTER,
396+
title: localize('import profile dialog', "Import Profile"),
397+
});
398+
if (!profileLocation) {
399+
return null;
400+
}
401+
const content = (await fileService.readFile(profileLocation[0])).value.toString();
402+
const parsed = JSON.parse(content);
403+
return isUserDataProfileTemplate(parsed) ? parsed : null;
404+
}
405+
406+
private async getProfileFromURL(url: string, requestService: IRequestService): Promise<IUserDataProfileTemplate | null> {
407+
const options = { type: 'GET', url };
408+
const context = await requestService.request(options, CancellationToken.None);
409+
if (context.res.statusCode === 200) {
410+
const result = await asJson(context);
411+
return isUserDataProfileTemplate(result) ? result : null;
412+
} else {
413+
const message = await asText(context);
414+
throw new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`);
415+
}
416+
}
417+
}));
418+
disposables.add(MenuRegistry.appendMenuItem(MenuId.MenubarShare, {
419+
command: {
420+
id,
421+
title: {
422+
value: localize('import settings profile', "Import Settings Profile...",),
423+
original: 'Import Settings Profile...'
424+
},
425+
precondition: PROFILES_ENABLEMENT_CONTEXT,
426+
},
427+
}));
428+
return disposables;
429+
}
308430
}

src/vs/workbench/contrib/userDataProfile/browser/userDataProfileActions.ts

Lines changed: 1 addition & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,12 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { CancellationToken } from 'vs/base/common/cancellation';
7-
import { DisposableStore } from 'vs/base/common/lifecycle';
86
import { localize } from 'vs/nls';
97
import { Action2, IMenuService, registerAction2 } from 'vs/platform/actions/common/actions';
10-
import { IDialogService, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
11-
import { IFileService } from 'vs/platform/files/common/files';
128
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
139
import { INotificationService } from 'vs/platform/notification/common/notification';
1410
import { QuickPickItem, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
15-
import { asJson, asText, IRequestService } from 'vs/platform/request/common/request';
16-
import { IUserDataProfileTemplate, isUserDataProfileTemplate, IUserDataProfileManagementService, IUserDataProfileImportExportService, PROFILES_CATEGORY, ManageProfilesSubMenu, IUserDataProfileService, PROFILES_ENABLEMENT_CONTEXT, HAS_PROFILES_CONTEXT, MANAGE_PROFILES_ACTION_ID, PROFILE_FILTER } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
11+
import { IUserDataProfileManagementService, PROFILES_CATEGORY, ManageProfilesSubMenu, IUserDataProfileService, PROFILES_ENABLEMENT_CONTEXT, HAS_PROFILES_CONTEXT, MANAGE_PROFILES_ACTION_ID } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
1712
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
1813
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
1914
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -141,9 +136,6 @@ registerAction2(class CreateProfileAction extends Action2 {
141136
}, {
142137
id: CreateFromCurrentProfileAction.ID,
143138
label: CreateFromCurrentProfileAction.TITLE.value,
144-
}, {
145-
id: CreateFromTemplateAction.ID,
146-
label: CreateFromTemplateAction.TITLE.value,
147139
}, {
148140
type: 'separator',
149141
}, {
@@ -386,130 +378,6 @@ registerAction2(class SwitchProfileAction extends Action2 {
386378
}
387379
});
388380

389-
class ImportProfileAction extends Action2 {
390-
static readonly ID = 'workbench.profiles.actions.importProfile';
391-
static readonly TITLE = {
392-
value: localize('import profile', "Import from ..."),
393-
original: 'Import...'
394-
};
395-
constructor() {
396-
super({
397-
id: ImportProfileAction.ID,
398-
title: ImportProfileAction.TITLE,
399-
category: PROFILES_CATEGORY,
400-
f1: true,
401-
precondition: PROFILES_ENABLEMENT_CONTEXT?.negate(),
402-
});
403-
}
404-
405-
async run(accessor: ServicesAccessor) {
406-
const fileDialogService = accessor.get(IFileDialogService);
407-
const quickInputService = accessor.get(IQuickInputService);
408-
const fileService = accessor.get(IFileService);
409-
const requestService = accessor.get(IRequestService);
410-
const userDataProfileImportExportService = accessor.get(IUserDataProfileImportExportService);
411-
const dialogService = accessor.get(IDialogService);
412-
const contextKeyService = accessor.get(IContextKeyService);
413-
const notificationService = accessor.get(INotificationService);
414-
415-
const isSettingProfilesEnabled = contextKeyService.contextMatchesRules(PROFILES_ENABLEMENT_CONTEXT);
416-
417-
if (!isSettingProfilesEnabled) {
418-
if (!(await dialogService.confirm({
419-
title: localize('import profile title', "Import Settings from a Profile"),
420-
message: localize('confiirmation message', "This will replace your current settings. Are you sure you want to continue?"),
421-
})).confirmed) {
422-
return;
423-
}
424-
}
425-
426-
const disposables = new DisposableStore();
427-
const quickPick = disposables.add(quickInputService.createQuickPick());
428-
const updateQuickPickItems = (value?: string) => {
429-
const selectFromFileItem: IQuickPickItem = { label: isSettingProfilesEnabled ? localize('select from file', "Select Settings Profile template file") : localize('import from file', "Import from profile file") };
430-
quickPick.items = value ? [{ label: isSettingProfilesEnabled ? localize('select from url', "Create from template URL") : localize('import from url', "Import from URL"), description: quickPick.value }, selectFromFileItem] : [selectFromFileItem];
431-
};
432-
quickPick.title = isSettingProfilesEnabled ? localize('create from profile template quick pick title', "Create from Settings Profile Template") : localize('import profile quick pick title', "Import Settings from a Profile");
433-
quickPick.placeholder = isSettingProfilesEnabled ? localize('create from profile template placeholder', "Provide a template URL or Select a template file") : localize('import profile placeholder', "Provide profile URL or select profile file to import");
434-
quickPick.ignoreFocusOut = true;
435-
disposables.add(quickPick.onDidChangeValue(updateQuickPickItems));
436-
updateQuickPickItems();
437-
quickPick.matchOnLabel = false;
438-
quickPick.matchOnDescription = false;
439-
disposables.add(quickPick.onDidAccept(async () => {
440-
try {
441-
quickPick.hide();
442-
const profile = quickPick.selectedItems[0].description ? await this.getProfileFromURL(quickPick.value, requestService) : await this.getProfileFromFileSystem(fileDialogService, fileService);
443-
if (profile) {
444-
if (isSettingProfilesEnabled) {
445-
await userDataProfileImportExportService.importProfile(profile);
446-
} else {
447-
await userDataProfileImportExportService.setProfile(profile);
448-
}
449-
}
450-
} catch (error) {
451-
notificationService.error(error);
452-
}
453-
}));
454-
disposables.add(quickPick.onDidHide(() => disposables.dispose()));
455-
quickPick.show();
456-
}
457-
458-
private async getProfileFromFileSystem(fileDialogService: IFileDialogService, fileService: IFileService): Promise<IUserDataProfileTemplate | null> {
459-
const profileLocation = await fileDialogService.showOpenDialog({
460-
canSelectFolders: false,
461-
canSelectFiles: true,
462-
canSelectMany: false,
463-
filters: PROFILE_FILTER,
464-
title: localize('import profile dialog', "Import Profile"),
465-
});
466-
if (!profileLocation) {
467-
return null;
468-
}
469-
const content = (await fileService.readFile(profileLocation[0])).value.toString();
470-
const parsed = JSON.parse(content);
471-
return isUserDataProfileTemplate(parsed) ? parsed : null;
472-
}
473-
474-
private async getProfileFromURL(url: string, requestService: IRequestService): Promise<IUserDataProfileTemplate | null> {
475-
const options = { type: 'GET', url };
476-
const context = await requestService.request(options, CancellationToken.None);
477-
if (context.res.statusCode === 200) {
478-
const result = await asJson(context);
479-
return isUserDataProfileTemplate(result) ? result : null;
480-
} else {
481-
const message = await asText(context);
482-
throw new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`);
483-
}
484-
}
485-
486-
}
487-
registerAction2(ImportProfileAction);
488-
489-
class CreateFromTemplateAction extends Action2 {
490-
static readonly ID = 'workbench.profiles.actions.createFromTemplate';
491-
static readonly TITLE = {
492-
value: localize('create from template profile', "Create from a Settings Profile Template..."),
493-
original: 'Create from a Settings Profile Template...'
494-
};
495-
constructor() {
496-
super({
497-
id: CreateFromTemplateAction.ID,
498-
title: CreateFromTemplateAction.TITLE,
499-
category: PROFILES_CATEGORY,
500-
f1: true,
501-
precondition: PROFILES_ENABLEMENT_CONTEXT,
502-
});
503-
}
504-
505-
async run(accessor: ServicesAccessor) {
506-
return accessor.get(ICommandService).executeCommand(ImportProfileAction.ID);
507-
}
508-
509-
}
510-
511-
registerAction2(CreateFromTemplateAction);
512-
513381
// Developer Actions
514382

515383
registerAction2(class CleanupProfilesAction extends Action2 {

0 commit comments

Comments
 (0)