1
1
import { Injectable } from '@angular/core' ;
2
2
import * as go from 'gojs' ;
3
- import produce from "immer" ;
3
+ import produce , { current } from "immer" ;
4
4
5
5
@Injectable ( )
6
6
export class DataSyncService {
@@ -18,6 +18,12 @@ export class DataSyncService {
18
18
19
19
// maintain a map of modified nodes for fast lookup during insertion
20
20
const modifiedNodesMap = new go . Map < go . Key , go . ObjectData > ( ) ;
21
+ // generate a map of keys -> indices for faster operations
22
+ const keyIdxMap = new Map < go . Key , number > ( ) ;
23
+ nodeData . forEach ( ( nd , idx ) => {
24
+ const key = model ? model . getKeyForNodeData ( nd ) : nd [ 'key' ] ;
25
+ keyIdxMap . set ( key , idx ) ;
26
+ } ) ;
21
27
22
28
// nodeData is immutable, modify it using the immer package's "produce" function (creates new array)
23
29
var newNodeDataArray = produce ( nodeData , ( draft ) => {
@@ -27,12 +33,9 @@ export class DataSyncService {
27
33
// Get the value of the node key property checking wether is a function or a string
28
34
const key = model ? model . getKeyForNodeData ( nd ) : nd [ 'key' ] ;
29
35
modifiedNodesMap . set ( key , nd ) ;
30
- for ( let i = 0 ; i < nodeData . length ; i ++ ) {
31
- const ndEntry = nodeData [ i ] ;
32
- const keyNdEntry = model ? model . getKeyForNodeData ( ndEntry ) : ndEntry [ 'key' ] ;
33
- if ( keyNdEntry === key ) {
34
- draft [ i ] = nd ;
35
- }
36
+ const idx = keyIdxMap . get ( key ) ;
37
+ if ( idx !== undefined && idx >= 0 ) {
38
+ draft [ idx ] = nd ;
36
39
}
37
40
} ) ;
38
41
}
@@ -41,18 +44,18 @@ export class DataSyncService {
41
44
if ( changes . insertedNodeKeys ) {
42
45
changes . insertedNodeKeys . forEach ( ( key : go . Key ) => {
43
46
const nd = modifiedNodesMap . get ( key ) ;
44
- if ( nd ) {
47
+ if ( nd && ! keyIdxMap . has ( key ) ) {
45
48
draft . push ( nd ) ;
46
49
}
47
50
} ) ;
48
51
}
49
52
50
53
// account for removed node data
51
54
if ( changes . removedNodeKeys ) {
52
- changes . removedNodeKeys . forEach ( rnk => {
53
- const idx = draft . findIndex ( nd => { return model . getKeyForNodeData ( nd ) == rnk } ) ;
54
- if ( idx >= 0 ) draft . splice ( idx , 1 ) ;
55
- } ) ;
55
+ const removals = changes . removedNodeKeys . map ( key => keyIdxMap . get ( key ) ) . sort ( ) ;
56
+ for ( let i = removals . length - 1 ; i >= 0 ; i -- ) {
57
+ draft . splice ( removals [ i ] , 1 ) ;
58
+ }
56
59
}
57
60
} ) ;
58
61
@@ -72,6 +75,12 @@ export class DataSyncService {
72
75
73
76
// maintain a map of modified nodes for fast lookup during insertion
74
77
const modifiedLinksMap = new go . Map < go . Key , go . ObjectData > ( ) ;
78
+ // generate a map of keys -> indices for faster operations
79
+ const keyIdxMap = new Map < go . Key , number > ( ) ;
80
+ linkData . forEach ( ( ld , idx ) => {
81
+ const key = model ? model . getKeyForLinkData ( ld ) : ld [ 'key' ] ;
82
+ keyIdxMap . set ( key , idx ) ;
83
+ } ) ;
75
84
76
85
// linkData is immutable, modify it using the immer package's "produce" function (creates new array)
77
86
linkData = produce ( linkData , draft => {
@@ -81,13 +90,9 @@ export class DataSyncService {
81
90
// Get the value of the link key
82
91
const key = model ? model . getKeyForLinkData ( ld ) : ld [ 'key' ] ;
83
92
modifiedLinksMap . set ( key , ld ) ;
84
-
85
- for ( let i = 0 ; i < linkData . length ; i ++ ) {
86
- const ldEntry = linkData [ i ] ;
87
- const keyLdEntry = model ? model . getKeyForLinkData ( ldEntry ) : ldEntry [ 'key' ] ;
88
- if ( keyLdEntry === key ) {
89
- draft [ i ] = ld ;
90
- }
93
+ const idx = keyIdxMap . get ( key ) ;
94
+ if ( idx !== undefined && idx >= 0 ) {
95
+ draft [ idx ] = ld ;
91
96
}
92
97
} ) ;
93
98
}
@@ -96,18 +101,18 @@ export class DataSyncService {
96
101
if ( changes . insertedLinkKeys ) {
97
102
changes . insertedLinkKeys . forEach ( ( key : go . Key ) => {
98
103
const nd = modifiedLinksMap . get ( key ) ;
99
- if ( nd ) {
104
+ if ( nd && ! keyIdxMap . has ( key ) ) {
100
105
draft . push ( nd ) ;
101
106
}
102
107
} ) ;
103
108
}
104
109
105
110
// account for removed link data
106
111
if ( changes . removedLinkKeys ) {
107
- changes . removedLinkKeys . forEach ( rlk => {
108
- const idx = draft . findIndex ( ld => { return model . getKeyForLinkData ( ld ) == rlk } ) ;
109
- if ( idx >= 0 ) draft . splice ( idx , 1 ) ;
110
- } ) ;
112
+ const removals = changes . removedLinkKeys . map ( key => keyIdxMap . get ( key ) ) . sort ( ) ;
113
+ for ( let i = removals . length - 1 ; i >= 0 ; i -- ) {
114
+ draft . splice ( removals [ i ] , 1 ) ;
115
+ }
111
116
}
112
117
} ) ;
113
118
0 commit comments