33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
55
6- import 'vs/css!./media/userDataProfileCreateWidget' ;
76import { Disposable , DisposableStore , IDisposable , MutableDisposable } from 'vs/base/common/lifecycle' ;
87import { isWeb } from 'vs/base/common/platform' ;
9- import { Event } from 'vs/base/common/event' ;
108import { ServicesAccessor } from 'vs/editor/browser/editorExtensions' ;
119import { localize } from 'vs/nls' ;
1210import { Action2 , IMenuService , ISubmenuItem , MenuId , MenuRegistry , registerAction2 } from 'vs/platform/actions/common/actions' ;
1311import { ContextKeyExpr , IContextKey , IContextKeyService } from 'vs/platform/contextkey/common/contextkey' ;
14- import { IUserDataProfile , IUserDataProfilesService , ProfileResourceType , UseDefaultProfileFlags } from 'vs/platform/userDataProfile/common/userDataProfile' ;
12+ import { IUserDataProfile , IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile' ;
1513import { IWorkbenchContribution } from 'vs/workbench/common/contributions' ;
1614import { ILifecycleService , LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle' ;
17- 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' ;
15+ 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 , IProfileTemplateInfo } from 'vs/workbench/services/userDataProfile/common/userDataProfile' ;
1816import { IQuickInputService , IQuickPickItem , IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput' ;
1917import { INotificationService } from 'vs/platform/notification/common/notification' ;
2018import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs' ;
@@ -25,22 +23,6 @@ import { IWorkspaceTagsService } from 'vs/workbench/contrib/tags/common/workspac
2523import { getErrorMessage } from 'vs/base/common/errors' ;
2624import { Categories } from 'vs/platform/action/common/actionCommonCategories' ;
2725import { IOpenerService } from 'vs/platform/opener/common/opener' ;
28- import { IProductService } from 'vs/platform/product/common/productService' ;
29- import { IRequestService , asJson } from 'vs/platform/request/common/request' ;
30- import { CancellationToken } from 'vs/base/common/cancellation' ;
31- import { ILogService } from 'vs/platform/log/common/log' ;
32- import Severity from 'vs/base/common/severity' ;
33- import { $ , append } from 'vs/base/browser/dom' ;
34- import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
35- import { ISelectOptionItem , SelectBox } from 'vs/base/browser/ui/selectBox/selectBox' ;
36- import { IContextViewService } from 'vs/platform/contextview/browser/contextView' ;
37- import { defaultSelectBoxStyles } from 'vs/platform/theme/browser/defaultStyles' ;
38- import { isString } from 'vs/base/common/types' ;
39-
40- interface IProfileTemplateInfo {
41- readonly name : string ;
42- readonly url : string ;
43- }
4426
4527type IProfileTemplateQuickPickItem = IQuickPickItem & IProfileTemplateInfo ;
4628
@@ -59,14 +41,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
5941 @IWorkspaceContextService private readonly workspaceContextService : IWorkspaceContextService ,
6042 @IWorkspaceTagsService private readonly workspaceTagsService : IWorkspaceTagsService ,
6143 @IContextKeyService contextKeyService : IContextKeyService ,
62- @IQuickInputService private readonly quickInputService : IQuickInputService ,
63- @INotificationService private readonly notificationService : INotificationService ,
6444 @ILifecycleService private readonly lifecycleService : ILifecycleService ,
65- @IProductService private readonly productService : IProductService ,
66- @IRequestService private readonly requestService : IRequestService ,
67- @IInstantiationService private readonly instantiationService : IInstantiationService ,
68- @IContextViewService private readonly contextViewService : IContextViewService ,
69- @ILogService private readonly logService : ILogService ,
7045 ) {
7146 super ( ) ;
7247
@@ -228,7 +203,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
228203 } ) ;
229204 }
230205 run ( ) {
231- return that . saveProfile ( that . userDataProfileService . currentProfile ) ;
206+ return that . userDataProfileImportExportService . editProfile ( that . userDataProfileService . currentProfile ) ;
232207 }
233208 } ) ;
234209 }
@@ -375,7 +350,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
375350 }
376351 try {
377352 if ( ( < IProfileTemplateQuickPickItem > selectedItem ) . url ) {
378- return await that . saveProfile ( undefined , ( < IProfileTemplateQuickPickItem > selectedItem ) . url ) ;
353+ return await that . userDataProfileImportExportService . createProfile ( URI . parse ( ( < IProfileTemplateQuickPickItem > selectedItem ) . url ) ) ;
379354 }
380355 const profile = selectedItem . label === quickPick . value ? URI . parse ( quickPick . value ) : await this . getProfileUriFromFileSystem ( fileDialogService ) ;
381356 if ( profile ) {
@@ -433,194 +408,11 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
433408 }
434409
435410 run ( accessor : ServicesAccessor ) {
436- return that . saveProfile ( undefined , that . userDataProfileService . currentProfile ) ;
411+ return that . userDataProfileImportExportService . createProfile ( that . userDataProfileService . currentProfile ) ;
437412 }
438413 } ) ) ;
439414 }
440415
441- private async saveProfile ( profile : IUserDataProfile ) : Promise < void > ;
442- private async saveProfile ( profile ?: IUserDataProfile , source ?: IUserDataProfile | string ) : Promise < void > ;
443- private async saveProfile ( profile ?: IUserDataProfile , source ?: IUserDataProfile | string ) : Promise < void > {
444-
445- type CreateProfileInfoClassification = {
446- owner : 'sandy081' ;
447- comment : 'Report when profile is about to be created' ;
448- } ;
449- this . telemetryService . publicLog2 < { } , CreateProfileInfoClassification > ( 'userDataProfile.startCreate' ) ;
450-
451- const disposables = new DisposableStore ( ) ;
452- const title = profile ? localize ( 'save profile' , "Edit {0} Profile..." , profile . name ) : localize ( 'create new profle' , "Create New Profile..." ) ;
453-
454- const settings : IQuickPickItem & { id : ProfileResourceType } = { id : ProfileResourceType . Settings , label : localize ( 'settings' , "Settings" ) , picked : ! profile ?. useDefaultFlags ?. settings } ;
455- const keybindings : IQuickPickItem & { id : ProfileResourceType } = { id : ProfileResourceType . Keybindings , label : localize ( 'keybindings' , "Keyboard Shortcuts" ) , picked : ! profile ?. useDefaultFlags ?. keybindings } ;
456- const snippets : IQuickPickItem & { id : ProfileResourceType } = { id : ProfileResourceType . Snippets , label : localize ( 'snippets' , "User Snippets" ) , picked : ! profile ?. useDefaultFlags ?. snippets } ;
457- const tasks : IQuickPickItem & { id : ProfileResourceType } = { id : ProfileResourceType . Tasks , label : localize ( 'tasks' , "User Tasks" ) , picked : ! profile ?. useDefaultFlags ?. tasks } ;
458- const extensions : IQuickPickItem & { id : ProfileResourceType } = { id : ProfileResourceType . Extensions , label : localize ( 'extensions' , "Extensions" ) , picked : ! profile ?. useDefaultFlags ?. extensions } ;
459- const resources = [ settings , keybindings , snippets , tasks , extensions ] ;
460-
461- const quickPick = this . quickInputService . createQuickPick ( ) ;
462- quickPick . title = title ;
463- quickPick . placeholder = localize ( 'name placeholder' , "Profile name" ) ;
464- quickPick . value = profile ?. name ?? '' ;
465- quickPick . canSelectMany = true ;
466- quickPick . matchOnDescription = false ;
467- quickPick . matchOnDetail = false ;
468- quickPick . matchOnLabel = false ;
469- quickPick . sortByLabel = false ;
470- quickPick . hideCountBadge = true ;
471- quickPick . ok = false ;
472- quickPick . customButton = true ;
473- quickPick . hideCheckAll = true ;
474- quickPick . ignoreFocusOut = true ;
475- quickPick . customLabel = profile ? localize ( 'save' , "Save" ) : localize ( 'create' , "Create" ) ;
476- quickPick . description = localize ( 'customise the profile' , "Choose what to configure in your Profile:" ) ;
477- quickPick . items = [ ...resources ] ;
478-
479- const update = ( ) => {
480- quickPick . items = resources ;
481- quickPick . selectedItems = resources . filter ( item => item . picked ) ;
482- } ;
483- update ( ) ;
484-
485- const validate = ( ) => {
486- if ( ! profile && this . userDataProfilesService . profiles . some ( p => p . name === quickPick . value ) ) {
487- quickPick . validationMessage = localize ( 'profileExists' , "Profile with name {0} already exists." , quickPick . value ) ;
488- quickPick . severity = Severity . Warning ;
489- return ;
490- }
491- if ( resources . every ( resource => ! resource . picked ) ) {
492- quickPick . validationMessage = localize ( 'invalid configurations' , "The profile should contain at least one configuration." ) ;
493- quickPick . severity = Severity . Warning ;
494- return ;
495- }
496- quickPick . severity = Severity . Ignore ;
497- quickPick . validationMessage = undefined ;
498- } ;
499-
500- disposables . add ( quickPick . onDidChangeSelection ( items => {
501- let needUpdate = false ;
502- for ( const resource of resources ) {
503- resource . picked = items . includes ( resource ) ;
504- const description = resource . picked ? undefined : localize ( 'use default profile' , "Using Default Profile" ) ;
505- if ( resource . description !== description ) {
506- resource . description = description ;
507- needUpdate = true ;
508- }
509- }
510- if ( needUpdate ) {
511- update ( ) ;
512- }
513- validate ( ) ;
514- } ) ) ;
515-
516- disposables . add ( quickPick . onDidChangeValue ( validate ) ) ;
517-
518- let result : { name : string ; items : ReadonlyArray < IQuickPickItem > } | undefined ;
519- disposables . add ( Event . any ( quickPick . onDidCustom , quickPick . onDidAccept ) ( ( ) => {
520- if ( ! quickPick . value ) {
521- quickPick . validationMessage = localize ( 'name required' , "Provide a name for the new profile" ) ;
522- quickPick . severity = Severity . Error ;
523- }
524- if ( quickPick . validationMessage ) {
525- return ;
526- }
527- result = { name : quickPick . value , items : quickPick . selectedItems } ;
528- quickPick . hide ( ) ;
529- quickPick . severity = Severity . Ignore ;
530- quickPick . validationMessage = undefined ;
531- } ) ) ;
532-
533- if ( ! profile ) {
534- const domNode = $ ( '.profile-type-widget' ) ;
535- append ( domNode , $ ( '.profile-type-create-label' , undefined , localize ( 'create from' , "Copy from:" ) ) ) ;
536- const separator = { text : '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500' , isDisabled : true } ;
537- const profileOptions : ( ISelectOptionItem & { id ?: string ; source ?: IUserDataProfile | string } ) [ ] = [ ] ;
538- profileOptions . push ( { text : localize ( 'empty profile' , "None" ) } ) ;
539- const templates = await this . getProfileTemplatesFromProduct ( ) ;
540- if ( templates . length ) {
541- profileOptions . push ( { ...separator , decoratorRight : localize ( 'from templates' , "Profile Templates" ) } ) ;
542- for ( const template of templates ) {
543- profileOptions . push ( { text : template . name , id : template . url , source : template . url } ) ;
544- }
545- }
546- profileOptions . push ( { ...separator , decoratorRight : localize ( 'from existing profiles' , "Existing Profiles" ) } ) ;
547- for ( const profile of this . userDataProfilesService . profiles ) {
548- profileOptions . push ( { text : profile . name , id : profile . id , source : profile } ) ;
549- }
550-
551- const findOptionIndex = ( ) => {
552- const index = profileOptions . findIndex ( option => {
553- if ( isString ( source ) ) {
554- return option . id === source ;
555- } else if ( source ) {
556- return option . id === source . id ;
557- }
558- return false ;
559- } ) ;
560- return index > - 1 ? index : 0 ;
561- } ;
562-
563- const selectBox = disposables . add ( this . instantiationService . createInstance ( SelectBox , profileOptions , findOptionIndex ( ) , this . contextViewService , defaultSelectBoxStyles , { useCustomDrawn : true } ) ) ;
564- selectBox . render ( append ( domNode , $ ( '.profile-type-select-container' ) ) ) ;
565- quickPick . widget = domNode ;
566-
567- const updateQuickpickInfo = ( ) => {
568- const option = profileOptions [ findOptionIndex ( ) ] ;
569- for ( const resource of resources ) {
570- resource . picked = option . source && ! isString ( option . source ) ? ! option . source ?. useDefaultFlags ?. [ resource . id ] : true ;
571- }
572- update ( ) ;
573- } ;
574-
575- updateQuickpickInfo ( ) ;
576- disposables . add ( selectBox . onDidSelect ( ( { index } ) => {
577- source = profileOptions [ index ] . source ;
578- updateQuickpickInfo ( ) ;
579- } ) ) ;
580- }
581-
582- quickPick . show ( ) ;
583-
584- await new Promise < void > ( ( c , e ) => {
585- disposables . add ( quickPick . onDidHide ( ( ) => {
586- disposables . dispose ( ) ;
587- c ( ) ;
588- } ) ) ;
589- } ) ;
590-
591- if ( ! result ) {
592- this . telemetryService . publicLog2 < { } , CreateProfileInfoClassification > ( 'userDataProfile.cancelCreate' ) ;
593- return ;
594- }
595-
596- this . telemetryService . publicLog2 < { } , CreateProfileInfoClassification > ( 'userDataProfile.successCreate' ) ;
597-
598- try {
599- const useDefaultFlags : UseDefaultProfileFlags | undefined = result . items . length === resources . length
600- ? undefined
601- : {
602- settings : ! result . items . includes ( settings ) ,
603- keybindings : ! result . items . includes ( keybindings ) ,
604- snippets : ! result . items . includes ( snippets ) ,
605- tasks : ! result . items . includes ( tasks ) ,
606- extensions : ! result . items . includes ( extensions )
607- } ;
608- if ( profile ) {
609- await this . userDataProfileManagementService . updateProfile ( profile , { name : result . name , useDefaultFlags : profile . useDefaultFlags && ! useDefaultFlags ? { } : useDefaultFlags } ) ;
610- } else {
611- if ( isString ( source ) ) {
612- await this . userDataProfileImportExportService . importProfile ( URI . parse ( source ) , { mode : 'apply' , name : result . name , useDefaultFlags } ) ;
613- } else if ( source ) {
614- await this . userDataProfileImportExportService . createFromProfile ( source , result . name , { useDefaultFlags } ) ;
615- } else {
616- await this . userDataProfileManagementService . createAndEnterProfile ( result . name , { useDefaultFlags } ) ;
617- }
618- }
619- } catch ( error ) {
620- this . notificationService . error ( error ) ;
621- }
622- }
623-
624416 private registerCreateProfileAction ( ) : void {
625417 const that = this ;
626418 this . _register ( registerAction2 ( class CreateProfileAction extends Action2 {
@@ -646,7 +438,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
646438 }
647439
648440 async run ( accessor : ServicesAccessor ) {
649- return that . saveProfile ( ) ;
441+ return that . userDataProfileImportExportService . createProfile ( ) ;
650442 }
651443 } ) ) ;
652444 }
@@ -726,7 +518,7 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
726518
727519 private async getProfileTemplatesQuickPickItems ( ) : Promise < IProfileTemplateQuickPickItem [ ] > {
728520 const quickPickItems : IProfileTemplateQuickPickItem [ ] = [ ] ;
729- const profileTemplates = await this . getProfileTemplatesFromProduct ( ) ;
521+ const profileTemplates = await this . userDataProfileManagementService . getBuiltinProfileTemplates ( ) ;
730522 for ( const template of profileTemplates ) {
731523 quickPickItems . push ( {
732524 label : template . name ,
@@ -736,22 +528,6 @@ export class UserDataProfilesWorkbenchContribution extends Disposable implements
736528 return quickPickItems ;
737529 }
738530
739- private async getProfileTemplatesFromProduct ( ) : Promise < IProfileTemplateInfo [ ] > {
740- if ( this . productService . profileTemplatesUrl ) {
741- try {
742- const context = await this . requestService . request ( { type : 'GET' , url : this . productService . profileTemplatesUrl } , CancellationToken . None ) ;
743- if ( context . res . statusCode === 200 ) {
744- return ( await asJson < IProfileTemplateInfo [ ] > ( context ) ) || [ ] ;
745- } else {
746- this . logService . error ( 'Could not get profile templates.' , context . res . statusCode ) ;
747- }
748- } catch ( error ) {
749- this . logService . error ( error ) ;
750- }
751- }
752- return [ ] ;
753- }
754-
755531 private async reportWorkspaceProfileInfo ( ) : Promise < void > {
756532 await this . lifecycleService . when ( LifecyclePhase . Eventually ) ;
757533 const workspaceId = await this . workspaceTagsService . getTelemetryWorkspaceId ( this . workspaceContextService . getWorkspace ( ) , this . workspaceContextService . getWorkbenchState ( ) ) ;
0 commit comments