@@ -7,13 +7,13 @@ import React, {
7
7
useEffect ,
8
8
} from 'react'
9
9
import { Flow , PipeData , PipeMeta } from 'src/types/flows'
10
- import { useParams } from 'react-router'
11
10
import { FlowListContext , FlowListProvider } from 'src/flows/context/flow.list'
12
11
import { v4 as UUID } from 'uuid'
13
12
import { DEFAULT_PROJECT_NAME , PIPE_DEFINITIONS } from 'src/flows'
14
13
import { isFlagEnabled } from 'src/shared/utils/featureFlag'
15
14
import * as Y from 'yjs'
16
15
import { WebsocketProvider } from 'y-websocket'
16
+ import { serialize , hydrate } from 'src/flows/context/flow.list'
17
17
18
18
export interface FlowContextType {
19
19
name : string
@@ -45,13 +45,10 @@ export const FlowProvider: FC = ({children}) => {
45
45
const { flows, update, currentID} = useContext ( FlowListContext )
46
46
const [ currentFlow , setCurrentFlow ] = useState < Flow > ( )
47
47
48
- const yDoc = useRef ( new Y . Doc ( ) )
49
48
const provider = useRef < WebsocketProvider > ( )
50
-
51
- const { id : flowId } = useParams < { id : string } > ( )
52
-
49
+ const yDoc = useRef ( new Y . Doc ( ) )
53
50
function disconnectProvider ( ) {
54
- if ( provider . current ?. wsconnected ) {
51
+ if ( provider . current ) {
55
52
provider . current . disconnect ( )
56
53
}
57
54
}
@@ -68,38 +65,49 @@ export const FlowProvider: FC = ({children}) => {
68
65
}
69
66
} , [ flows , currentID ] )
70
67
68
+ const syncFunc = useCallback (
69
+ ( isSynced : boolean ) => {
70
+ if ( ! isSynced || ! yDoc . current ) {
71
+ return
72
+ }
73
+ const { flowUpdateData} = yDoc . current . getMap ( 'flowUpdateData' ) ?. toJSON ( )
74
+ if ( ! flowUpdateData && currentFlow ) {
75
+ yDoc . current
76
+ . getMap ( 'flowUpdateData' )
77
+ . set ( 'flowUpdateData' , serialize ( currentFlow ) )
78
+ }
79
+ } ,
80
+ [ currentFlow ]
81
+ )
82
+
71
83
useEffect ( ( ) => {
72
- if ( isFlagEnabled ( 'sharedFlowEditing' ) ) {
84
+ const doc = yDoc . current
85
+ if ( isFlagEnabled ( 'sharedFlowEditing' ) && currentID ) {
73
86
provider . current = new WebsocketProvider (
87
+ // 'ws://localhost:1223', // todo(ariel): replace this with an actual API that we setup
74
88
'wss://demos.yjs.dev' , // todo(ariel): replace this with an actual API that we setup
75
- flowId , // todo(ariel): we might need to confine this to an org, depends on how multi-org plays out
76
- yDoc . current
89
+ currentID ,
90
+ doc
77
91
)
78
- provider . current . on ( 'sync' , isSynced => {
79
- if ( isSynced ) {
80
- const localState = yDoc . current . getMap ( 'localState' ) ?. toJSON ( )
81
- if ( ! localState ) {
82
- yDoc . current . getMap ( 'localState' ) . set ( 'localState' , currentFlow )
83
- }
84
- }
85
- } )
86
- yDoc . current . on ( 'update' , ( ) => {
87
- const { localState} = yDoc . current . getMap ( 'localState' ) . toJSON ( )
88
- setCurrentFlow ( prev => {
89
- if ( btoa ( JSON . stringify ( prev ) ) === btoa ( JSON . stringify ( localState ) ) ) {
90
- return prev
91
- }
92
- return localState
93
- } )
94
- } )
92
+
93
+ provider . current . on ( 'sync' , syncFunc )
95
94
}
96
95
96
+ const onUpdate = ( ) => {
97
+ const { flowUpdateData} = doc . getMap ( 'flowUpdateData' ) . toJSON ( )
98
+ const hydrated = hydrate ( flowUpdateData ?. data )
99
+
100
+ setCurrentFlow ( hydrated )
101
+ }
102
+
103
+ doc . on ( 'update' , onUpdate )
97
104
return ( ) => {
98
105
if ( isFlagEnabled ( 'sharedFlowEditing' ) ) {
99
106
disconnectProvider ( )
100
107
}
108
+ doc . off ( 'update' , onUpdate )
101
109
}
102
- } , [ flowId ] )
110
+ } , [ currentID ] )
103
111
104
112
const updateData = useCallback (
105
113
( id : string , data : Partial < PipeData > ) => {
@@ -110,11 +118,9 @@ export const FlowProvider: FC = ({children}) => {
110
118
...( flowCopy . data . byID [ id ] || { } ) ,
111
119
...data ,
112
120
}
113
- const update = {
114
- ...flowCopy ,
115
- ...flowCopy . data . byID [ id ] ,
116
- }
117
- yDoc . current . getMap ( 'localState' ) . set ( 'localState' , update )
121
+ yDoc . current
122
+ . getMap ( 'flowUpdateData' )
123
+ . set ( 'flowUpdateData' , serialize ( flowCopy ) )
118
124
}
119
125
return
120
126
}
@@ -154,11 +160,9 @@ export const FlowProvider: FC = ({children}) => {
154
160
...meta ,
155
161
}
156
162
157
- const update = {
158
- ...flowCopy ,
159
- ...flowCopy . meta . byID [ id ] ,
160
- }
161
- yDoc . current . getMap ( 'localState' ) . set ( 'localState' , update )
163
+ yDoc . current
164
+ . getMap ( 'flowUpdateData' )
165
+ . set ( 'flowUpdateData' , serialize ( flowCopy ) )
162
166
}
163
167
return
164
168
}
@@ -198,9 +202,9 @@ export const FlowProvider: FC = ({children}) => {
198
202
for ( const ni in flow ) {
199
203
flowCopy [ ni ] = flow [ ni ]
200
204
}
201
- yDoc . current . getMap ( 'localState' ) . set ( 'localState' , {
202
- ... flowCopy ,
203
- } )
205
+ yDoc . current
206
+ . getMap ( 'flowUpdateData' )
207
+ . set ( 'flowUpdateData' , serialize ( flowCopy ) )
204
208
}
205
209
return
206
210
}
@@ -248,9 +252,9 @@ export const FlowProvider: FC = ({children}) => {
248
252
flowCopy . data . allIDs . push ( id )
249
253
flowCopy . meta . allIDs . push ( id )
250
254
}
251
- yDoc . current . getMap ( 'localState' ) . set ( 'localState' , {
252
- ... flowCopy ,
253
- } )
255
+ yDoc . current
256
+ . getMap ( 'flowUpdateData' )
257
+ . set ( 'flowUpdateData' , serialize ( flowCopy ) )
254
258
return
255
259
}
256
260
if ( isFlagEnabled ( 'ephemeralNotebook' ) && ! currentFlow . id ) {
@@ -299,9 +303,9 @@ export const FlowProvider: FC = ({children}) => {
299
303
300
304
delete flowCopy . data . byID [ id ]
301
305
delete flowCopy . meta . byID [ id ]
302
- yDoc . current . getMap ( 'localState' ) . set ( 'localState' , {
303
- ... flowCopy ,
304
- } )
306
+ yDoc . current
307
+ . getMap ( 'flowUpdateData' )
308
+ . set ( 'flowUpdateData' , serialize ( flowCopy ) )
305
309
return
306
310
}
307
311
if ( isFlagEnabled ( 'ephemeralNotebook' ) && ! currentFlow . id ) {
0 commit comments