@@ -21,6 +21,7 @@ import ReactFlow, {
2121 MarkerType ,
2222 Node ,
2323 ReactFlowProvider ,
24+ Edge ,
2425} from "reactflow" ;
2526import "reactflow/dist/style.css" ;
2627
@@ -33,7 +34,7 @@ import { useStore } from "zustand";
3334
3435import { RepoContext } from "../lib/store" ;
3536import { dbtype2nodetype , nodetype2dbtype } from "../lib/utils" ;
36- import { useYjsObserver } from "../lib/nodes" ;
37+ import { useEdgesYjsObserver , useYjsObserver } from "../lib/nodes" ;
3738
3839import { useApolloClient } from "@apollo/client" ;
3940import { CanvasContextMenu } from "./CanvasContextMenu" ;
@@ -149,14 +150,60 @@ function verifyConsistency(nodes: Node[], nodesMap: YMap<Node>) {
149150 return true ;
150151}
151152
153+ function verifyEdgeConsistency ( edges : Edge [ ] , edgesMap : YMap < Edge > ) {
154+ let keys = new Set ( edgesMap . keys ( ) ) ;
155+ let edgesMap2 = new Map < string , Edge > ( ) ;
156+ edges . forEach ( ( edge ) => edgesMap2 . set ( edge . id , edge ) ) ;
157+ let keys2 = new Set ( edgesMap2 . keys ( ) ) ;
158+ if ( keys . size !== keys2 . size ) {
159+ console . error ( "key sizes are not the same" , keys , keys2 ) ;
160+ return false ;
161+ }
162+ for ( let i = 0 ; i < keys . size ; i ++ ) {
163+ if ( keys [ i ] !== keys2 [ i ] ) {
164+ console . error ( "keys are not the same" , keys , keys2 ) ;
165+ return false ;
166+ }
167+ }
168+ // verify the values
169+ for ( let key of Array . from ( keys ) ) {
170+ let edge1 = edgesMap . get ( key ) ;
171+ let edge2 = edgesMap2 . get ( key ) ;
172+ if ( ! edge1 ) {
173+ console . error ( "edge1 is undefined" ) ;
174+ return false ;
175+ }
176+ if ( ! edge2 ) {
177+ console . error ( "edge2 is undefined" ) ;
178+ return false ;
179+ }
180+ if ( edge1 . id !== edge2 . id ) {
181+ console . error ( "edge id are not the same" , edge1 . id , edge2 . id , "key" , key ) ;
182+ return false ;
183+ }
184+ if ( edge1 . source !== edge2 . source ) {
185+ console . error ( "edge source are not the same" , edge1 . source , edge2 . source ) ;
186+ return false ;
187+ }
188+ if ( edge1 . target !== edge2 . target ) {
189+ console . error ( "edge target are not the same" , edge1 . target , edge2 . target ) ;
190+ return false ;
191+ }
192+ }
193+ return true ;
194+ }
195+
152196function useInitNodes ( ) {
153197 const store = useContext ( RepoContext ) ! ;
154198 const getPod = useStore ( store , ( state ) => state . getPod ) ;
155199 const nodesMap = useStore ( store , ( state ) => state . ydoc . getMap < Node > ( "pods" ) ) ;
200+ const edgesMap = useStore ( store , ( state ) => state . ydoc . getMap < Edge > ( "edges" ) ) ;
201+ const arrows = useStore ( store , ( state ) => state . arrows ) ;
156202 const getId2children = useStore ( store , ( state ) => state . getId2children ) ;
157203 const provider = useStore ( store , ( state ) => state . provider ) ;
158204 const [ loading , setLoading ] = useState ( true ) ;
159205 const updateView = useStore ( store , ( state ) => state . updateView ) ;
206+ const updateEdgeView = useStore ( store , ( state ) => state . updateEdgeView ) ;
160207 const adjustLevel = useStore ( store , ( state ) => state . adjustLevel ) ;
161208 useEffect ( ( ) => {
162209 const init = ( ) => {
@@ -173,15 +220,7 @@ function useInitNodes() {
173220 let nodesMap2 = new Map < string , Node > ( ) ;
174221 nodes . forEach ( ( node ) => nodesMap2 . set ( node . id , node ) ) ;
175222 // Not only should we set nodes, but also delete.
176- nodesMap . forEach ( ( node , key ) => {
177- if ( ! nodesMap2 . has ( key ) ) {
178- console . error ( `Yjs has key ${ key } that is not in database.` ) ;
179- // FIXME CAUTION This will delete the node in the database! Be
180- // careful! For now, just log errors and do not delete.
181- //
182- nodesMap . delete ( key ) ;
183- }
184- } ) ;
223+ nodesMap . clear ( ) ;
185224 // add the nodes, so that the nodesMap is consistent with the database.
186225 nodes . forEach ( ( node ) => {
187226 nodesMap . set ( node . id , node ) ;
@@ -190,8 +229,36 @@ function useInitNodes() {
190229 // NOTE we have to trigger an update here, otherwise the nodes are not
191230 // rendered.
192231 // triggerUpdate();
232+ // adjust level and update view
193233 adjustLevel ( ) ;
194234 updateView ( ) ;
235+ // handling the arrows
236+ isConsistent = verifyEdgeConsistency (
237+ arrows . map ( ( { source, target } ) => ( {
238+ source,
239+ target,
240+ id : `${ source } _${ target } ` ,
241+ } ) ) ,
242+ edgesMap
243+ ) ;
244+ if ( ! isConsistent ) {
245+ console . warn ( "The yjs server is not consistent with the database." ) ;
246+ // delete the old keys
247+ edgesMap . clear ( ) ;
248+ arrows . forEach ( ( { target, source } ) => {
249+ const edge : Edge = {
250+ id : `${ source } _${ target } ` ,
251+ source,
252+ sourceHandle : "top" ,
253+ target,
254+ targetHandle : "top" ,
255+ } ;
256+ edgesMap . set ( edge . id , edge ) ;
257+ // This isn't working. I need to set {edges} manually (from edgesMap)
258+ // reactFlowInstance.addEdges(edge);
259+ } ) ;
260+ }
261+ updateEdgeView ( ) ;
195262 setLoading ( false ) ;
196263 } ;
197264
@@ -391,6 +458,7 @@ function CanvasImplWrap() {
391458 const reactFlowWrapper = useRef < any > ( null ) ;
392459
393460 useYjsObserver ( ) ;
461+ useEdgesYjsObserver ( ) ;
394462 usePaste ( reactFlowWrapper ) ;
395463 useCut ( reactFlowWrapper ) ;
396464
@@ -419,8 +487,10 @@ function CanvasImpl() {
419487 const onNodesChange = useStore ( store , ( state ) =>
420488 state . onNodesChange ( apolloClient )
421489 ) ;
422- const onEdgesChange = useStore ( store , ( state ) => state . onEdgesChange ) ;
423- const onConnect = useStore ( store , ( state ) => state . onConnect ) ;
490+ const onEdgesChange = useStore ( store , ( state ) =>
491+ state . onEdgesChange ( apolloClient )
492+ ) ;
493+ const onConnect = useStore ( store , ( state ) => state . onConnect ( apolloClient ) ) ;
424494 const moveIntoScope = useStore ( store , ( state ) => state . moveIntoScope ) ;
425495 const setDragHighlight = useStore ( store , ( state ) => state . setDragHighlight ) ;
426496 const removeDragHighlight = useStore (
0 commit comments