@@ -25,6 +25,7 @@ import { useWorkspace } from "@/shared/lib/useWorkspace";
2525
2626export interface YNode extends Node {
2727 isHolding : boolean ;
28+ parentId ?: string ;
2829}
2930
3031export const useCanvas = ( ) => {
@@ -33,6 +34,7 @@ export const useCanvas = () => {
3334 const { pages } = usePages ( ) ;
3435 const queryClient = useQueryClient ( ) ;
3536 const { ydoc } = useYDocStore ( ) ;
37+ const { getIntersectingNodes } = useReactFlow ( ) ;
3638
3739 const workspace = useWorkspace ( ) ;
3840
@@ -70,23 +72,17 @@ export const useCanvas = () => {
7072 useEffect ( ( ) => {
7173 const yTitleMap = ydoc . getMap ( "title" ) ;
7274 const yEmojiMap = ydoc . getMap ( "emoji" ) ;
73-
7475 const nodesMap = ydoc . getMap ( "nodes" ) ;
7576
7677 yTitleMap . observeDeep ( ( event ) => {
7778 if ( ! event [ 0 ] . path . length ) return ;
78-
7979 const pageId = event [ 0 ] . path [ 0 ] . toString ( ) . split ( "_" ) [ 1 ] ;
8080 const value = event [ 0 ] . target . toString ( ) ;
81-
8281 const existingNode = nodesMap . get ( pageId ) as YNode ;
8382
8483 const newNode : YNode = {
85- id : pageId ,
86- type : "note" ,
87- data : { title : value , id : pageId , emoji : existingNode . data . emoji } ,
88- position : existingNode . position ,
89- selected : false ,
84+ ...existingNode ,
85+ data : { ...existingNode . data , title : value } ,
9086 isHolding : false ,
9187 } ;
9288
@@ -95,18 +91,13 @@ export const useCanvas = () => {
9591
9692 yEmojiMap . observeDeep ( ( event ) => {
9793 if ( ! event [ 0 ] . path . length ) return ;
98-
9994 const pageId = event [ 0 ] . path [ 0 ] . toString ( ) . split ( "_" ) [ 1 ] ;
10095 const value = event [ 0 ] . target . toString ( ) ;
101-
10296 const existingNode = nodesMap . get ( pageId ) as YNode ;
10397
10498 const newNode : YNode = {
105- id : pageId ,
106- type : "note" ,
107- data : { title : existingNode . data . title , id : pageId , emoji : value } ,
108- position : existingNode . position ,
109- selected : false ,
99+ ...existingNode ,
100+ data : { ...existingNode . data , emoji : value } ,
110101 isHolding : false ,
111102 } ;
112103
@@ -118,7 +109,6 @@ export const useCanvas = () => {
118109 if ( ! ydoc ) return ;
119110
120111 const wsProvider = createSocketIOProvider ( "flow-room" , ydoc ) ;
121-
122112 provider . current = wsProvider ;
123113
124114 const nodesMap = ydoc . getMap ( "nodes" ) ;
@@ -240,13 +230,17 @@ export const useCanvas = () => {
240230 if ( change . type === "position" && change . position ) {
241231 const node = nodes . find ( ( n ) => n . id === change . id ) ;
242232 if ( node ) {
243- const updatedYNode : YNode = {
244- ...node ,
245- position : change . position ,
246- selected : false ,
247- isHolding : holdingNodeRef . current === change . id ,
248- } ;
249- nodesMap . set ( change . id , updatedYNode ) ;
233+ onNodesChange ( [ change ] ) ;
234+
235+ const currentNode = nodes . find ( ( n ) => n . id === change . id ) ;
236+ if ( currentNode ) {
237+ nodesMap . set ( change . id , {
238+ ...currentNode ,
239+ position : change . position ,
240+ selected : false ,
241+ isHolding : holdingNodeRef . current === change . id ,
242+ } ) ;
243+ }
250244
251245 const affectedEdges = edges . filter (
252246 ( edge ) => edge . source === change . id || edge . target === change . id ,
@@ -270,10 +264,10 @@ export const useCanvas = () => {
270264 }
271265 } ) ;
272266 }
267+ } else {
268+ onNodesChange ( [ change ] ) ;
273269 }
274270 } ) ;
275-
276- onNodesChange ( changes ) ;
277271 } ,
278272 [ nodes , edges , onNodesChange ] ,
279273 ) ;
@@ -341,12 +335,112 @@ export const useCanvas = () => {
341335 if ( ydoc ) {
342336 const nodesMap = ydoc . getMap ( "nodes" ) ;
343337 const yNode = nodesMap . get ( node . id ) as YNode | undefined ;
338+
344339 if ( yNode ) {
345- nodesMap . set ( node . id , { ...yNode , isHolding : false } ) ;
340+ const currentNode = nodes . find ( ( n ) => n . id === node . id ) ;
341+ if ( ! currentNode ) return ;
342+
343+ if ( node . type === "group" ) {
344+ const intersectingNotes = getIntersectingNodes ( currentNode ) . filter (
345+ ( n ) => n . type === "note" && ! n . parentId ,
346+ ) ;
347+
348+ intersectingNotes . forEach ( ( noteNode ) => {
349+ const relativePosition = {
350+ x : noteNode . position . x - currentNode . position . x ,
351+ y : noteNode . position . y - currentNode . position . y ,
352+ } ;
353+
354+ nodesMap . set ( noteNode . id , {
355+ ...noteNode ,
356+ parentId : node . id ,
357+ position : relativePosition ,
358+ isHolding : false ,
359+ } ) ;
360+ } ) ;
361+
362+ nodesMap . set ( node . id , {
363+ ...currentNode ,
364+ isHolding : false ,
365+ } ) ;
366+ } else {
367+ const intersectingGroups = getIntersectingNodes ( currentNode ) . filter (
368+ ( n ) => n . type === "group" ,
369+ ) ;
370+
371+ if ( intersectingGroups . length > 0 ) {
372+ const parentNode =
373+ intersectingGroups [ intersectingGroups . length - 1 ] ;
374+
375+ if ( yNode . parentId === parentNode . id ) {
376+ nodesMap . set ( node . id , {
377+ ...yNode ,
378+ position : currentNode . position ,
379+ isHolding : false ,
380+ } ) ;
381+ } else {
382+ let absolutePosition = currentNode . position ;
383+ if ( yNode . parentId ) {
384+ const oldParentNode = nodes . find (
385+ ( n ) => n . id === yNode . parentId ,
386+ ) ;
387+ if ( oldParentNode ) {
388+ absolutePosition = {
389+ x : oldParentNode . position . x + currentNode . position . x ,
390+ y : oldParentNode . position . y + currentNode . position . y ,
391+ } ;
392+ }
393+ }
394+
395+ const relativePosition = {
396+ x : absolutePosition . x - parentNode . position . x ,
397+ y : absolutePosition . y - parentNode . position . y ,
398+ } ;
399+
400+ nodesMap . set ( node . id , {
401+ ...currentNode ,
402+ parentId : parentNode . id ,
403+ position : relativePosition ,
404+ isHolding : false ,
405+ } ) ;
406+ }
407+ } else {
408+ if ( yNode . parentId ) {
409+ const oldParentNode = nodes . find (
410+ ( n ) => n . id === yNode . parentId ,
411+ ) ;
412+ if ( oldParentNode ) {
413+ const absolutePosition = {
414+ x : oldParentNode . position . x + currentNode . position . x ,
415+ y : oldParentNode . position . y + currentNode . position . y ,
416+ } ;
417+
418+ nodesMap . set ( node . id , {
419+ ...currentNode ,
420+ parentId : undefined ,
421+ position : absolutePosition ,
422+ isHolding : false ,
423+ } ) ;
424+ }
425+ } else {
426+ nodesMap . set ( node . id , {
427+ ...currentNode ,
428+ parentId : undefined ,
429+ isHolding : false ,
430+ } ) ;
431+ }
432+ }
433+ }
434+
435+ setNodes ( ( ns ) => {
436+ const groups = ns . filter ( ( n ) => n . type === "group" ) ;
437+ const notes = ns . filter ( ( n ) => n . type !== "group" ) ;
438+ return [ ...groups , ...notes ] ;
439+ } ) ;
346440 }
347441 }
348442 } ,
349- [ ydoc ] ,
443+ [ ydoc , getIntersectingNodes , nodes , setNodes ] ,
350444 ) ;
351445
352446 return {
0 commit comments