@@ -12,6 +12,7 @@ import * as Y from 'yjs'
12
12
import { ACTOR_CONFIG } from '@/renderer/core/layout/constants'
13
13
import { LayoutSource } from '@/renderer/core/layout/types'
14
14
import type {
15
+ BatchUpdateBoundsOperation ,
15
16
Bounds ,
16
17
CreateLinkOperation ,
17
18
CreateNodeOperation ,
@@ -863,6 +864,12 @@ class LayoutStoreImpl implements LayoutStore {
863
864
case 'deleteNode' :
864
865
this . handleDeleteNode ( operation as DeleteNodeOperation , change )
865
866
break
867
+ case 'batchUpdateBounds' :
868
+ this . handleBatchUpdateBounds (
869
+ operation as BatchUpdateBoundsOperation ,
870
+ change
871
+ )
872
+ break
866
873
case 'createLink' :
867
874
this . handleCreateLink ( operation as CreateLinkOperation , change )
868
875
break
@@ -1091,6 +1098,38 @@ class LayoutStoreImpl implements LayoutStore {
1091
1098
change . nodeIds . push ( operation . nodeId )
1092
1099
}
1093
1100
1101
+ private handleBatchUpdateBounds (
1102
+ operation : BatchUpdateBoundsOperation ,
1103
+ change : LayoutChange
1104
+ ) : void {
1105
+ const spatialUpdates : Array < { nodeId : NodeId ; bounds : Bounds } > = [ ]
1106
+
1107
+ for ( const nodeId of operation . nodeIds ) {
1108
+ const data = operation . bounds [ nodeId ]
1109
+ const ynode = this . ynodes . get ( nodeId )
1110
+ if ( ! ynode || ! data ) continue
1111
+
1112
+ ynode . set ( 'position' , { x : data . bounds . x , y : data . bounds . y } )
1113
+ ynode . set ( 'size' , {
1114
+ width : data . bounds . width ,
1115
+ height : data . bounds . height
1116
+ } )
1117
+ ynode . set ( 'bounds' , data . bounds )
1118
+
1119
+ spatialUpdates . push ( { nodeId, bounds : data . bounds } )
1120
+ change . nodeIds . push ( nodeId )
1121
+ }
1122
+
1123
+ // Batch update spatial index for better performance
1124
+ if ( spatialUpdates . length > 0 ) {
1125
+ this . spatialIndex . batchUpdate ( spatialUpdates )
1126
+ }
1127
+
1128
+ if ( change . nodeIds . length ) {
1129
+ change . type = 'update'
1130
+ }
1131
+ }
1132
+
1094
1133
private handleCreateLink (
1095
1134
operation : CreateLinkOperation ,
1096
1135
change : LayoutChange
@@ -1371,19 +1410,38 @@ class LayoutStoreImpl implements LayoutStore {
1371
1410
const originalSource = this . currentSource
1372
1411
this . currentSource = LayoutSource . Vue
1373
1412
1374
- this . ydoc . transact ( ( ) => {
1375
- for ( const { nodeId, bounds } of updates ) {
1376
- const ynode = this . ynodes . get ( nodeId )
1377
- if ( ! ynode ) continue
1413
+ const nodeIds : NodeId [ ] = [ ]
1414
+ const boundsRecord : BatchUpdateBoundsOperation [ 'bounds' ] = { }
1378
1415
1379
- this . spatialIndex . update ( nodeId , bounds )
1380
- ynode . set ( 'bounds' , bounds )
1381
- ynode . set ( 'position' , { x : bounds . x , y : bounds . y } )
1382
- ynode . set ( 'size' , { width : bounds . width , height : bounds . height } )
1416
+ for ( const { nodeId, bounds } of updates ) {
1417
+ const ynode = this . ynodes . get ( nodeId )
1418
+ if ( ! ynode ) continue
1419
+ const currentLayout = yNodeToLayout ( ynode )
1420
+
1421
+ boundsRecord [ nodeId ] = {
1422
+ bounds,
1423
+ previousBounds : currentLayout . bounds
1383
1424
}
1384
- } , this . currentActor )
1425
+ nodeIds . push ( nodeId )
1426
+ }
1427
+
1428
+ if ( ! nodeIds . length ) {
1429
+ this . currentSource = originalSource
1430
+ return
1431
+ }
1432
+
1433
+ const operation : BatchUpdateBoundsOperation = {
1434
+ type : 'batchUpdateBounds' ,
1435
+ entity : 'node' ,
1436
+ nodeIds,
1437
+ bounds : boundsRecord ,
1438
+ timestamp : Date . now ( ) ,
1439
+ source : this . currentSource ,
1440
+ actor : this . currentActor
1441
+ }
1442
+
1443
+ this . applyOperation ( operation )
1385
1444
1386
- // Restore original source
1387
1445
this . currentSource = originalSource
1388
1446
}
1389
1447
}
0 commit comments