diff --git a/client/src/components/ConferencePage/ConferencePage.tsx b/client/src/components/ConferencePage/ConferencePage.tsx index 8bc2a02..0a6553f 100644 --- a/client/src/components/ConferencePage/ConferencePage.tsx +++ b/client/src/components/ConferencePage/ConferencePage.tsx @@ -13,22 +13,23 @@ const StatusThumbsUp = 'thumbs-up'; const StatusThumbsDown = 'thumbs-down'; const StatusNoVote = 'no-vote'; +const HeartbeatInterval = 5000; + export const ConferencePage:FunctionComponent = () => { const { user } = useUserProfile(); - const { id, data, peers, setNickname, setEmail, ping, setStatus } = useConference(); + const { uuid, data, setNickname, setEmail, ping, setStatus, forget } = useConference(); - const currentStatus = data.statuses[id]; + const currentStatus = data.statuses[uuid]; useEffect(() => { - if (peers.length === 0) return; - if (!id || (!user.name && !user.email)) return; + if (!user.name && !user.email) return; setNickname(user.name || user.email.split('@')[0]); setEmail(user.email); - }, [user.name, user.email, peers.length]); + }, [user.name, user.email]); useEffect(() => { ping(); - const intervalId = setInterval(() => ping(), 30000); + const intervalId = setInterval(() => ping(), HeartbeatInterval); return () => clearInterval(intervalId); }, []); @@ -78,11 +79,21 @@ export const ConferencePage:FunctionComponent = () => {

Assemblée

{ - peers.map(p => { + Object.keys(data.peers).map(p => { + const now = new Date(); + const lastHeartBeat = new Date(data.peers[p]); + + if (p === uuid) return null; + + if (now.getTime() > lastHeartBeat.getTime() + HeartbeatInterval) { + forget(p); + return null; + } + const nickname = data.nicknames[p] || '???'; const email = data.emails[p] || ''; return ( diff --git a/client/src/hooks/useConference.tsx b/client/src/hooks/useConference.tsx index 0c94e5b..6295524 100644 --- a/client/src/hooks/useConference.tsx +++ b/client/src/hooks/useConference.tsx @@ -1,19 +1,21 @@ import * as Y from 'yjs' import { WebrtcProvider, } from 'y-webrtc' import { useEffect, useRef, useState } from 'react' +import { uuidV4 } from '../util/uuid'; + +const uuid = uuidV4(); export function useConference() { const docRef = useRef(new Y.Doc()); const [ state, setState ] = useState({ data: { - heartbeats: {}, emails: {}, nicknames: {}, statuses: {}, + peers: {}, }, - peers: [], - id: null, + uuid, }); const setData = (key: string, value: any) => { @@ -25,17 +27,8 @@ export function useConference() { const roomName = `${window.location.protocol}//${window.location.host}/daddy/conference`; const provider = new WebrtcProvider(roomName, docRef.current); - const onPeers = (evt) => { - let peers = [...state.peers]; - peers = peers.filter(p => evt.removed.indexOf(p) === -1); - peers.push(...evt.added); - setState(state => ({ ...state, id: provider.room.peerId, peers })); - }; - - provider.on('peers', onPeers); - - const heartbeats = doc.getMap('heartbeats'); - heartbeats.observe(evt => setData('heartbeats', evt.currentTarget.toJSON())); + const peers = doc.getMap('peers'); + peers.observe(evt => setData('peers', evt.currentTarget.toJSON())); const nicknames = doc.getMap('nicknames'); nicknames.observe(evt => setData('nicknames', evt.currentTarget.toJSON())); @@ -47,7 +40,6 @@ export function useConference() { statuses.observe(evt => setData('statuses', evt.currentTarget.toJSON())); return () => { - provider.off('peers', onPeers); provider.destroy(); docRef.current.destroy(); }; @@ -55,31 +47,38 @@ export function useConference() { return { data: state.data, - peers: state.peers, - id: state.id, + uuid: state.uuid, setStatus: (status: string) => { const doc = docRef.current; const statuses = doc.getMap('statuses'); - statuses.set(state.id, status); + statuses.set(state.uuid, status); }, ping: () => { const doc = docRef.current; - const heartbeats = doc.getMap('heartbeats'); - heartbeats.set(state.id, (new Date()).toJSON()); + const peers = doc.getMap('peers'); + peers.set(state.uuid, (new Date()).toJSON()); }, setNickname: (nickname: string) => { + console.log('setNickname', nickname); const doc = docRef.current; const nicknames = doc.getMap('nicknames'); - nicknames.set(state.id, nickname); + nicknames.set(state.uuid, nickname); }, setEmail: (email: string) => { + console.log('setEmail', email); const doc = docRef.current; const emails = doc.getMap('emails'); - emails.set(state.id, email); + emails.set(state.uuid, email); + }, + + forget: (uuid: string) => { + const doc = docRef.current; + const peers = doc.getMap('peers'); + peers.delete(uuid); }, }; } \ No newline at end of file