@@ -18,7 +18,9 @@ import CommsPanel from "./CommsPanel";
18
18
19
19
import { diff_match_patch } from "diff-match-patch" ;
20
20
import { callFormatter } from "@/app/api/internal/formatter/helper" ;
21
+ import { connect } from "http2" ;
21
22
23
+ const PING_INTERVAL_MILLISECONDS = 3000 ;
22
24
const languages : Language [ ] = [ "javascript" , "python" , "c_cpp" ] ;
23
25
24
26
const themes = [
@@ -50,7 +52,7 @@ interface Props {
50
52
}
51
53
52
54
interface Message {
53
- type : "content_change" | "auth" | "close_session" ;
55
+ type : "content_change" | "auth" | "close_session" | "ping" ;
54
56
data ?: string ;
55
57
userId ?: string | undefined ;
56
58
token ?: string ;
@@ -73,6 +75,8 @@ export default function CollabEditor({
73
75
const [ value , setValue ] = useState ( questionSeed ) ;
74
76
const [ socket , setSocket ] = useState < WebSocket | null > ( null ) ;
75
77
const [ connected , setConnected ] = useState ( false ) ;
78
+ const [ otherUserConnected , setOtherUserConnected ] = useState < boolean > ( false ) ;
79
+ const [ lastPingReceived , setLastPingReceived ] = useState < number | null > ( null ) ;
76
80
const router = useRouter ( ) ;
77
81
78
82
const generatePatch = ( oldContent : string , newContent : string ) : string => {
@@ -168,6 +172,8 @@ export default function CollabEditor({
168
172
}
169
173
router . push ( "/questions" ) ;
170
174
} else {
175
+ // seem to be getting json error here. logs show messages of "ping" type with both user ids tho
176
+ console . log ( event . data ) ;
171
177
const message : Message = JSON . parse ( event . data ) ;
172
178
173
179
if ( message . type === "content_change" && message . userId !== userId ) {
@@ -183,6 +189,12 @@ export default function CollabEditor({
183
189
return applyPatches ( currentValue , message . data ) ;
184
190
} ) ;
185
191
}
192
+
193
+ if ( message . type === "ping" && message . userId !== userId ) {
194
+ console . log ( "other user connected!" ) ;
195
+ setOtherUserConnected ( true ) ;
196
+ setLastPingReceived ( Date . now ( ) ) ;
197
+ }
186
198
}
187
199
} ;
188
200
@@ -204,6 +216,42 @@ export default function CollabEditor({
204
216
} ;
205
217
} , [ ] ) ;
206
218
219
+ // ping ws
220
+ const notifyRoomOfConnection = async ( ) => {
221
+ // send message over ws
222
+ if ( socket ) {
223
+ const msg : Message = {
224
+ type : "ping" ,
225
+ data : "pinging" ,
226
+ userId : userId ,
227
+ } ;
228
+ socket . send ( JSON . stringify ( msg ) ) ;
229
+ }
230
+ } ;
231
+
232
+ useEffect ( ( ) => {
233
+ if ( ! connected || ! socket ) return ;
234
+
235
+ const interval = setInterval (
236
+ notifyRoomOfConnection ,
237
+ PING_INTERVAL_MILLISECONDS ,
238
+ ) ;
239
+
240
+ const disconnectCheckInterval = setInterval ( ( ) => {
241
+ if (
242
+ lastPingReceived &&
243
+ Date . now ( ) - lastPingReceived > 2 * PING_INTERVAL_MILLISECONDS
244
+ ) {
245
+ setOtherUserConnected ( false ) ;
246
+ clearInterval ( disconnectCheckInterval ) ;
247
+ }
248
+ } , PING_INTERVAL_MILLISECONDS ) ;
249
+ return ( ) => {
250
+ clearInterval ( interval ) ;
251
+ clearInterval ( disconnectCheckInterval ) ;
252
+ } ;
253
+ } , [ notifyRoomOfConnection , PING_INTERVAL_MILLISECONDS , connected , socket ] ) ;
254
+
207
255
const handleCloseConnection = ( ) => {
208
256
const confirmClose = confirm (
209
257
"Are you sure you are finished? This will close the room for all users." ,
@@ -224,7 +272,7 @@ export default function CollabEditor({
224
272
{ connected && (
225
273
< CommsPanel className = "flex flex-row justify-around" roomId = { roomID } />
226
274
) }
227
- < div className = "m-4 flex items-center space-x-4 p-4" >
275
+ < div className = "m-4 flex items-end space-x-4 p-4" >
228
276
< div className = "flex flex-col" >
229
277
< label className = "mb-1 font-semibold" > Font Size</ label >
230
278
< input
@@ -261,13 +309,13 @@ export default function CollabEditor({
261
309
262
310
{ roomID &&
263
311
( connected ? (
264
- < div className = "h-full align-middle" >
312
+ < div className = "align-middle" >
265
313
< PeerprepButton onClick = { handleCloseConnection } >
266
314
Close Room
267
315
</ PeerprepButton >
268
316
</ div >
269
317
) : (
270
- < div className = "h-full align-middle" >
318
+ < div className = "align-middle" >
271
319
< PeerprepButton
272
320
onClick = { handleCloseConnection }
273
321
className = "disabled"
@@ -277,6 +325,23 @@ export default function CollabEditor({
277
325
</ div >
278
326
) ) }
279
327
</ div >
328
+ { roomID &&
329
+ ( connected ? (
330
+ < div className = "flex items-center space-x-2 p-2" >
331
+ < span
332
+ className = { `h-4 w-4 rounded-full ${
333
+ otherUserConnected ? "bg-difficulty-easy" : "bg-difficulty-hard"
334
+ } `}
335
+ > </ span >
336
+ < span >
337
+ { otherUserConnected
338
+ ? "Other user connected"
339
+ : "Other user disconnected" }
340
+ </ span >
341
+ </ div >
342
+ ) : (
343
+ < div className = "py-2" > Disconnected. Check logs.</ div >
344
+ ) ) }
280
345
< AceEditor
281
346
mode = { language }
282
347
className = { "editor" }
0 commit comments