@@ -106,57 +106,70 @@ export default class Diff<L1 extends TItemLocation, L2 extends TItemLocation, A
106106 this . actions
107107 )
108108 }
109+
110+ static contains ( mappingsSnapshot : MappingSnapshot , item1 : TItem < TItemLocation > , item2 : TItem < TItemLocation > , itemTree : Folder < TItemLocation > , cache : Record < string , boolean > ) : boolean {
111+ const cacheKey = 'contains:' + Mappings . mapId ( mappingsSnapshot , item2 , ItemLocation . LOCAL ) + ':' + Mappings . mapId ( mappingsSnapshot , item2 , ItemLocation . SERVER ) +
112+ '-' + Mappings . mapId ( mappingsSnapshot , item1 , ItemLocation . LOCAL ) + ':' + Mappings . mapId ( mappingsSnapshot , item1 , ItemLocation . SERVER )
113+ if ( typeof cache [ cacheKey ] !== 'undefined' ) {
114+ return cache [ cacheKey ]
115+ }
116+ const item1InTree = itemTree . findItem ( item1 . type , Mappings . mapId ( mappingsSnapshot , item1 , itemTree . location ) )
117+ if (
118+ // target action payload contains item2's parent
119+ item1 . findItem ( ItemType . FOLDER ,
120+ Mappings . mapParentId ( mappingsSnapshot , item2 , item1 . location ) ) ||
121+ // target action payload contains item2
122+ item1 . findItem ( ItemType . FOLDER ,
123+ Mappings . mapId ( mappingsSnapshot , item2 , item1 . location ) ) ||
124+ // or target in tree contains item2's parent
125+ ( item1InTree && item1InTree . findItem ( ItemType . FOLDER , Mappings . mapParentId ( mappingsSnapshot , item2 , itemTree . location ) ) ) ||
126+ // or target in tree contains item2
127+ ( item1InTree && item1InTree . findItem ( item2 . type , Mappings . mapId ( mappingsSnapshot , item2 , itemTree . location ) ) ) ||
128+ // or target action payload is the item2
129+ Mappings . mapId ( mappingsSnapshot , item1 , item2 . location ) === item2 . id ||
130+ // or target action payload is the item2's parent
131+ Mappings . mapId ( mappingsSnapshot , item1 , item2 . location ) === item2 . parentId ||
132+ // or target action payload is the item2
133+ Mappings . mapId ( mappingsSnapshot , item2 , item1 . location ) === item1 . id ||
134+ // or target action payload is the item2s parent
135+ Mappings . mapParentId ( mappingsSnapshot , item2 , item1 . location ) === item1 . id
136+ ) {
137+ cache [ cacheKey ] = true
138+ return true
139+ }
140+ cache [ cacheKey ] = false
141+ return false
142+ }
109143
110144 static findChain (
111145 mappingsSnapshot : MappingSnapshot ,
112146 actions : Action < TItemLocation , TItemLocation > [ ] ,
113147 itemTree : Folder < TItemLocation > ,
114148 currentItem : TItem < TItemLocation > ,
115149 targetAction : Action < TItemLocation , TItemLocation > ,
150+ cache : Record < string , boolean > = { } ,
116151 chain : Action < TItemLocation , TItemLocation > [ ] = [ ]
117152 ) : boolean {
118- const targetItemInTree = itemTree . findItem ( targetAction . payload . type , Mappings . mapId ( mappingsSnapshot , targetAction . payload , itemTree . location ) )
119- if (
120- // target action payload contains currentItem's parent
121- targetAction . payload . findItem ( ItemType . FOLDER ,
122- Mappings . mapParentId ( mappingsSnapshot , currentItem , targetAction . payload . location ) ) ||
123- // target action payload contains currentItem
124- targetAction . payload . findItem ( ItemType . FOLDER ,
125- Mappings . mapId ( mappingsSnapshot , currentItem , targetAction . payload . location ) ) ||
126- // or target in tree contains currentItem
127- ( targetItemInTree && targetItemInTree . findItem ( ItemType . FOLDER , Mappings . mapParentId ( mappingsSnapshot , currentItem , itemTree . location ) ) ) ||
128- // or target action payload is the currentItem
129- Mappings . mapId ( mappingsSnapshot , targetAction . payload , currentItem . location ) === currentItem . id ||
130- // or target action payload is the currentItem's parent
131- Mappings . mapId ( mappingsSnapshot , targetAction . payload , currentItem . location ) === currentItem . parentId ||
132- // or target action payload is the currentItem
133- Mappings . mapId ( mappingsSnapshot , currentItem , targetAction . payload . location ) === targetAction . payload . id ||
134- // or target action payload is the currentItems parent
135- Mappings . mapParentId ( mappingsSnapshot , currentItem , targetAction . payload . location ) === targetAction . payload . id
136- ) {
153+
154+ const cacheKey = 'hasChain:' + Mappings . mapId ( mappingsSnapshot , currentItem , ItemLocation . LOCAL ) + ':' + Mappings . mapId ( mappingsSnapshot , currentItem , ItemLocation . SERVER ) + '-' + Mappings . mapId ( mappingsSnapshot , targetAction . payload , ItemLocation . LOCAL ) + ':' + Mappings . mapId ( mappingsSnapshot , targetAction . payload , ItemLocation . SERVER )
155+ if ( typeof cache [ cacheKey ] !== 'undefined' ) {
156+ return cache [ cacheKey ]
157+ }
158+ if ( Diff . contains ( mappingsSnapshot , targetAction . payload , currentItem , itemTree , cache ) ) {
159+ cache [ cacheKey ] = true
137160 return true
138161 }
139- const newCurrentActions = actions . filter ( targetAction =>
140- ! chain . includes ( targetAction ) && (
141- targetAction . payload . findItem ( ItemType . FOLDER , Mappings . mapParentId ( mappingsSnapshot , currentItem , targetAction . payload . location ) ) ||
142- targetAction . payload . findItem ( currentItem . type , Mappings . mapId ( mappingsSnapshot , currentItem , targetAction . payload . location ) ) ||
143- (
144- itemTree . findFolder ( Mappings . mapId ( mappingsSnapshot , targetAction . payload , itemTree . location ) ) &&
145- itemTree . findFolder ( Mappings . mapId ( mappingsSnapshot , targetAction . payload , itemTree . location ) ) . findFolder ( Mappings . mapParentId ( mappingsSnapshot , currentItem , itemTree . location ) )
146- ) ||
147- (
148- itemTree . findFolder ( Mappings . mapId ( mappingsSnapshot , targetAction . payload , itemTree . location ) ) &&
149- itemTree . findFolder ( Mappings . mapId ( mappingsSnapshot , targetAction . payload , itemTree . location ) ) . findItem ( currentItem . type , Mappings . mapId ( mappingsSnapshot , currentItem , itemTree . location ) )
150- )
151- )
162+ const newCurrentActions = actions . filter ( newTargetAction =>
163+ ! chain . includes ( newTargetAction ) && Diff . contains ( mappingsSnapshot , newTargetAction . payload , currentItem , itemTree , cache )
152164 )
153165 if ( newCurrentActions . length ) {
154166 for ( const newCurrentAction of newCurrentActions ) {
155- if ( Diff . findChain ( mappingsSnapshot , actions , itemTree , newCurrentAction . payload , targetAction , [ ...chain , newCurrentAction ] ) ) {
167+ if ( Diff . findChain ( mappingsSnapshot , actions , itemTree , newCurrentAction . payload , targetAction , cache , [ ...chain , newCurrentAction ] ) ) {
156168 return true
157169 }
158170 }
159171 }
172+ cache [ cacheKey ] = false
160173 return false
161174 }
162175
0 commit comments