@@ -21,7 +21,6 @@ import "@xyflow/react/dist/style.css";
21
21
import { usePages } from "@/hooks/usePages" ;
22
22
import { NoteNode } from "./NoteNode" ;
23
23
import * as Y from "yjs" ;
24
- // import { WebsocketProvider } from "y-websocket";
25
24
import { SocketIOProvider } from "y-socket.io" ;
26
25
import { cn } from "@/lib/utils" ;
27
26
import { useQueryClient } from "@tanstack/react-query" ;
@@ -34,6 +33,10 @@ import { getHandlePosition } from "@/lib/getHandlePosition";
34
33
35
34
const proOptions = { hideAttribution : true } ;
36
35
36
+ interface YNode extends Node {
37
+ isHolding : boolean ;
38
+ }
39
+
37
40
interface CanvasProps {
38
41
className ?: string ;
39
42
}
@@ -54,6 +57,7 @@ function Flow({ className }: CanvasProps) {
54
57
55
58
const provider = useRef < SocketIOProvider > ( ) ;
56
59
const existingPageIds = useRef ( new Set < string > ( ) ) ;
60
+ const holdingNodeRef = useRef < string | null > ( null ) ;
57
61
58
62
useEffect ( ( ) => {
59
63
if ( ! pages ) return ;
@@ -93,7 +97,15 @@ function Flow({ className }: CanvasProps) {
93
97
const nodesMap = ydoc . getMap ( "nodes" ) ;
94
98
const edgesMap = ydoc . getMap ( "edges" ) ;
95
99
96
- const initialNodes = Array . from ( nodesMap . values ( ) ) as Node [ ] ;
100
+ const yNodes = Array . from ( nodesMap . values ( ) ) as YNode [ ] ;
101
+
102
+ const initialNodes = yNodes . map ( ( yNode ) => {
103
+ const nodeEntries = Object . entries ( yNode ) . filter (
104
+ ( [ key ] ) => key !== "isHolding" ,
105
+ ) ;
106
+ return Object . fromEntries ( nodeEntries ) as Node ;
107
+ } ) ;
108
+
97
109
setNodes ( initialNodes ) ;
98
110
99
111
let isInitialSync = true ;
@@ -107,7 +119,11 @@ function Flow({ className }: CanvasProps) {
107
119
event . changes . keys . forEach ( ( change , key ) => {
108
120
const nodeId = key ;
109
121
if ( change . action === "add" || change . action === "update" ) {
110
- const updatedNode = nodesMap . get ( nodeId ) as Node ;
122
+ const updatedYNode = nodesMap . get ( nodeId ) as YNode ;
123
+ const updatedNodeEntries = Object . entries ( updatedYNode ) . filter (
124
+ ( [ key ] ) => key !== "isHolding" ,
125
+ ) ;
126
+ const updatedNode = Object . fromEntries ( updatedNodeEntries ) as Node ;
111
127
112
128
if ( change . action === "add" ) {
113
129
queryClient . invalidateQueries ( { queryKey : [ "pages" ] } ) ;
@@ -157,9 +173,9 @@ function Flow({ className }: CanvasProps) {
157
173
158
174
pages . forEach ( ( page ) => {
159
175
const pageId = page . id . toString ( ) ;
160
- const existingNode = nodesMap . get ( pageId ) as Node | undefined ;
176
+ const existingNode = nodesMap . get ( pageId ) as YNode | undefined ;
161
177
162
- const newNode = {
178
+ const newNode : YNode = {
163
179
id : pageId ,
164
180
type : "note" ,
165
181
data : { title : page . title , id : page . id } ,
@@ -168,6 +184,7 @@ function Flow({ className }: CanvasProps) {
168
184
y : Math . random ( ) * 500 ,
169
185
} ,
170
186
selected : false ,
187
+ isHolding : false ,
171
188
} ;
172
189
173
190
nodesMap . set ( pageId , newNode ) ;
@@ -185,12 +202,13 @@ function Flow({ className }: CanvasProps) {
185
202
if ( change . type === "position" && change . position ) {
186
203
const node = nodes . find ( ( n ) => n . id === change . id ) ;
187
204
if ( node ) {
188
- const updatedNode = {
205
+ const updatedYNode : YNode = {
189
206
...node ,
190
207
position : change . position ,
191
208
selected : false ,
209
+ isHolding : holdingNodeRef . current === change . id ,
192
210
} ;
193
- nodesMap . set ( change . id , updatedNode ) ;
211
+ nodesMap . set ( change . id , updatedYNode ) ;
194
212
195
213
edges . forEach ( ( edge ) => {
196
214
if ( edge . source === change . id || edge . target === change . id ) {
@@ -330,6 +348,25 @@ function Flow({ className }: CanvasProps) {
330
348
[ setEdges , edges , nodes , ydoc ] ,
331
349
) ;
332
350
351
+ const onNodeDragStart = useCallback (
352
+ ( _event : React . MouseEvent , node : Node ) => {
353
+ holdingNodeRef . current = node . id ;
354
+ } ,
355
+ [ ] ,
356
+ ) ;
357
+
358
+ const onNodeDragStop = useCallback (
359
+ ( _event : React . MouseEvent , node : Node ) => {
360
+ if ( ydoc ) {
361
+ const nodesMap = ydoc . getMap ( "nodes" ) ;
362
+ const yNode = nodesMap . get ( node . id ) as YNode | undefined ;
363
+ if ( yNode ) {
364
+ nodesMap . set ( node . id , { ...yNode , isHolding : false } ) ;
365
+ }
366
+ }
367
+ } ,
368
+ [ ydoc ] ,
369
+ ) ;
333
370
const nodeTypes = useMemo ( ( ) => ( { note : NoteNode } ) , [ ] ) ;
334
371
335
372
return (
@@ -341,6 +378,8 @@ function Flow({ className }: CanvasProps) {
341
378
onEdgesChange = { handleEdgesChange }
342
379
onMouseLeave = { handleMouseLeave }
343
380
onNodeDrag = { handleNodeDrag }
381
+ onNodeDragStart = { onNodeDragStart }
382
+ onNodeDragStop = { onNodeDragStop }
344
383
onConnect = { onConnect }
345
384
proOptions = { proOptions }
346
385
nodeTypes = { nodeTypes }
0 commit comments