@@ -31,7 +31,7 @@ import { BuildContext, Project, TargetSetData } from './components-data';
3131import { ComponentsPacksActions , CurrentProject , normalizeForCompare } from './components-packs-actions' ;
3232import { ComponentRowDataType , ComponentScope } from './data/component-tools' ;
3333import { componentTreeWalker } from './data/component-tree-walker' ;
34- import { uniqWith } from 'lodash' ;
34+ import { uniqWith , cloneDeep } from 'lodash' ;
3535import { parsePackId } from './data/pack-parse' ;
3636import { lineOf , readTextFile } from '../../utils/fs-utils' ;
3737import { stripTwoExtensions } from '../../utils/string-utils' ;
@@ -131,6 +131,12 @@ export class ComponentsPacksWebviewMain {
131131 return ; // nothing to show
132132 }
133133
134+ const reload = this . projectFromPath ( this . currentProject ?. project . projectId ) !== this . projectFromPath ( cprojectPath ) ;
135+ const csolution = this . solutionManager . getCsolution ( ) ;
136+ if ( csolution ) {
137+ this . currentProject = { solutionPath : csolution . solutionPath , project : createProject ( cprojectPath ) } ;
138+ }
139+
134140 if ( clayerPath ) {
135141 const selectedTarget = this . findTargetSetFromPath ( clayerPath ) ;
136142 if ( selectedTarget ) {
@@ -141,7 +147,6 @@ export class ComponentsPacksWebviewMain {
141147 }
142148 this . webviewManager . createOrShowPanel ( ) ;
143149
144- const reload = this . projectFromPath ( this . currentProject ?. project . projectId ) !== this . projectFromPath ( cprojectPath ) ;
145150 await this . debounce_load ( cprojectPath , reload ) ;
146151 await this . sendDirtyState ( ) ;
147152 }
@@ -204,37 +209,39 @@ export class ComponentsPacksWebviewMain {
204209 return undefined ;
205210 }
206211
207- private async isDirty ( ) : Promise < boolean > {
212+ private async isDirty ( usedItems ?: UsedItems ) : Promise < boolean > {
208213 const actx = this . getActiveContext ( ) ;
209214
210215 if ( this . solutionManager . getCsolution ( ) ?. cbuildPackFile . isModified ( ) ) {
211216 return true ;
212217 }
213218
214- const usedItems = await this . csolutionService . getUsedItems ( { context : actx } ) ;
215- if ( this . usedItems ?. packs . length !== usedItems . packs . length || this . usedItems ?. components . length !== usedItems . components . length ) {
219+ const latestUsedItems = usedItems ?? await this . csolutionService . getUsedItems ( { context : actx } ) ;
220+ if ( this . usedItems ?. packs . length !== latestUsedItems . packs . length || this . usedItems ?. components . length !== latestUsedItems . components . length ) {
216221 return true ;
217222 }
218223
219224 const componentMapper = ( c : ComponentInstance ) => ( { id : c . id , variant : c . resolvedComponent ?. pack } ) ;
220225 const packMapper = ( p : PackReference ) => ( { pack : p . pack , origin : normalizeForCompare ( p . origin ) } ) ;
221226 const localUsedItemsSorted = {
222- components : this . usedItems ?. components . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) . map ( componentMapper ) ?? [ ] ,
223- packs : this . usedItems ?. packs . sort ( ( a , b ) => a . pack . localeCompare ( b . pack ) ) . map ( packMapper ) ?? [ ] ,
227+ components : [ ... ( this . usedItems ?. components ?? [ ] ) ] . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) . map ( componentMapper ) ,
228+ packs : [ ... ( this . usedItems ?. packs ?? [ ] ) ] . sort ( ( a , b ) => a . pack . localeCompare ( b . pack ) ) . map ( packMapper ) ,
224229 } ;
225230 const usedItemsSorted = {
226- components : usedItems . components . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) . map ( componentMapper ) ,
227- packs : usedItems . packs . sort ( ( a , b ) => a . pack . localeCompare ( b . pack ) ) . map ( packMapper ) ,
231+ components : [ ... latestUsedItems . components ] . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) . map ( componentMapper ) ,
232+ packs : [ ... latestUsedItems . packs ] . sort ( ( a , b ) => a . pack . localeCompare ( b . pack ) ) . map ( packMapper ) ,
228233 } ;
229234 const usedItemsChanged = ! isDeepStrictEqual ( localUsedItemsSorted , usedItemsSorted ) ;
230235 return usedItemsChanged ;
231236 }
232237
233- private async sendDirtyState ( ) : Promise < void > {
238+ private async sendDirtyState ( options ?: { skipApply ?: boolean , usedItems ?: UsedItems } ) : Promise < void > {
234239 const actx = this . getActiveContext ( ) ;
235- await this . csolutionService . apply ( { context : actx } ) ;
240+ if ( ! options ?. skipApply ) {
241+ await this . csolutionService . apply ( { context : actx } ) ;
242+ }
236243
237- const isDirty = await this . isDirty ( ) ;
244+ const isDirty = await this . isDirty ( options ?. usedItems ) ;
238245 await this . webviewManager . sendMessage ( { type : 'IS_DIRTY' , isDirty : isDirty } ) ;
239246 }
240247
@@ -368,7 +375,7 @@ export class ComponentsPacksWebviewMain {
368375 label : `Layer: ${ layerLabel } ` ,
369376 key : layer . absolutePath ,
370377 path : backToForwardSlashes ( layer . absolutePath ) ,
371- relativePath : backToForwardSlashes ( path . relative ( dirname ( this . currentProject ?. solutionPath ?? '' ) , layer . absolutePath ) ) ,
378+ relativePath : this . getRelativePath ( this . getSolutionDir ( ) , layer . absolutePath ) ,
372379 type : 'layer' as const
373380 } ;
374381
@@ -413,11 +420,12 @@ export class ComponentsPacksWebviewMain {
413420 const activeContext = this . getActiveContext ( ) ;
414421 const state = await this . csolutionService . apply ( { context : activeContext } ) ;
415422 this . usedItems = await this . csolutionService . getUsedItems ( { context : activeContext } ) ;
423+ const usedItemsForProjectFileUpdate = cloneDeep ( this . usedItems ) ;
416424 const projectFileName = this . currentProject ?. project . projectId ?? '' ;
417425 const requestAll = this . scope === ComponentScope . All ;
418426 this . componentTree = this . manageComponentsActions . mapComponentsFromService ( await this . csolutionService . getComponentsTree ( { context : activeContext , all : requestAll } ) ) ;
419427 this . validations = await this . csolutionService . validateComponents ( { context : activeContext } ) ;
420- await this . projectFileUpdater . updateUsedItems ( activeContext , projectFileName , this . usedItems ) ;
428+ await this . projectFileUpdater . updateUsedItems ( activeContext , projectFileName , usedItemsForProjectFileUpdate ) ;
421429
422430 await Promise . all ( [
423431 this . webviewManager . sendMessage ( { type : 'SET_ERROR_MESSAGES' , messages : [ ] } ) ,
@@ -426,7 +434,7 @@ export class ComponentsPacksWebviewMain {
426434 if ( state . success === false ) {
427435 this . webviewManager . sendMessage ( { type : 'SET_SOLUTION_STATE' , stateMessage : state . message ?? 'Unspecified error when writing solution information' } ) ;
428436 }
429- await this . sendDirtyState ( ) ;
437+ await this . sendDirtyState ( { skipApply : true , usedItems : usedItemsForProjectFileUpdate } ) ;
430438 }
431439
432440 private async handleOpenFile ( message : Messages . OutgoingMessage ) : Promise < void > {
@@ -447,9 +455,7 @@ export class ComponentsPacksWebviewMain {
447455 ) ;
448456
449457 await this . sendDirtyState ( ) ;
450- const validations = await this . csolutionService . validateComponents ( { context : activeContext } ) ;
451- this . componentTree = this . manageComponentsActions . mapComponentsFromService ( await this . csolutionService . getComponentsTree ( { context : activeContext , all : this . scope === ComponentScope . All } ) ) ;
452- await this . webviewManager ?. sendMessage ( { type : 'SET_COMPONENT_TREE' , tree : this . componentTree , validations : validations . validation } ) ;
458+ await this . refreshComponentTree ( activeContext ) ;
453459 }
454460 }
455461 }
@@ -465,9 +471,7 @@ export class ComponentsPacksWebviewMain {
465471 variant
466472 ) ;
467473 await this . sendDirtyState ( ) ;
468- this . componentTree = this . manageComponentsActions . mapComponentsFromService ( await this . csolutionService . getComponentsTree ( { context : activeContext , all : this . scope === ComponentScope . All } ) ) ;
469- const validations = await this . csolutionService . validateComponents ( { context : activeContext } ) ;
470- await this . webviewManager ?. sendMessage ( { type : 'SET_COMPONENT_TREE' , tree : this . componentTree , validations : validations . validation } ) ;
474+ await this . refreshComponentTree ( activeContext ) ;
471475 }
472476 }
473477 }
@@ -483,10 +487,7 @@ export class ComponentsPacksWebviewMain {
483487 bundle
484488 ) ;
485489 await this . sendDirtyState ( ) ;
486- const requestAll = this . scope === ComponentScope . All ;
487- this . componentTree = this . manageComponentsActions . mapComponentsFromService ( await this . csolutionService . getComponentsTree ( { context : activeContext , all : requestAll } ) ) ;
488- this . validations = await this . csolutionService . validateComponents ( { context : activeContext } ) ;
489- await this . webviewManager . sendMessage ( { type : 'SET_COMPONENT_TREE' , tree : this . componentTree , validations : this . validations . validation ?? [ ] , scope : this . scope } ) ;
490+ await this . refreshComponentTree ( activeContext ) ;
490491 }
491492 }
492493 }
@@ -596,37 +597,40 @@ export class ComponentsPacksWebviewMain {
596597 }
597598 } ;
598599
600+ private async handlePackageSelectionChange (
601+ target : string ,
602+ packId : string ,
603+ stateMessage : string ,
604+ action : ( actx : string , target : string , packId : string ) => Promise < void >
605+ ) : Promise < void > {
606+ try {
607+ await this . webviewManager . sendMessage ( { type : 'SET_SOLUTION_STATE' , stateMessage } ) ;
608+ const actx = this . getActiveContext ( ) ;
609+ await action ( actx , target , packId ) ;
610+ const requestAll = this . scope === ComponentScope . All ;
611+ const packs = this . mapPacksFromService ( await this . csolutionService . getPacksInfo ( { context : actx , all : requestAll } ) ) ;
612+ await this . webviewManager . sendMessage ( { type : 'SET_PACKS_INFO' , packs : packs ?. packs || [ ] } ) ;
613+ await this . sendDirtyState ( ) ;
614+ } finally {
615+ await this . webviewManager . sendMessage ( { type : 'SET_SOLUTION_STATE' , stateMessage : undefined } ) ;
616+ }
617+ }
618+
599619 private async selectPackage ( message : Messages . OutgoingMessage ) : Promise < void > {
600620 if ( isSelectPackageMessage ( message ) ) {
601- try {
602- await this . webviewManager . sendMessage ( { type : 'SET_SOLUTION_STATE' , stateMessage : 'Selecting Pack' } ) ;
603-
604- const actx = this . getActiveContext ( ) ;
605- await this . manageComponentsActions . selectPackage ( actx , message . target , message . packId ) ;
606- const requestAll = this . scope === ComponentScope . All ;
607- const packs = this . mapPacksFromService ( await this . csolutionService ?. getPacksInfo ( { context : actx , all : requestAll } ) ) ;
608- await this . webviewManager ?. sendMessage ( { type : 'SET_PACKS_INFO' , packs : packs ?. packs || [ ] } ) ;
609- await this . sendDirtyState ( ) ;
610- } finally {
611- await this . webviewManager . sendMessage ( { type : 'SET_SOLUTION_STATE' , stateMessage : undefined } ) ;
612- }
621+ await this . handlePackageSelectionChange (
622+ message . target , message . packId , 'Selecting Pack' ,
623+ ( actx , target , packId ) => this . manageComponentsActions . selectPackage ( actx , target , packId )
624+ ) ;
613625 }
614626 }
615627
616628 private async unselectPackage ( message : Messages . OutgoingMessage ) : Promise < void > {
617629 if ( isUnselectPackageMessage ( message ) ) {
618- try {
619- await this . webviewManager . sendMessage ( { type : 'SET_SOLUTION_STATE' , stateMessage : 'Unselecting Pack' } ) ;
620-
621- const actx = this . getActiveContext ( ) ;
622- await this . manageComponentsActions . unselectPackage ( actx , message . target , message . packId ) ;
623- const requestAll = this . scope === ComponentScope . All ;
624- const packs = this . mapPacksFromService ( await this . csolutionService ?. getPacksInfo ( { context : actx , all : requestAll } ) ) ;
625- await this . webviewManager ?. sendMessage ( { type : 'SET_PACKS_INFO' , packs : packs ?. packs || [ ] } ) ;
626- await this . sendDirtyState ( ) ;
627- } finally {
628- await this . webviewManager . sendMessage ( { type : 'SET_SOLUTION_STATE' , stateMessage : undefined } ) ;
629- }
630+ await this . handlePackageSelectionChange (
631+ message . target , message . packId , 'Unselecting Pack' ,
632+ ( actx , target , packId ) => this . manageComponentsActions . unselectPackage ( actx , target , packId )
633+ ) ;
630634 }
631635 }
632636
@@ -658,14 +662,14 @@ export class ComponentsPacksWebviewMain {
658662 const activeContext = this . getActiveContext ( ) ;
659663 const requestAll = this . scope === ComponentScope . All ;
660664
661- this . componentTree = this . manageComponentsActions . mapComponentsFromService ( await this . csolutionService . getComponentsTree ( { context : activeContext , all : requestAll } ) ) ;
662- this . validations = await this . csolutionService . validateComponents ( { context : activeContext } ) ;
663- const packsInfo = this . mapPacksFromService ( await this . csolutionService . getPacksInfo ( { context : activeContext , all : requestAll } ) ) ;
664-
665665 if ( ! this . availablePacksCache || Object . keys ( this . availablePacksCache ) . length === 0 ) {
666666 this . availablePacksCache = await this . filterAvailablePacks ( activeContext ) ;
667667 }
668668
669+ this . componentTree = this . manageComponentsActions . mapComponentsFromService ( await this . csolutionService . getComponentsTree ( { context : activeContext , all : requestAll } ) ) ;
670+ this . validations = await this . csolutionService . validateComponents ( { context : activeContext } ) ;
671+ const packsInfo = this . mapPacksFromService ( await this . csolutionService . getPacksInfo ( { context : activeContext , all : requestAll } ) ) ;
672+
669673 componentTreeWalker ( this . componentTree , ( node , type ) => {
670674 if ( type === 'aggregate' && ( node as CtAggregate ) . options ?. layer ) {
671675 ( node as CtAggregate ) . options ! . layer = ( node as CtAggregate ) . options ! . layer || '' ;
@@ -776,6 +780,19 @@ export class ComponentsPacksWebviewMain {
776780 await this . webviewManager . sendMessage ( programMessage ) ;
777781 }
778782
783+ private async refreshComponentTree ( activeContext : string ) : Promise < void > {
784+ this . componentTree = this . manageComponentsActions . mapComponentsFromService (
785+ await this . csolutionService . getComponentsTree ( { context : activeContext , all : this . scope === ComponentScope . All } )
786+ ) ;
787+ this . validations = await this . csolutionService . validateComponents ( { context : activeContext } ) ;
788+ await this . webviewManager . sendMessage ( {
789+ type : 'SET_COMPONENT_TREE' ,
790+ tree : this . componentTree ,
791+ validations : this . validations . validation ?? [ ] ,
792+ scope : this . scope
793+ } ) ;
794+ }
795+
779796 private async openFile ( filePath : string , openExternal ?: boolean , focusOn ?: string ) : Promise < void > {
780797 if ( openExternal ) {
781798 this . openFileExternal . openFile ( filePath ) ;
0 commit comments