From eecb1280413a7364be05c8515095304c1ea472e7 Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Tue, 23 Feb 2021 10:57:39 -0800 Subject: [PATCH 01/10] First pass at handleTrackStarted function --- src/components/Call/Call.js | 199 +++++++++++++++++++++++++++++------- 1 file changed, 163 insertions(+), 36 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index 339ef66..57f7008 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -1,4 +1,10 @@ -import React, { useEffect, useContext, useReducer, useCallback } from 'react'; +import React, { + useEffect, + useContext, + useReducer, + useState, + useCallback, +} from 'react'; import './Call.css'; import Tile from '../Tile/Tile'; import CallObjectContext from '../../CallObjectContext'; @@ -10,9 +16,10 @@ import { CAM_OR_MIC_ERROR, FATAL_ERROR, callReducer, - isLocal, - isScreenShare, - containsScreenShare, + // isLocal, + // isScreenShare, + // containsScreenShare, + // shouldIncludeScreenCallItem, getMessage, } from './callState'; import { logDailyEvent } from '../../logUtils'; @@ -20,6 +27,11 @@ import { logDailyEvent } from '../../logUtils'; export default function Call() { const callObject = useContext(CallObjectContext); const [callState, dispatch] = useReducer(callReducer, initialCallState); + const [isScreenSharing, setScreenSharing] = useState(false); + const [screenShareTrackId, setScreenShareTrackId] = useState(''); + const toggleScreenShare = () => setScreenSharing(!isScreenSharing); + const [largeTiles, setLargeTiles] = useState([]); + const [smallTiles, setSmallTiles] = useState([]); /** * Start listening for participant changes, when the callObject is set. @@ -57,6 +69,82 @@ export default function Call() { }; }, [callObject]); + // Validate screenshare state changes + useEffect(() => { + if (isScreenSharing) { + console.log(`New screen sharing state is: ${isScreenSharing}`); + console.log(`The track that is being shared is: ${screenShareTrackId}`); + } + }); + + /** + * When a track starts, display a participant's video or audio + */ + useEffect(() => { + if (!callObject) return; + + function handleTrackStarted(event) { + // logDailyEvent(event); + console.log(`track started: ${event}`); + let trackType = event.track.kind; + let trackId = event.track.id; + let screenVideoTrackState = event.participant.tracks.screenVideo.track; + console.log(`This is the track that started: ${trackId}`); + + if (typeof screenVideoTrackState === 'undefined') { + if (trackType === 'video') { + displayVideo(event); + } + if (trackType === 'audio') { + playAudio(event); + } + } else { + console.log(`SCREENSHARE started SCREENSHARE started`); + setScreenShareTrackId(trackId); + setScreenSharing(!isScreenSharing); + displayVideo(event); + } + } + + callObject.on('track-started', handleTrackStarted); + + return function cleanup() { + callObject.off('track-started', handleTrackStarted); + }; + }, [ + callObject, + isScreenSharing, + screenShareTrackId, + toggleScreenShare, + displayVideo, + ]); + + /** + * When a track stops, destroy the track + */ + useEffect(() => { + if (!callObject) return; + + function handleTrackStopped(event) { + logDailyEvent(event); + console.log(event); + let trackId = event.track.id; + console.log(`This is the track that STOPPED: ${trackId}`); + if (trackId === screenShareTrackId) { + console.log(`STOP THE SCREENSHARE`); + toggleScreenShare(); + } + // If track id is in large tiles, remove from large tiles + // If in small tiles, remove from small tiles + } + + callObject.on('track-stopped', handleTrackStopped); + + return function cleanup() { + callObject.off('track-stopped', handleTrackStopped); + }; + }, [callObject, isScreenSharing]); + /** * Start listening for call errors, when the callObject is set. */ @@ -130,40 +218,79 @@ export default function Call() { [callObject] ); - function getTiles() { - let largeTiles = []; - let smallTiles = []; - Object.entries(callState.callItems).forEach(([id, callItem]) => { - const isLarge = - isScreenShare(id) || - (!isLocal(id) && !containsScreenShare(callState.callItems)); - const tile = ( - { - sendHello(id); - } - } - /> - ); - if (isLarge) { - largeTiles.push(tile); - } else { - smallTiles.push(tile); - } - }); - return [largeTiles, smallTiles]; + function displayVideo(event) { + console.log(`Video display comin' up!`); + console.log(event); + const trackId = event.track.id; + const isLocal = event.participant.local; + const isSharedScreen = trackId === screenShareTrackId; + const isLarge = isSharedScreen || (!isLocal && !isScreenSharing); + console.log(`The track that started is large: ${isLarge}`); + + const tile = ( + { + sendHello(event.participant.session_id); + } + } + /> + ); + + if (isLarge) { + setLargeTiles(largeTiles.push(tile)); + } else { + setSmallTiles(smallTiles.push(tile)); + } } - const [largeTiles, smallTiles] = getTiles(); + function playAudio(event) { + console.log(`Audio coming your way!`); + console.log(event); + } + + // function getTiles() { + // let largeTiles = []; + // let smallTiles = []; + // Object.entries(callState.callItems).forEach(([id, callItem]) => { + // const isLarge = + // isScreenShare(id) || + // (!isLocal(id) && !containsScreenShare(callState.callItems)); + // const tile = ( + // { + // sendHello(id); + // } + // } + // /> + // ); + // if (isLarge) { + // largeTiles.push(tile); + // } else { + // smallTiles.push(tile); + // } + // }); + // return [largeTiles, smallTiles]; + // } + + // const [largeTiles, smallTiles] = getTiles(); const message = getMessage(callState); return (
From 6470cc365445bbe14b0adfa06545e084f4a15ac4 Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Thu, 25 Feb 2021 12:32:06 -0800 Subject: [PATCH 02/10] First attempt at iterating over tiles when tracks start --- src/components/Call/Call.js | 275 +++++++++++++++++-------------- src/components/Call/callState.js | 1 + src/components/Tile/Tile.js | 2 + 3 files changed, 153 insertions(+), 125 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index 57f7008..ebb5c09 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -4,6 +4,7 @@ import React, { useReducer, useState, useCallback, + useMemo, } from 'react'; import './Call.css'; import Tile from '../Tile/Tile'; @@ -36,46 +37,136 @@ export default function Call() { /** * Start listening for participant changes, when the callObject is set. */ - useEffect(() => { - if (!callObject) return; - - const events = [ - 'participant-joined', - 'participant-updated', - 'participant-left', - ]; - - function handleNewParticipantsState(event) { - event && logDailyEvent(event); - dispatch({ - type: PARTICIPANTS_CHANGE, - participants: callObject.participants(), - }); - } + // useEffect(() => { + // if (!callObject) return; + + // const events = [ + // 'participant-joined', + // 'participant-updated', + // 'participant-left', + // ]; + + // function handleNewParticipantsState(event) { + // event && logDailyEvent(event); + // dispatch({ + // type: PARTICIPANTS_CHANGE, + // participants: callObject.participants(), + // }); + // } + + // // Use initial state + // handleNewParticipantsState(); + + // // Listen for changes in state + // for (const event of events) { + // callObject.on(event, handleNewParticipantsState); + // } + + // // Stop listening for changes in state + // return function cleanup() { + // for (const event of events) { + // callObject.off(event, handleNewParticipantsState); + // } + // }; + // }, [callObject]); - // Use initial state - handleNewParticipantsState(); + // Validate screenshare state changes + // useEffect(() => { + // if (isScreenSharing) { + // console.log(`New screen sharing state is: ${isScreenSharing}`); + // console.log(`The track that is being shared is: ${screenShareTrackId}`); + // } + // }); + + const addVideoTrack = useCallback( + (event) => { + console.log(`Video display comin' up!`); + const trackId = event.track.id; + const isLocal = event.participant.local; + const isSharedScreen = trackId === screenShareTrackId; + const isLarge = isSharedScreen || (!isLocal && !isScreenSharing); + console.log(`The track that started is large: ${isLarge}`); + + const tile = { + key: trackId, + videoTrackState: event.participant.tracks.video, + audioTrackState: event.participant.tracks.audio, + isLocalPerson: isLocal, + isLarge: isLarge, + disableCornerMessage: isSharedScreen, + // onClick: isLocal + // ? null + // : () => { + // sendHello(event.participant.session_id); + // }, + }; + if (isLarge) { + setLargeTiles([...largeTiles, tile]); + } else { + setSmallTiles([...smallTiles, tile]); + } + }, + [smallTiles, largeTiles, callObject] + ); - // Listen for changes in state - for (const event of events) { - callObject.on(event, handleNewParticipantsState); - } + const displayLargeTiles = useMemo(() => { + const participantTracks = [...largeTiles]; + if (Object.entries(largeTiles).length === 0) return; + return ( +
+ {participantTracks?.map((p, i) => ( + + ))} +
+ ); + }, [largeTiles]); + + const displaySmallTiles = useMemo(() => { + const participantTracks = [...smallTiles]; + return ( +
+ {participantTracks?.map((p, i) => ( + + ))} +
+ ); + }, [smallTiles]); - // Stop listening for changes in state - return function cleanup() { - for (const event of events) { - callObject.off(event, handleNewParticipantsState); - } - }; - }, [callObject]); + /** + * When a participant is updated, update their tracks + */ + // useEffect(() => { + // if (!callObject) return; + + // function handleParticipantUpdate(event) { + // console.log('UPDATE UPDATE UPDATE'); + // console.log(event); + // if (event.participant.tracks.video.track) { + // displayVideo(event); + // } + // } + // callObject.on('participant-updated', handleParticipantUpdate); - // Validate screenshare state changes - useEffect(() => { - if (isScreenSharing) { - console.log(`New screen sharing state is: ${isScreenSharing}`); - console.log(`The track that is being shared is: ${screenShareTrackId}`); - } - }); + // return function cleanup() { + // callObject.off('participant-updated', handleParticipantUpdate); + // }; + // }, [callObject, displayVideo]); /** * When a track starts, display a participant's video or audio @@ -85,24 +176,21 @@ export default function Call() { function handleTrackStarted(event) { // logDailyEvent(event); - console.log(`track started: ${event}`); let trackType = event.track.kind; let trackId = event.track.id; let screenVideoTrackState = event.participant.tracks.screenVideo.track; - console.log(`This is the track that started: ${trackId}`); if (typeof screenVideoTrackState === 'undefined') { if (trackType === 'video') { - displayVideo(event); - } - if (trackType === 'audio') { - playAudio(event); + addVideoTrack(event); + } else if (trackType === 'audio') { + console.log(`Audio up next!`); } } else { console.log(`SCREENSHARE started SCREENSHARE started`); setScreenShareTrackId(trackId); setScreenSharing(!isScreenSharing); - displayVideo(event); + addVideoTrack(event); } } @@ -115,8 +203,9 @@ export default function Call() { callObject, isScreenSharing, screenShareTrackId, - toggleScreenShare, - displayVideo, + largeTiles, + smallTiles, + addVideoTrack, ]); /** @@ -217,95 +306,31 @@ export default function Call() { }, [callObject] ); + const message = getMessage(callState); - function displayVideo(event) { - console.log(`Video display comin' up!`); - console.log(event); - const trackId = event.track.id; - const isLocal = event.participant.local; - const isSharedScreen = trackId === screenShareTrackId; - const isLarge = isSharedScreen || (!isLocal && !isScreenSharing); - console.log(`The track that started is large: ${isLarge}`); - - const tile = ( - { - sendHello(event.participant.session_id); - } - } - /> - ); + /** + * Display a join link to share if there is only one call participant + */ + function displayJoinLink() { + let header = null; + let detail = null; - if (isLarge) { - setLargeTiles(largeTiles.push(tile)); - } else { - setSmallTiles(smallTiles.push(tile)); + if (largeTiles.length === 0) { + header = "Copy and share this page's URL to invite others"; + detail = window.location.href; } - } - function playAudio(event) { - console.log(`Audio coming your way!`); - console.log(event); + return { header, detail }; } - - // function getTiles() { - // let largeTiles = []; - // let smallTiles = []; - // Object.entries(callState.callItems).forEach(([id, callItem]) => { - // const isLarge = - // isScreenShare(id) || - // (!isLocal(id) && !containsScreenShare(callState.callItems)); - // const tile = ( - // { - // sendHello(id); - // } - // } - // /> - // ); - // if (isLarge) { - // largeTiles.push(tile); - // } else { - // smallTiles.push(tile); - // } - // }); - // return [largeTiles, smallTiles]; - // } - - // const [largeTiles, smallTiles] = getTiles(); - const message = getMessage(callState); + const joinLink = displayJoinLink(); return (
-
- { - !message - ? largeTiles - : null /* Avoid showing large tiles to make room for the message */ - } -
-
{smallTiles}
+ {displayLargeTiles} + {displaySmallTiles} {message && ( )} diff --git a/src/components/Call/callState.js b/src/components/Call/callState.js index 2163c78..0fe3f59 100644 --- a/src/components/Call/callState.js +++ b/src/components/Call/callState.js @@ -154,5 +154,6 @@ export { isLocal, isScreenShare, containsScreenShare, + shouldIncludeScreenCallItem, getMessage, }; diff --git a/src/components/Tile/Tile.js b/src/components/Tile/Tile.js index a6997da..031f32e 100644 --- a/src/components/Tile/Tile.js +++ b/src/components/Tile/Tile.js @@ -10,12 +10,14 @@ function getTrackUnavailableMessage(kind, trackState) { } else if (trackState.blocked.byDeviceMissing) { return `${kind} device missing`; } + return `${kind} blocked`; case 'off': if (trackState.off.byUser) { return `${kind} muted`; } else if (trackState.off.byBandwidth) { return `${kind} muted to save bandwidth`; } + return `${kind} off`; case 'sendable': return `${kind} not subscribed`; case 'loading': From 8a2476a9f2278c5bf1c8af3cd3a548cc3b432995 Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Thu, 25 Feb 2021 15:37:15 -0800 Subject: [PATCH 03/10] Pairing round 1 --- src/components/Call/Call.js | 53 ++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index ebb5c09..12b1219 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -33,6 +33,7 @@ export default function Call() { const toggleScreenShare = () => setScreenSharing(!isScreenSharing); const [largeTiles, setLargeTiles] = useState([]); const [smallTiles, setSmallTiles] = useState([]); + const [participants, setParticipants] = useState([]); /** * Start listening for participant changes, when the callObject is set. @@ -78,9 +79,14 @@ export default function Call() { // } // }); + // Update participant list + // When participants updates + // Have addVideoTrack as useEffect that formats into large and small tiles + const addVideoTrack = useCallback( (event) => { - console.log(`Video display comin' up!`); + console.log(`πŸŽ₯ Video display comin' up!`); + console.log(event); const trackId = event.track.id; const isLocal = event.participant.local; const isSharedScreen = trackId === screenShareTrackId; @@ -88,7 +94,6 @@ export default function Call() { console.log(`The track that started is large: ${isLarge}`); const tile = { - key: trackId, videoTrackState: event.participant.tracks.video, audioTrackState: event.participant.tracks.audio, isLocalPerson: isLocal, @@ -101,22 +106,22 @@ export default function Call() { // }, }; if (isLarge) { + console.log([...largeTiles, tile]); setLargeTiles([...largeTiles, tile]); } else { setSmallTiles([...smallTiles, tile]); } }, - [smallTiles, largeTiles, callObject] + [smallTiles, largeTiles] ); const displayLargeTiles = useMemo(() => { const participantTracks = [...largeTiles]; - if (Object.entries(largeTiles).length === 0) return; return (
{participantTracks?.map((p, i) => ( {participantTracks?.map((p, i) => ( { + console.log(`Is participants changed??? ${participants}`); + console.log(participants); + }, [participants]); + /** * When a participant is updated, update their tracks */ - // useEffect(() => { - // if (!callObject) return; + useEffect(() => { + if (!callObject) return; - // function handleParticipantUpdate(event) { - // console.log('UPDATE UPDATE UPDATE'); - // console.log(event); - // if (event.participant.tracks.video.track) { - // displayVideo(event); - // } - // } - // callObject.on('participant-updated', handleParticipantUpdate); + function handleParticipantUpdate(event) { + console.log('UPDATE UPDATE UPDATE'); + console.log(event); + setParticipants([event.participant]); + } + callObject.on('participant-updated', handleParticipantUpdate); - // return function cleanup() { - // callObject.off('participant-updated', handleParticipantUpdate); - // }; - // }, [callObject, displayVideo]); + return function cleanup() { + callObject.off('participant-updated', handleParticipantUpdate); + }; + }, [callObject, addVideoTrack]); /** * When a track starts, display a participant's video or audio @@ -175,13 +183,14 @@ export default function Call() { if (!callObject) return; function handleTrackStarted(event) { - // logDailyEvent(event); + console.log(`πŸ›€πŸ›€πŸ›€πŸ›€`); + console.log(event); let trackType = event.track.kind; let trackId = event.track.id; let screenVideoTrackState = event.participant.tracks.screenVideo.track; if (typeof screenVideoTrackState === 'undefined') { - if (trackType === 'video') { + if (trackType) { addVideoTrack(event); } else if (trackType === 'audio') { console.log(`Audio up next!`); From 11226e7bb4dcddce32e641e377c8937cf55822af Mon Sep 17 00:00:00 2001 From: Jessica Mitchell Date: Thu, 25 Feb 2021 19:14:56 -0500 Subject: [PATCH 04/10] wip = displaying all videos --- src/components/Call/Call.js | 43 +++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index 12b1219..e26eb48 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -87,17 +87,16 @@ export default function Call() { (event) => { console.log(`πŸŽ₯ Video display comin' up!`); console.log(event); - const trackId = event.track.id; - const isLocal = event.participant.local; - const isSharedScreen = trackId === screenShareTrackId; - const isLarge = isSharedScreen || (!isLocal && !isScreenSharing); + const isSharedScreen = event?.track?.id === screenShareTrackId; + const isLarge = + isSharedScreen || (!event?.participant?.local && !isScreenSharing); console.log(`The track that started is large: ${isLarge}`); - const tile = { - videoTrackState: event.participant.tracks.video, - audioTrackState: event.participant.tracks.audio, - isLocalPerson: isLocal, - isLarge: isLarge, + id: event?.participant?.session_id, + videoTrackState: event?.participant?.tracks?.video, + audioTrackState: event?.participant?.tracks?.audio, + isLocalPerson: event?.participant?.local, + isLarge, disableCornerMessage: isSharedScreen, // onClick: isLocal // ? null @@ -105,14 +104,28 @@ export default function Call() { // sendHello(event.participant.session_id); // }, }; + // Note to Kimberlee: this could be a reduce function too but I went simple + function addOrReplace(arr, obj) { + const index = arr?.findIndex((e) => e?.id === obj?.id); + if (index === -1) { + arr.push(obj); + } else { + arr[index] = obj; + } + return arr; + } + console.log(callObject.participants()); if (isLarge) { - console.log([...largeTiles, tile]); - setLargeTiles([...largeTiles, tile]); + console.log(largeTiles); + console.log(tile); + const updatedLarge = addOrReplace(largeTiles.slice(), tile); + setLargeTiles(updatedLarge); } else { - setSmallTiles([...smallTiles, tile]); + const updatedSmall = addOrReplace(smallTiles.slice(), tile); + setSmallTiles(updatedSmall); } }, - [smallTiles, largeTiles] + [smallTiles, largeTiles, callObject] ); const displayLargeTiles = useMemo(() => { @@ -135,6 +148,7 @@ export default function Call() { }, [largeTiles]); const displaySmallTiles = useMemo(() => { + console.log(smallTiles); const participantTracks = [...smallTiles]; return (
@@ -162,12 +176,13 @@ export default function Call() { * When a participant is updated, update their tracks */ useEffect(() => { + console.log('something happened'); if (!callObject) return; function handleParticipantUpdate(event) { console.log('UPDATE UPDATE UPDATE'); console.log(event); - setParticipants([event.participant]); + addVideoTrack(event); } callObject.on('participant-updated', handleParticipantUpdate); From 9f23a503c6f5c29d149fb6776c83643a4aaa52e1 Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Mon, 1 Mar 2021 16:19:13 -0800 Subject: [PATCH 05/10] First attempt at screenshare functionality --- src/components/Call/Call.js | 382 ++++++++++++++++--------------- src/components/Call/callState.js | 318 ++++++++++++------------- 2 files changed, 354 insertions(+), 346 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index e26eb48..d08cc87 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -1,7 +1,7 @@ import React, { useEffect, useContext, - useReducer, + // useReducer, useState, useCallback, useMemo, @@ -10,30 +10,28 @@ import './Call.css'; import Tile from '../Tile/Tile'; import CallObjectContext from '../../CallObjectContext'; import CallMessage from '../CallMessage/CallMessage'; -import { - initialCallState, - CLICK_ALLOW_TIMEOUT, - PARTICIPANTS_CHANGE, - CAM_OR_MIC_ERROR, - FATAL_ERROR, - callReducer, - // isLocal, - // isScreenShare, - // containsScreenShare, - // shouldIncludeScreenCallItem, - getMessage, -} from './callState'; +// import { +// initialCallState, +// CLICK_ALLOW_TIMEOUT, +// PARTICIPANTS_CHANGE, +// CAM_OR_MIC_ERROR, +// FATAL_ERROR, +// callReducer, +// isLocal, +// isScreenShare, +// containsScreenShare, +// shouldIncludeScreenCallItem, +// getMessage, +// } from './callState'; import { logDailyEvent } from '../../logUtils'; export default function Call() { const callObject = useContext(CallObjectContext); - const [callState, dispatch] = useReducer(callReducer, initialCallState); + // const [callState, dispatch] = useReducer(callReducer, initialCallState); const [isScreenSharing, setScreenSharing] = useState(false); const [screenShareTrackId, setScreenShareTrackId] = useState(''); - const toggleScreenShare = () => setScreenSharing(!isScreenSharing); - const [largeTiles, setLargeTiles] = useState([]); - const [smallTiles, setSmallTiles] = useState([]); - const [participants, setParticipants] = useState([]); + const [screenShareEvent, setScreenShareEvent] = useState({}); + const [tiles, setTiles] = useState([]); /** * Start listening for participant changes, when the callObject is set. @@ -41,14 +39,14 @@ export default function Call() { // useEffect(() => { // if (!callObject) return; - // const events = [ - // 'participant-joined', - // 'participant-updated', - // 'participant-left', - // ]; + // const es = [ + // 'participant-joined', + // 'participant-updated', + // 'participant-left', + // ]; - // function handleNewParticipantsState(event) { - // event && logDailyEvent(event); + // function handleNewParticipantsState(e) { + // e && logDailyEvent(e); // dispatch({ // type: PARTICIPANTS_CHANGE, // participants: callObject.participants(), @@ -59,53 +57,47 @@ export default function Call() { // handleNewParticipantsState(); // // Listen for changes in state - // for (const event of events) { - // callObject.on(event, handleNewParticipantsState); + // for (const e of es) { + // callObject.on(e, handleNewParticipantsState); // } // // Stop listening for changes in state // return function cleanup() { - // for (const event of events) { - // callObject.off(event, handleNewParticipantsState); + // for (const e of es) { + // callObject.off(e, handleNewParticipantsState); // } // }; // }, [callObject]); - // Validate screenshare state changes - // useEffect(() => { - // if (isScreenSharing) { - // console.log(`New screen sharing state is: ${isScreenSharing}`); - // console.log(`The track that is being shared is: ${screenShareTrackId}`); - // } - // }); - - // Update participant list - // When participants updates - // Have addVideoTrack as useEffect that formats into large and small tiles + /** + * Add or update a participant's "tile" details + */ + const addOrUpdateTile = useCallback( + (e) => { + logDailyEvent(e); - const addVideoTrack = useCallback( - (event) => { - console.log(`πŸŽ₯ Video display comin' up!`); - console.log(event); - const isSharedScreen = event?.track?.id === screenShareTrackId; + const isSharedScreen = e?.track?.id === screenShareTrackId; const isLarge = - isSharedScreen || (!event?.participant?.local && !isScreenSharing); - console.log(`The track that started is large: ${isLarge}`); + isSharedScreen || (!e?.participant?.local && !isScreenSharing); + const isLocalPerson = e?.participant?.local; + + console.log(`The trackId in addTile is ${e?.track?.id}`); + console.log(`The screenshare track in state: ${screenShareTrackId}`); + console.log(`It is a shared screen: ${isSharedScreen}`); + console.log(`The shared screen isLarge ${isLarge}`); + const tile = { - id: event?.participant?.session_id, - videoTrackState: event?.participant?.tracks?.video, - audioTrackState: event?.participant?.tracks?.audio, - isLocalPerson: event?.participant?.local, + id: e?.participant?.session_id, + videoTrackState: isSharedScreen + ? e?.participant?.tracks?.screenVideo + : e?.participant?.tracks?.video, + audioTrackState: e?.participant?.tracks?.audio, + isLocalPerson, isLarge, disableCornerMessage: isSharedScreen, - // onClick: isLocal - // ? null - // : () => { - // sendHello(event.participant.session_id); - // }, }; - // Note to Kimberlee: this could be a reduce function too but I went simple - function addOrReplace(arr, obj) { + + function addOrUpdate(arr, obj) { const index = arr?.findIndex((e) => e?.id === obj?.id); if (index === -1) { arr.push(obj); @@ -114,107 +106,88 @@ export default function Call() { } return arr; } - console.log(callObject.participants()); - if (isLarge) { - console.log(largeTiles); - console.log(tile); - const updatedLarge = addOrReplace(largeTiles.slice(), tile); - setLargeTiles(updatedLarge); - } else { - const updatedSmall = addOrReplace(smallTiles.slice(), tile); - setSmallTiles(updatedSmall); - } + + const updatedTiles = addOrUpdate(tiles.slice(), tile); + setTiles(updatedTiles); }, - [smallTiles, largeTiles, callObject] + [tiles, screenShareTrackId, isScreenSharing] ); - const displayLargeTiles = useMemo(() => { - const participantTracks = [...largeTiles]; - return ( -
- {participantTracks?.map((p, i) => ( - - ))} -
- ); - }, [largeTiles]); - - const displaySmallTiles = useMemo(() => { - console.log(smallTiles); - const participantTracks = [...smallTiles]; - return ( -
- {participantTracks?.map((p, i) => ( - - ))} -
- ); - }, [smallTiles]); + /** + * Remove a participant's tile details from state + */ + const removeTile = useCallback( + (e) => { + logDailyEvent(e); + const remainingTiles = tiles.filter( + (t) => t.id !== e?.participant?.session_id + ); + setTiles(remainingTiles); + }, + [tiles] + ); useEffect(() => { - console.log(`Is participants changed??? ${participants}`); - console.log(participants); - }, [participants]); + console.log(`New screen sharing state is: ${isScreenSharing}`); + console.log(`The track that is being shared is: ${screenShareTrackId}`); + + // addOrUpdateTile(screenShareEvent); + }, [ + isScreenSharing, + // tiles, + addOrUpdateTile, + // screenShareEvent, + screenShareTrackId, + ]); /** - * When a participant is updated, update their tracks + * When the call object is set, listen and react to participant updates */ useEffect(() => { - console.log('something happened'); if (!callObject) return; - function handleParticipantUpdate(event) { - console.log('UPDATE UPDATE UPDATE'); - console.log(event); - addVideoTrack(event); + function handleParticipantUpdate(e) { + logDailyEvent(e); + addOrUpdateTile(e); } + callObject.on('participant-updated', handleParticipantUpdate); return function cleanup() { callObject.off('participant-updated', handleParticipantUpdate); }; - }, [callObject, addVideoTrack]); + }, [callObject, addOrUpdateTile]); /** - * When a track starts, display a participant's video or audio + * When the call obect is set, listen for tracks starting and get "tile" details from the event object + * NOTE: We'll pass audio and video at once in this app, via event.participant.tracks, because our "tile" component renders both. However, it's possible, and sometimes preferred, to pass audio separately. */ useEffect(() => { if (!callObject) return; - function handleTrackStarted(event) { - console.log(`πŸ›€πŸ›€πŸ›€πŸ›€`); - console.log(event); - let trackType = event.track.kind; - let trackId = event.track.id; - let screenVideoTrackState = event.participant.tracks.screenVideo.track; + function handleTrackStarted(e) { + let trackType = e.track.kind; + let trackId = e.track.id; + let screenVideoTrackState = e.participant.tracks.screenVideo.track; + console.log(e); if (typeof screenVideoTrackState === 'undefined') { - if (trackType) { - addVideoTrack(event); + if (trackType === 'video') { + addOrUpdateTile(e); } else if (trackType === 'audio') { - console.log(`Audio up next!`); + console.log( + `We'll pass audio when we pass video, because one tile holds both tracks.` + ); } } else { - console.log(`SCREENSHARE started SCREENSHARE started`); - setScreenShareTrackId(trackId); - setScreenSharing(!isScreenSharing); - addVideoTrack(event); + if (trackType === 'video') { + console.log(`A screenshare is starting!`); + setScreenShareTrackId(trackId); + setScreenSharing(!isScreenSharing); + setScreenShareEvent(e); + } else { + console.log(`Passing screenAudio when the video starts.`); + } } } @@ -223,40 +196,28 @@ export default function Call() { return function cleanup() { callObject.off('track-started', handleTrackStarted); }; - }, [ - callObject, - isScreenSharing, - screenShareTrackId, - largeTiles, - smallTiles, - addVideoTrack, - ]); + }, [callObject, isScreenSharing, screenShareTrackId, tiles, addOrUpdateTile]); /** - * When a track stops, destroy the track + * PLACEHOLDER for track-stopped on screenshare + */ + + /** + * When the call object is set, listen for participants leaving a call and remove their tracks */ useEffect(() => { if (!callObject) return; - function handleTrackStopped(event) { - logDailyEvent(event); - console.log(event); - let trackId = event.track.id; - console.log(`This is the track that STOPPED: ${trackId}`); - if (trackId === screenShareTrackId) { - console.log(`STOP THE SCREENSHARE`); - toggleScreenShare(); - } - // If track id is in large tiles, remove from large tiles - // If in small tiles, remove from small tiles + function handleParticipantLeft(e) { + removeTile(e); } - callObject.on('track-stopped', handleTrackStopped); + callObject.on('participant-left', handleParticipantLeft); return function cleanup() { - callObject.off('track-stopped', handleTrackStopped); + callObject.off('participant-left', handleParticipantLeft); }; - }, [callObject, isScreenSharing]); + }, [callObject, isScreenSharing, removeTile]); /** * Start listening for call errors, when the callObject is set. @@ -264,18 +225,13 @@ export default function Call() { useEffect(() => { if (!callObject) return; - function handleCameraErrorEvent(event) { - logDailyEvent(event); - dispatch({ - type: CAM_OR_MIC_ERROR, - message: - (event && event.errorMsg && event.errorMsg.errorMsg) || 'Unknown', - }); + function handleCameraErrorEvent(e) { + logDailyEvent(e); + getMessage(e); } // We're making an assumption here: there is no camera error when callObject // is first assigned. - callObject.on('camera-error', handleCameraErrorEvent); return function cleanup() { @@ -291,15 +247,11 @@ export default function Call() { function handleErrorEvent(e) { logDailyEvent(e); - dispatch({ - type: FATAL_ERROR, - message: (e && e.errorMsg) || 'Unknown', - }); + getMessage(e); } // We're making an assumption here: there is no error when callObject is // first assigned. - callObject.on('error', handleErrorEvent); return function cleanup() { @@ -310,15 +262,15 @@ export default function Call() { /** * Start a timer to show the "click allow" message, when the component mounts. */ - useEffect(() => { - const t = setTimeout(() => { - dispatch({ type: CLICK_ALLOW_TIMEOUT }); - }, 2500); + // useEffect(() => { + // const t = setTimeout(() => { + // toggleShouldShowClickAllow(); + // }, 2500); - return function cleanup() { - clearTimeout(t); - }; - }, []); + // return function cleanup() { + // clearTimeout(t); + // }; + // }, [shouldShowClickAllow, toggleShouldShowClickAllow]); /** * Send an app message to the remote participant whose tile was clicked on. @@ -330,31 +282,87 @@ export default function Call() { }, [callObject] ); - const message = getMessage(callState); + + const displayLargeTiles = useMemo(() => { + const participantTracks = [...tiles]; + const largeTiles = participantTracks.filter((t) => t.isLarge === true); + return ( +
+ {largeTiles?.map((t, i) => ( + { + sendHello(t.id); + } + } + /> + ))} +
+ ); + }, [tiles, sendHello]); + + const displaySmallTiles = useMemo(() => { + const participantTracks = [...tiles]; + const smallTiles = participantTracks.filter((t) => t.isLarge === false); + return ( +
+ {smallTiles?.map((t, i) => ( + + ))} +
+ ); + }, [tiles]); /** - * Display a join link to share if there is only one call participant + * Display a message */ - function displayJoinLink() { + function getMessage(e) { let header = null; let detail = null; + let isError = false; - if (largeTiles.length === 0) { - header = "Copy and share this page's URL to invite others"; - detail = window.location.href; + if (!e) { + if (tiles.length <= 1) { + header = "Copy and share this page's URL to invite others"; + detail = window.location.href; + } + } else if (e.action === 'error') { + header = `Fatal error ${(e && e.errorMsg) || 'Unknown'}`; + } else if (e.action === 'camera-error') { + header = `Camera or mic access error: ${ + (e && e.errorMsg && e.errorMsg.errorMsg) || 'Unknown' + }`; + detail = + 'See https://help.daily.co/en/articles/2528184-unblock-camera-mic-access-on-a-computer to troubleshoot.'; + isError = true; } - - return { header, detail }; + return header || detail ? { header, detail, isError } : null; } - const joinLink = displayJoinLink(); + const message = getMessage(); return (
{displayLargeTiles} {displaySmallTiles} {message && ( )} diff --git a/src/components/Call/callState.js b/src/components/Call/callState.js index 0fe3f59..4999882 100644 --- a/src/components/Call/callState.js +++ b/src/components/Call/callState.js @@ -1,159 +1,159 @@ -/** - * Call state is comprised of: - * - "Call items" (inputs to the call, i.e. participants or shared screens) - * - UI state that depends on call items (for now, just whether to show "click allow" message) - * - * Call items are keyed by id: - * - "local" for the current participant - * - A session id for each remote participant - * - "-screen" for each shared screen - */ -const initialCallState = { - callItems: { - local: { - videoTrackState: null, - audioTrackState: null, - }, - }, - clickAllowTimeoutFired: false, - camOrMicError: null, - fatalError: null, -}; - -// --- Actions --- - -/** - * CLICK_ALLOW_TIMEOUT action structure: - * - type: string - */ -const CLICK_ALLOW_TIMEOUT = 'CLICK_ALLOW_TIMEOUT'; - -/** - * PARTICIPANTS_CHANGE action structure: - * - type: string - * - participants: Object (from Daily callObject.participants()) - */ -const PARTICIPANTS_CHANGE = 'PARTICIPANTS_CHANGE'; - -/** - * CAM_OR_MIC_ERROR action structure: - * - type: string - * - message: string - */ -const CAM_OR_MIC_ERROR = 'CAM_OR_MIC_ERROR'; - -/** - * CAM_OR_MIC_ERROR action structure: - * - type: string - * - message: string - */ -const FATAL_ERROR = 'FATAL_ERROR'; - -// --- Reducer and helpers -- - -function callReducer(callState, action) { - switch (action.type) { - case CLICK_ALLOW_TIMEOUT: - return { - ...callState, - clickAllowTimeoutFired: true, - }; - case PARTICIPANTS_CHANGE: - const callItems = getCallItems(action.participants); - return { - ...callState, - callItems, - }; - case CAM_OR_MIC_ERROR: - return { ...callState, camOrMicError: action.message }; - case FATAL_ERROR: - return { ...callState, fatalError: action.message }; - default: - throw new Error(); - } -} - -function getLocalCallItem(callItems) { - return callItems['local']; -} - -function getCallItems(participants) { - let callItems = { ...initialCallState.callItems }; // Ensure we *always* have a local participant - for (const [id, participant] of Object.entries(participants)) { - callItems[id] = { - videoTrackState: participant.tracks.video, - audioTrackState: participant.tracks.audio, - }; - if (shouldIncludeScreenCallItem(participant)) { - callItems[id + '-screen'] = { - videoTrackState: participant.tracks.screenVideo, - audioTrackState: participant.tracks.screenAudio, - }; - } - } - return callItems; -} - -function shouldIncludeScreenCallItem(participant) { - const trackStatesForInclusion = ['loading', 'playable', 'interrupted']; - return ( - trackStatesForInclusion.includes(participant.tracks.screenVideo.state) || - trackStatesForInclusion.includes(participant.tracks.screenAudio.state) - ); -} - -// --- Derived data --- - -// True if id corresponds to local participant (*not* their screen share) -function isLocal(id) { - return id === 'local'; -} - -function isScreenShare(id) { - return id.endsWith('-screen'); -} - -function containsScreenShare(callItems) { - return Object.keys(callItems).some((id) => isScreenShare(id)); -} - -function getMessage(callState) { - function shouldShowClickAllow() { - const localCallItem = getLocalCallItem(callState.callItems); - const hasLoaded = localCallItem && !localCallItem.isLoading; - return !hasLoaded && callState.clickAllowTimeoutFired; - } - - let header = null; - let detail = null; - let isError = false; - if (callState.fatalError) { - header = `Fatal error: ${callState.fatalError}`; - isError = true; - } else if (callState.camOrMicError) { - header = `Camera or mic access error: ${callState.camOrMicError}`; - detail = - 'See https://help.daily.co/en/articles/2528184-unblock-camera-mic-access-on-a-computer to troubleshoot.'; - isError = true; - } else if (shouldShowClickAllow()) { - header = 'Click "Allow" to enable camera and mic access'; - } else if (Object.keys(callState.callItems).length === 1) { - header = "Copy and share this page's URL to invite others"; - detail = window.location.href; - } - return header || detail ? { header, detail, isError } : null; -} - -export { - initialCallState, - CLICK_ALLOW_TIMEOUT, - PARTICIPANTS_CHANGE, - CAM_OR_MIC_ERROR, - FATAL_ERROR, - callReducer, - isLocal, - isScreenShare, - containsScreenShare, - shouldIncludeScreenCallItem, - getMessage, -}; +// /** +// * Call state is comprised of: +// * - "Call items" (inputs to the call, i.e. participants or shared screens) +// * - UI state that depends on call items (for now, just whether to show "click allow" message) +// * +// * Call items are keyed by id: +// * - "local" for the current participant +// * - A session id for each remote participant +// * - "-screen" for each shared screen +// */ +// const initialCallState = { +// callItems: { +// local: { +// videoTrackState: null, +// audioTrackState: null, +// }, +// }, +// clickAllowTimeoutFired: false, +// camOrMicError: null, +// fatalError: null, +// }; + +// // --- Actions --- + +// /** +// * CLICK_ALLOW_TIMEOUT action structure: +// * - type: string +// */ +// const CLICK_ALLOW_TIMEOUT = 'CLICK_ALLOW_TIMEOUT'; + +// /** +// * PARTICIPANTS_CHANGE action structure: +// * - type: string +// * - participants: Object (from Daily callObject.participants()) +// */ +// const PARTICIPANTS_CHANGE = 'PARTICIPANTS_CHANGE'; + +// /** +// * CAM_OR_MIC_ERROR action structure: +// * - type: string +// * - message: string +// */ +// const CAM_OR_MIC_ERROR = 'CAM_OR_MIC_ERROR'; + +// /** +// * CAM_OR_MIC_ERROR action structure: +// * - type: string +// * - message: string +// */ +// const FATAL_ERROR = 'FATAL_ERROR'; + +// // --- Reducer and helpers -- + +// function callReducer(callState, action) { +// switch (action.type) { +// case CLICK_ALLOW_TIMEOUT: +// return { +// ...callState, +// clickAllowTimeoutFired: true, +// }; +// case PARTICIPANTS_CHANGE: +// const callItems = getCallItems(action.participants); +// return { +// ...callState, +// callItems, +// }; +// case CAM_OR_MIC_ERROR: +// return { ...callState, camOrMicError: action.message }; +// case FATAL_ERROR: +// return { ...callState, fatalError: action.message }; +// default: +// throw new Error(); +// } +// } + +// function getLocalCallItem(callItems) { +// return callItems['local']; +// } + +// function getCallItems(participants) { +// let callItems = { ...initialCallState.callItems }; // Ensure we *always* have a local participant +// for (const [id, participant] of Object.entries(participants)) { +// callItems[id] = { +// videoTrackState: participant.tracks.video, +// audioTrackState: participant.tracks.audio, +// }; +// if (shouldIncludeScreenCallItem(participant)) { +// callItems[id + '-screen'] = { +// videoTrackState: participant.tracks.screenVideo, +// audioTrackState: participant.tracks.screenAudio, +// }; +// } +// } +// return callItems; +// } + +// function shouldIncludeScreenCallItem(participant) { +// const trackStatesForInclusion = ['loading', 'playable', 'interrupted']; +// return ( +// trackStatesForInclusion.includes(participant.tracks.screenVideo.state) || +// trackStatesForInclusion.includes(participant.tracks.screenAudio.state) +// ); +// } + +// // --- Derived data --- + +// // True if id corresponds to local participant (*not* their screen share) +// function isLocal(id) { +// return id === 'local'; +// } + +// function isScreenShare(id) { +// return id.endsWith('-screen'); +// } + +// function containsScreenShare(callItems) { +// return Object.keys(callItems).some((id) => isScreenShare(id)); +// } + +// function getMessage(callState) { +// function shouldShowClickAllow() { +// const localCallItem = getLocalCallItem(callState.callItems); +// const hasLoaded = localCallItem && !localCallItem.isLoading; +// return !hasLoaded && callState.clickAllowTimeoutFired; +// } + +// let header = null; +// let detail = null; +// let isError = false; +// if (callState.fatalError) { +// header = `Fatal error: ${callState.fatalError}`; +// isError = true; +// } else if (callState.camOrMicError) { +// header = `Camera or mic access error: ${callState.camOrMicError}`; +// detail = +// 'See https://help.daily.co/en/articles/2528184-unblock-camera-mic-access-on-a-computer to troubleshoot.'; +// isError = true; +// } else if (shouldShowClickAllow()) { +// header = 'Click "Allow" to enable camera and mic access'; +// } else if (Object.keys(callState.callItems).length === 1) { +// header = "Copy and share this page's URL to invite others"; +// detail = window.location.href; +// } +// return header || detail ? { header, detail, isError } : null; +// } + +// export { +// initialCallState, +// CLICK_ALLOW_TIMEOUT, +// PARTICIPANTS_CHANGE, +// CAM_OR_MIC_ERROR, +// FATAL_ERROR, +// callReducer, +// isLocal, +// isScreenShare, +// containsScreenShare, +// shouldIncludeScreenCallItem, +// getMessage, +// }; From 2e3249fc20da7987295a6eca01618ffc1c2206bc Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Tue, 2 Mar 2021 11:59:36 -0800 Subject: [PATCH 06/10] Monitoring for tile changes shows second update on screenshare --- src/components/Call/Call.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index d08cc87..0690b8d 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -30,6 +30,8 @@ export default function Call() { // const [callState, dispatch] = useReducer(callReducer, initialCallState); const [isScreenSharing, setScreenSharing] = useState(false); const [screenShareTrackId, setScreenShareTrackId] = useState(''); + // Set a flag for screenshare started + const [screenShareStarted, setScreenShareStarted] = useState(false); const [screenShareEvent, setScreenShareEvent] = useState({}); const [tiles, setTiles] = useState([]); @@ -87,7 +89,9 @@ export default function Call() { console.log(`The shared screen isLarge ${isLarge}`); const tile = { - id: e?.participant?.session_id, + id: !isSharedScreen + ? e?.participant?.session_id + : `${e?.participant?.session_id}-screen`, videoTrackState: isSharedScreen ? e?.participant?.tracks?.screenVideo : e?.participant?.tracks?.video, @@ -101,6 +105,7 @@ export default function Call() { const index = arr?.findIndex((e) => e?.id === obj?.id); if (index === -1) { arr.push(obj); + console.log(`PUSH PUSH PUSH`); } else { arr[index] = obj; } @@ -130,14 +135,18 @@ export default function Call() { useEffect(() => { console.log(`New screen sharing state is: ${isScreenSharing}`); console.log(`The track that is being shared is: ${screenShareTrackId}`); - - // addOrUpdateTile(screenShareEvent); + console.log(screenShareEvent); + if (isScreenSharing && screenShareStarted && screenShareEvent) { + console.log('Doing a thing just once.'); + addOrUpdateTile(screenShareEvent); + setScreenShareStarted(!screenShareStarted); + } }, [ isScreenSharing, - // tiles, addOrUpdateTile, - // screenShareEvent, + screenShareEvent, screenShareTrackId, + screenShareStarted, ]); /** @@ -166,9 +175,9 @@ export default function Call() { if (!callObject) return; function handleTrackStarted(e) { - let trackType = e.track.kind; - let trackId = e.track.id; - let screenVideoTrackState = e.participant.tracks.screenVideo.track; + let trackType = e?.track?.kind; + let trackId = e?.track?.id; + let screenVideoTrackState = e?.participant?.tracks?.screenVideo?.track; console.log(e); if (typeof screenVideoTrackState === 'undefined') { @@ -182,9 +191,10 @@ export default function Call() { } else { if (trackType === 'video') { console.log(`A screenshare is starting!`); + setScreenShareStarted(!screenShareStarted); setScreenShareTrackId(trackId); - setScreenSharing(!isScreenSharing); setScreenShareEvent(e); + setScreenSharing(!isScreenSharing); } else { console.log(`Passing screenAudio when the video starts.`); } @@ -283,6 +293,12 @@ export default function Call() { [callObject] ); + /**Display tiles when there is a change */ + useEffect(() => { + console.log(`TILE CHANGE`); + console.log(tiles); + }, [tiles]); + const displayLargeTiles = useMemo(() => { const participantTracks = [...tiles]; const largeTiles = participantTracks.filter((t) => t.isLarge === true); From ea9cdc2bd6af100175f2c01c8ddf6d18d4be9d5e Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Tue, 9 Mar 2021 11:28:40 -0800 Subject: [PATCH 07/10] Added check for screenshare to shrink other tracks --- src/components/Call/Call.js | 74 +++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index 0690b8d..c1c12ab 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -77,17 +77,12 @@ export default function Call() { const addOrUpdateTile = useCallback( (e) => { logDailyEvent(e); - + console.log(`✨IN OUR UPDATE FUNCTION✨`); const isSharedScreen = e?.track?.id === screenShareTrackId; const isLarge = isSharedScreen || (!e?.participant?.local && !isScreenSharing); const isLocalPerson = e?.participant?.local; - console.log(`The trackId in addTile is ${e?.track?.id}`); - console.log(`The screenshare track in state: ${screenShareTrackId}`); - console.log(`It is a shared screen: ${isSharedScreen}`); - console.log(`The shared screen isLarge ${isLarge}`); - const tile = { id: !isSharedScreen ? e?.participant?.session_id @@ -108,11 +103,20 @@ export default function Call() { console.log(`PUSH PUSH PUSH`); } else { arr[index] = obj; + console.log(`DUPE DUPE UPDATE`); } return arr; } const updatedTiles = addOrUpdate(tiles.slice(), tile); + + if (isSharedScreen) { + updatedTiles.forEach((t) => { + if (!t.id.includes('-screen')) { + t.isLarge = false; + } + }); + } setTiles(updatedTiles); }, [tiles, screenShareTrackId, isScreenSharing] @@ -133,13 +137,12 @@ export default function Call() { ); useEffect(() => { - console.log(`New screen sharing state is: ${isScreenSharing}`); - console.log(`The track that is being shared is: ${screenShareTrackId}`); - console.log(screenShareEvent); if (isScreenSharing && screenShareStarted && screenShareEvent) { - console.log('Doing a thing just once.'); addOrUpdateTile(screenShareEvent); setScreenShareStarted(!screenShareStarted); + // Change all other tiles to be small + // Filter out the ones that are not the target + // Set all their isLarge to isSmall } }, [ isScreenSharing, @@ -147,6 +150,7 @@ export default function Call() { screenShareEvent, screenShareTrackId, screenShareStarted, + tiles, ]); /** @@ -178,6 +182,7 @@ export default function Call() { let trackType = e?.track?.kind; let trackId = e?.track?.id; let screenVideoTrackState = e?.participant?.tracks?.screenVideo?.track; + console.log(`START`); console.log(e); if (typeof screenVideoTrackState === 'undefined') { @@ -206,11 +211,24 @@ export default function Call() { return function cleanup() { callObject.off('track-started', handleTrackStarted); }; - }, [callObject, isScreenSharing, screenShareTrackId, tiles, addOrUpdateTile]); + }, [ + callObject, + isScreenSharing, + screenShareTrackId, + screenShareStarted, + tiles, + addOrUpdateTile, + ]); - /** - * PLACEHOLDER for track-stopped on screenshare - */ + useEffect(() => { + if (!callObject) return; + + function handleStartedCamera(e) { + console.log(e); + } + + callObject.on('started-camera', handleStartedCamera); + }, [callObject]); /** * When the call object is set, listen for participants leaving a call and remove their tracks @@ -229,6 +247,30 @@ export default function Call() { }; }, [callObject, isScreenSharing, removeTile]); + /** + * If a screenshare stops, remove the track from the list + */ + useEffect(() => { + if (!callObject) return; + + function handleTrackStopped(e) { + console.log(`STOP`); + console.log(e); + if (e.track.id === screenShareTrackId) { + const remainingTiles = tiles.filter( + (t) => t.id !== `${e?.participant?.session_id}-screen` + ); + setTiles(remainingTiles); + } + } + + callObject.on('track-stopped', handleTrackStopped); + + return function cleanup() { + callObject.off('track-stopped', handleTrackStopped); + }; + }, [callObject, screenShareTrackId]); + /** * Start listening for call errors, when the callObject is set. */ @@ -309,7 +351,7 @@ export default function Call() { key={`large-${i}`} videoTrackState={t.videoTrackState} audioTrackState={t.audioTrackState} - isLocalPerson={t.isLocal} + isLocalPerson={t.isLocalPerson} isLarge={t.isLarge} disableCornerMessage={t.disableCornerMessage} onClick={ @@ -335,7 +377,7 @@ export default function Call() { key={`small-${i}`} videoTrackState={t.videoTrackState} audioTrackState={t.audioTrackState} - isLocalPerson={t.isLocal} + isLocalPerson={t.isLocalPerson} isLarge={t.isLarge} disableCornerMessage={t.disableCornerMessage} onClick={t.onClick} From 481a312662e49967661a06eb558c3ca1bd38d04e Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Tue, 9 Mar 2021 18:58:45 -0800 Subject: [PATCH 08/10] Replaced participant-left handler with track-stopped --- src/components/Call/Call.js | 134 ++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 74 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index c1c12ab..b135cd8 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -30,7 +30,6 @@ export default function Call() { // const [callState, dispatch] = useReducer(callReducer, initialCallState); const [isScreenSharing, setScreenSharing] = useState(false); const [screenShareTrackId, setScreenShareTrackId] = useState(''); - // Set a flag for screenshare started const [screenShareStarted, setScreenShareStarted] = useState(false); const [screenShareEvent, setScreenShareEvent] = useState({}); const [tiles, setTiles] = useState([]); @@ -72,12 +71,12 @@ export default function Call() { // }, [callObject]); /** - * Add or update a participant's "tile" details + * Add or update a participant's "tile" data */ const addOrUpdateTile = useCallback( (e) => { logDailyEvent(e); - console.log(`✨IN OUR UPDATE FUNCTION✨`); + console.log(`✨ ADD OR UPDATE ✨ `); const isSharedScreen = e?.track?.id === screenShareTrackId; const isLarge = isSharedScreen || (!e?.participant?.local && !isScreenSharing); @@ -100,10 +99,10 @@ export default function Call() { const index = arr?.findIndex((e) => e?.id === obj?.id); if (index === -1) { arr.push(obj); - console.log(`PUSH PUSH PUSH`); + console.log(`βž• ADDING a tile βž•`); } else { arr[index] = obj; - console.log(`DUPE DUPE UPDATE`); + console.log(`πŸ‘―β€β™€οΈ UPDATING the tile πŸ‘―β€β™€οΈ`); } return arr; } @@ -123,45 +122,39 @@ export default function Call() { ); /** - * Remove a participant's tile details from state + * Remove a participant's tile data */ const removeTile = useCallback( (e) => { + console.log(`βœ‚οΈ REMOVE TILE βœ‚οΈ`); logDailyEvent(e); const remainingTiles = tiles.filter( - (t) => t.id !== e?.participant?.session_id + (t) => t.videoTrackState.track !== e?.track ); setTiles(remainingTiles); }, [tiles] ); - useEffect(() => { - if (isScreenSharing && screenShareStarted && screenShareEvent) { - addOrUpdateTile(screenShareEvent); - setScreenShareStarted(!screenShareStarted); - // Change all other tiles to be small - // Filter out the ones that are not the target - // Set all their isLarge to isSmall - } - }, [ - isScreenSharing, - addOrUpdateTile, - screenShareEvent, - screenShareTrackId, - screenShareStarted, - tiles, - ]); - /** - * When the call object is set, listen and react to participant updates + * When the call object is set, reflect participant-updated change in tiles */ useEffect(() => { if (!callObject) return; function handleParticipantUpdate(e) { logDailyEvent(e); - addOrUpdateTile(e); + console.log(`πŸ’… participant-updated makeover πŸ’…`); + console.log(e); + + // TEST: If the participant-updated is sharing a screen, don't do anything + if ( + e?.participant?.tracks?.screenVideo.track?.id === screenShareTrackId + ) { + console.log(`πŸ’• it's the participant screensharing, do nothing`); + } else { + addOrUpdateTile(e); + } } callObject.on('participant-updated', handleParticipantUpdate); @@ -182,7 +175,7 @@ export default function Call() { let trackType = e?.track?.kind; let trackId = e?.track?.id; let screenVideoTrackState = e?.participant?.tracks?.screenVideo?.track; - console.log(`START`); + console.log(`🟒 TRACK STARTING 🟒`); console.log(e); if (typeof screenVideoTrackState === 'undefined') { @@ -190,19 +183,15 @@ export default function Call() { addOrUpdateTile(e); } else if (trackType === 'audio') { console.log( - `We'll pass audio when we pass video, because one tile holds both tracks.` + `We listen for audio changes on participant-updated, so nothing to do here.` ); } } else { - if (trackType === 'video') { - console.log(`A screenshare is starting!`); - setScreenShareStarted(!screenShareStarted); - setScreenShareTrackId(trackId); - setScreenShareEvent(e); - setScreenSharing(!isScreenSharing); - } else { - console.log(`Passing screenAudio when the video starts.`); - } + console.log(`🎬 Screenshare starting 🎬`); + setScreenShareStarted(!screenShareStarted); + setScreenShareTrackId(trackId); + setScreenShareEvent(e); + setScreenSharing(!isScreenSharing); } } @@ -220,47 +209,24 @@ export default function Call() { addOrUpdateTile, ]); - useEffect(() => { - if (!callObject) return; - - function handleStartedCamera(e) { - console.log(e); - } - - callObject.on('started-camera', handleStartedCamera); - }, [callObject]); - - /** - * When the call object is set, listen for participants leaving a call and remove their tracks - */ - useEffect(() => { - if (!callObject) return; - - function handleParticipantLeft(e) { - removeTile(e); - } - - callObject.on('participant-left', handleParticipantLeft); - - return function cleanup() { - callObject.off('participant-left', handleParticipantLeft); - }; - }, [callObject, isScreenSharing, removeTile]); - /** - * If a screenshare stops, remove the track from the list + * Listen for track stops, and remove a track if it has ended (participant left) */ useEffect(() => { if (!callObject) return; function handleTrackStopped(e) { - console.log(`STOP`); + console.log(`πŸ›‘ TRACK STOPPED πŸ›‘`); console.log(e); - if (e.track.id === screenShareTrackId) { - const remainingTiles = tiles.filter( - (t) => t.id !== `${e?.participant?.session_id}-screen` - ); - setTiles(remainingTiles); + + if (e?.track?.readyState === 'ended') { + removeTile(e); + } else if (e?.track?.id === screenShareTrackId) { + removeTile(e); + setScreenShareTrackId(''); + setScreenShareEvent({}); + setScreenSharing(!isScreenSharing); + // TODO: Set tiles back to normal size } } @@ -269,7 +235,7 @@ export default function Call() { return function cleanup() { callObject.off('track-stopped', handleTrackStopped); }; - }, [callObject, screenShareTrackId]); + }, [callObject, screenShareTrackId, tiles, removeTile]); /** * Start listening for call errors, when the callObject is set. @@ -335,7 +301,9 @@ export default function Call() { [callObject] ); - /**Display tiles when there is a change */ + /** + * Whenever the list of tiles changes, display the new list + */ useEffect(() => { console.log(`TILE CHANGE`); console.log(tiles); @@ -343,7 +311,7 @@ export default function Call() { const displayLargeTiles = useMemo(() => { const participantTracks = [...tiles]; - const largeTiles = participantTracks.filter((t) => t.isLarge === true); + const largeTiles = participantTracks.filter((t) => t.isLarge); return (
{largeTiles?.map((t, i) => ( @@ -387,6 +355,24 @@ export default function Call() { ); }, [tiles]); + /** + * If somebody is screensharing, a screenshare started, and there is a screenShareEvent, show the shared screen + */ + useEffect(() => { + if (!callObject) return; + + if (isScreenSharing && screenShareStarted && screenShareEvent) { + addOrUpdateTile(screenShareEvent); + setScreenShareStarted(!screenShareStarted); + } + }, [ + isScreenSharing, + addOrUpdateTile, + screenShareEvent, + screenShareStarted, + tiles, + ]); + /** * Display a message */ From 548281227df0e3595319cadbbbdbc746a8b21b9e Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Thu, 11 Mar 2021 19:47:28 -0800 Subject: [PATCH 09/10] Refactoring to map over participants and first screenshare started attempted --- src/components/Call/Call.js | 510 +++++++++++++----------------------- 1 file changed, 186 insertions(+), 324 deletions(-) diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index b135cd8..2258b7c 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -28,267 +28,226 @@ import { logDailyEvent } from '../../logUtils'; export default function Call() { const callObject = useContext(CallObjectContext); // const [callState, dispatch] = useReducer(callReducer, initialCallState); - const [isScreenSharing, setScreenSharing] = useState(false); - const [screenShareTrackId, setScreenShareTrackId] = useState(''); - const [screenShareStarted, setScreenShareStarted] = useState(false); - const [screenShareEvent, setScreenShareEvent] = useState({}); - const [tiles, setTiles] = useState([]); - - /** - * Start listening for participant changes, when the callObject is set. - */ - // useEffect(() => { - // if (!callObject) return; - - // const es = [ - // 'participant-joined', - // 'participant-updated', - // 'participant-left', - // ]; - - // function handleNewParticipantsState(e) { - // e && logDailyEvent(e); - // dispatch({ - // type: PARTICIPANTS_CHANGE, - // participants: callObject.participants(), - // }); - // } - - // // Use initial state - // handleNewParticipantsState(); - - // // Listen for changes in state - // for (const e of es) { - // callObject.on(e, handleNewParticipantsState); - // } - - // // Stop listening for changes in state - // return function cleanup() { - // for (const e of es) { - // callObject.off(e, handleNewParticipantsState); - // } - // }; - // }, [callObject]); - - /** - * Add or update a participant's "tile" data - */ - const addOrUpdateTile = useCallback( + // const [isScreenSharing, setScreenSharing] = useState(false); + // const [screenShareTrackId, setScreenShareTrackId] = useState(''); + // const [screenShareStarted, setScreenShareStarted] = useState(false); + // const [screenShareEvent, setScreenShareEvent] = useState({}); + // const [tiles, setTiles] = useState([]); + const [participantUpdated, setParticipantUpdated] = useState(null); + const [participants, setParticipants] = useState([]); + + const handleTrackStarted = useCallback( (e) => { - logDailyEvent(e); - console.log(`✨ ADD OR UPDATE ✨ `); - const isSharedScreen = e?.track?.id === screenShareTrackId; - const isLarge = - isSharedScreen || (!e?.participant?.local && !isScreenSharing); - const isLocalPerson = e?.participant?.local; - - const tile = { - id: !isSharedScreen - ? e?.participant?.session_id - : `${e?.participant?.session_id}-screen`, - videoTrackState: isSharedScreen - ? e?.participant?.tracks?.screenVideo - : e?.participant?.tracks?.video, - audioTrackState: e?.participant?.tracks?.audio, - isLocalPerson, - isLarge, - disableCornerMessage: isSharedScreen, - }; - - function addOrUpdate(arr, obj) { - const index = arr?.findIndex((e) => e?.id === obj?.id); - if (index === -1) { - arr.push(obj); - console.log(`βž• ADDING a tile βž•`); - } else { - arr[index] = obj; - console.log(`πŸ‘―β€β™€οΈ UPDATING the tile πŸ‘―β€β™€οΈ`); - } - return arr; - } - - const updatedTiles = addOrUpdate(tiles.slice(), tile); - - if (isSharedScreen) { - updatedTiles.forEach((t) => { - if (!t.id.includes('-screen')) { - t.isLarge = false; - } - }); - } - setTiles(updatedTiles); - }, - [tiles, screenShareTrackId, isScreenSharing] - ); - - /** - * Remove a participant's tile data - */ - const removeTile = useCallback( - (e) => { - console.log(`βœ‚οΈ REMOVE TILE βœ‚οΈ`); - logDailyEvent(e); - const remainingTiles = tiles.filter( - (t) => t.videoTrackState.track !== e?.track + console.log(`TRACK STARTED`); + setParticipantUpdated( + `track-started-${e?.participant?.user_id}-${Date.now()}` ); - setTiles(remainingTiles); }, - [tiles] + [setParticipantUpdated] ); - /** - * When the call object is set, reflect participant-updated change in tiles - */ - useEffect(() => { - if (!callObject) return; + const handleTrackStopped = (e) => { + setParticipantUpdated( + `track-stopped-${e?.participant?.user_id}-${Date.now()}` + ); + }; + + const handleParticipantUpdate = (e) => { + console.log(`IN HANDLE UPDATE`); + console.log(callObject?.participants()); + setParticipantUpdated( + `participant-updated-${e?.participant?.user_id}-${Date.now()}` + ); + }; - function handleParticipantUpdate(e) { - logDailyEvent(e); - console.log(`πŸ’… participant-updated makeover πŸ’…`); - console.log(e); + const getMessage = (e) => { + let header = null; + let detail = null; + let isError = false; - // TEST: If the participant-updated is sharing a screen, don't do anything - if ( - e?.participant?.tracks?.screenVideo.track?.id === screenShareTrackId - ) { - console.log(`πŸ’• it's the participant screensharing, do nothing`); - } else { - addOrUpdateTile(e); + if (!e) { + if (participants.length <= 1) { + header = "Copy and share this page's URL to invite others"; + detail = window.location.href; } + } else if (e.action === 'error') { + header = `Fatal error ${(e && e.errorMsg) || 'Unknown'}`; + } else if (e.action === 'camera-error') { + header = `Camera or mic access error: ${ + (e && e.errorMsg && e.errorMsg.errorMsg) || 'Unknown' + }`; + detail = + 'See https://help.daily.co/en/articles/2528184-unblock-camera-mic-access-on-a-computer to troubleshoot.'; + isError = true; } + return header || detail ? { header, detail, isError } : null; + }; - callObject.on('participant-updated', handleParticipantUpdate); - - return function cleanup() { - callObject.off('participant-updated', handleParticipantUpdate); - }; - }, [callObject, addOrUpdateTile]); + const handleErrorEvent = (e) => { + logDailyEvent(e); + getMessage(e); + }; /** - * When the call obect is set, listen for tracks starting and get "tile" details from the event object - * NOTE: We'll pass audio and video at once in this app, via event.participant.tracks, because our "tile" component renders both. However, it's possible, and sometimes preferred, to pass audio separately. + * When the call object is set, listen and respond to events */ useEffect(() => { if (!callObject) return; - - function handleTrackStarted(e) { - let trackType = e?.track?.kind; - let trackId = e?.track?.id; - let screenVideoTrackState = e?.participant?.tracks?.screenVideo?.track; - console.log(`🟒 TRACK STARTING 🟒`); - console.log(e); - - if (typeof screenVideoTrackState === 'undefined') { - if (trackType === 'video') { - addOrUpdateTile(e); - } else if (trackType === 'audio') { - console.log( - `We listen for audio changes on participant-updated, so nothing to do here.` - ); - } - } else { - console.log(`🎬 Screenshare starting 🎬`); - setScreenShareStarted(!screenShareStarted); - setScreenShareTrackId(trackId); - setScreenShareEvent(e); - setScreenSharing(!isScreenSharing); - } - } - callObject.on('track-started', handleTrackStarted); + callObject.on('track-stopped', handleTrackStopped); + callObject.on('participant-updated', handleParticipantUpdate); + callObject.on('error', handleErrorEvent); + callObject.on('camera-error', handleErrorEvent); - return function cleanup() { + return () => { callObject.off('track-started', handleTrackStarted); + callObject.off('track-stopped', handleTrackStopped); + callObject.off('participant-updated', handleParticipantUpdate); + callObject.off('error', handleErrorEvent); + callObject.off('camera-error', handleErrorEvent); }; }, [ callObject, - isScreenSharing, - screenShareTrackId, - screenShareStarted, - tiles, - addOrUpdateTile, + participants, + handleTrackStarted, + handleParticipantUpdate, + handleTrackStopped, + handleErrorEvent, ]); /** - * Listen for track stops, and remove a track if it has ended (participant left) + * Update participants for any event that happens to keep local participant list up to date. + * We grab the whole participant list to make sure everyone's status is most up to date. */ useEffect(() => { - if (!callObject) return; - - function handleTrackStopped(e) { - console.log(`πŸ›‘ TRACK STOPPED πŸ›‘`); - console.log(e); - - if (e?.track?.readyState === 'ended') { - removeTile(e); - } else if (e?.track?.id === screenShareTrackId) { - removeTile(e); - setScreenShareTrackId(''); - setScreenShareEvent({}); - setScreenSharing(!isScreenSharing); - // TODO: Set tiles back to normal size - } + if (participantUpdated) { + console.log('[🎨 UPDATING PARTICIPANT LIST]'); + console.log(callObject?.participants()); + const list = Object.values(callObject?.participants()); + setParticipants(list); } + }, [participantUpdated, callObject]); - callObject.on('track-stopped', handleTrackStopped); - - return function cleanup() { - callObject.off('track-stopped', handleTrackStopped); - }; - }, [callObject, screenShareTrackId, tiles, removeTile]); - - /** - * Start listening for call errors, when the callObject is set. - */ useEffect(() => { - if (!callObject) return; - - function handleCameraErrorEvent(e) { - logDailyEvent(e); - getMessage(e); - } - - // We're making an assumption here: there is no camera error when callObject - // is first assigned. - callObject.on('camera-error', handleCameraErrorEvent); - - return function cleanup() { - callObject.off('camera-error', handleCameraErrorEvent); - }; - }, [callObject]); + console.log(`✨ Your participants just changed`); + console.log(participants); + console.log(callObject?.participants()); + }, [participants, callObject]); - /** - * Start listening for fatal errors, when the callObject is set. - */ - useEffect(() => { + const isScreenShare = useMemo(() => { if (!callObject) return; + console.log( + `SCREENSHARE: ${participants?.some((p) => p?.tracks?.screenVideo?.track)}` + ); + return participants?.some((p) => p?.tracks?.screenVideo?.track); + }, [participants, callObject]); - function handleErrorEvent(e) { - logDailyEvent(e); - getMessage(e); + const displayLargeTiles = useMemo(() => { + console.log('DISPLAY LARGE'); + const isLarge = true; + // If someone in the participants list has a screenshare + if (isScreenShare) { + // Find the person who is screensharing + const screenShare = participants?.find( + (p) => p?.tracks?.screenVideo?.track + ); + return ( +
+ { + { + sendHello(screenShare.id); + } + } + /> + } +
+ ); + } else { + const tiles = participants?.filter((p) => !p.local); + return ( +
+ {tiles?.map((t, i) => ( + { + sendHello(t.id); + } + } + /> + ))} +
+ ); } + }, [participants, isScreenShare]); - // We're making an assumption here: there is no error when callObject is - // first assigned. - callObject.on('error', handleErrorEvent); - - return function cleanup() { - callObject.off('error', handleErrorEvent); - }; - }, [callObject]); - - /** - * Start a timer to show the "click allow" message, when the component mounts. - */ - // useEffect(() => { - // const t = setTimeout(() => { - // toggleShouldShowClickAllow(); - // }, 2500); - - // return function cleanup() { - // clearTimeout(t); - // }; - // }, [shouldShowClickAllow, toggleShouldShowClickAllow]); + const displaySmallTiles = useMemo(() => { + const isLarge = false; + // If someone is screensharing + if (isScreenShare) { + return ( +
+ {participants?.map((p, i) => ( + { + sendHello(p.id); + } + } + /> + ))} +
+ ); + } else { + const tiles = participants?.filter((p) => p.local); + return ( +
+ {tiles?.map((t, i) => ( + { + sendHello(t.id); + } + } + /> + ))} +
+ ); + } + }, [participants, isScreenShare]); /** * Send an app message to the remote participant whose tile was clicked on. @@ -301,103 +260,6 @@ export default function Call() { [callObject] ); - /** - * Whenever the list of tiles changes, display the new list - */ - useEffect(() => { - console.log(`TILE CHANGE`); - console.log(tiles); - }, [tiles]); - - const displayLargeTiles = useMemo(() => { - const participantTracks = [...tiles]; - const largeTiles = participantTracks.filter((t) => t.isLarge); - return ( -
- {largeTiles?.map((t, i) => ( - { - sendHello(t.id); - } - } - /> - ))} -
- ); - }, [tiles, sendHello]); - - const displaySmallTiles = useMemo(() => { - const participantTracks = [...tiles]; - const smallTiles = participantTracks.filter((t) => t.isLarge === false); - return ( -
- {smallTiles?.map((t, i) => ( - - ))} -
- ); - }, [tiles]); - - /** - * If somebody is screensharing, a screenshare started, and there is a screenShareEvent, show the shared screen - */ - useEffect(() => { - if (!callObject) return; - - if (isScreenSharing && screenShareStarted && screenShareEvent) { - addOrUpdateTile(screenShareEvent); - setScreenShareStarted(!screenShareStarted); - } - }, [ - isScreenSharing, - addOrUpdateTile, - screenShareEvent, - screenShareStarted, - tiles, - ]); - - /** - * Display a message - */ - function getMessage(e) { - let header = null; - let detail = null; - let isError = false; - - if (!e) { - if (tiles.length <= 1) { - header = "Copy and share this page's URL to invite others"; - detail = window.location.href; - } - } else if (e.action === 'error') { - header = `Fatal error ${(e && e.errorMsg) || 'Unknown'}`; - } else if (e.action === 'camera-error') { - header = `Camera or mic access error: ${ - (e && e.errorMsg && e.errorMsg.errorMsg) || 'Unknown' - }`; - detail = - 'See https://help.daily.co/en/articles/2528184-unblock-camera-mic-access-on-a-computer to troubleshoot.'; - isError = true; - } - return header || detail ? { header, detail, isError } : null; - } const message = getMessage(); return (
From 02e54fef364040175b0ec6222ba28552b69aa948 Mon Sep 17 00:00:00 2001 From: Kimberlee Johnson Date: Fri, 12 Mar 2021 15:34:35 -0800 Subject: [PATCH 10/10] Removed isLocalPerson prop --- src/components/Call/Call.js | 76 ++++----------- src/components/Call/callState.js | 159 ------------------------------- 2 files changed, 17 insertions(+), 218 deletions(-) delete mode 100644 src/components/Call/callState.js diff --git a/src/components/Call/Call.js b/src/components/Call/Call.js index 2258b7c..a8c01b1 100644 --- a/src/components/Call/Call.js +++ b/src/components/Call/Call.js @@ -1,7 +1,6 @@ import React, { useEffect, useContext, - // useReducer, useState, useCallback, useMemo, @@ -10,55 +9,38 @@ import './Call.css'; import Tile from '../Tile/Tile'; import CallObjectContext from '../../CallObjectContext'; import CallMessage from '../CallMessage/CallMessage'; -// import { -// initialCallState, -// CLICK_ALLOW_TIMEOUT, -// PARTICIPANTS_CHANGE, -// CAM_OR_MIC_ERROR, -// FATAL_ERROR, -// callReducer, -// isLocal, -// isScreenShare, -// containsScreenShare, -// shouldIncludeScreenCallItem, -// getMessage, -// } from './callState'; import { logDailyEvent } from '../../logUtils'; export default function Call() { const callObject = useContext(CallObjectContext); - // const [callState, dispatch] = useReducer(callReducer, initialCallState); - // const [isScreenSharing, setScreenSharing] = useState(false); - // const [screenShareTrackId, setScreenShareTrackId] = useState(''); - // const [screenShareStarted, setScreenShareStarted] = useState(false); - // const [screenShareEvent, setScreenShareEvent] = useState({}); - // const [tiles, setTiles] = useState([]); const [participantUpdated, setParticipantUpdated] = useState(null); const [participants, setParticipants] = useState([]); - const handleTrackStarted = useCallback( - (e) => { - console.log(`TRACK STARTED`); - setParticipantUpdated( - `track-started-${e?.participant?.user_id}-${Date.now()}` - ); - }, - [setParticipantUpdated] - ); + const handleTrackStarted = useCallback((e) => { + logDailyEvent(e); + setParticipantUpdated( + `track-started-${e?.participant?.user_id}-${Date.now()}` + ); + }, []); - const handleTrackStopped = (e) => { + const handleTrackStopped = useCallback((e) => { + logDailyEvent(e); setParticipantUpdated( `track-stopped-${e?.participant?.user_id}-${Date.now()}` ); - }; + }, []); - const handleParticipantUpdate = (e) => { - console.log(`IN HANDLE UPDATE`); - console.log(callObject?.participants()); + const handleParticipantUpdate = useCallback((e) => { + logDailyEvent(e); setParticipantUpdated( `participant-updated-${e?.participant?.user_id}-${Date.now()}` ); - }; + }, []); + + const handleErrorEvent = useCallback((e) => { + logDailyEvent(e); + getMessage(e); + }, []); const getMessage = (e) => { let header = null; @@ -83,11 +65,6 @@ export default function Call() { return header || detail ? { header, detail, isError } : null; }; - const handleErrorEvent = (e) => { - logDailyEvent(e); - getMessage(e); - }; - /** * When the call object is set, listen and respond to events */ @@ -121,33 +98,18 @@ export default function Call() { */ useEffect(() => { if (participantUpdated) { - console.log('[🎨 UPDATING PARTICIPANT LIST]'); - console.log(callObject?.participants()); const list = Object.values(callObject?.participants()); setParticipants(list); } }, [participantUpdated, callObject]); - useEffect(() => { - console.log(`✨ Your participants just changed`); - console.log(participants); - console.log(callObject?.participants()); - }, [participants, callObject]); - const isScreenShare = useMemo(() => { - if (!callObject) return; - console.log( - `SCREENSHARE: ${participants?.some((p) => p?.tracks?.screenVideo?.track)}` - ); return participants?.some((p) => p?.tracks?.screenVideo?.track); }, [participants, callObject]); const displayLargeTiles = useMemo(() => { - console.log('DISPLAY LARGE'); const isLarge = true; - // If someone in the participants list has a screenshare if (isScreenShare) { - // Find the person who is screensharing const screenShare = participants?.find( (p) => p?.tracks?.screenVideo?.track ); @@ -158,7 +120,6 @@ export default function Call() { key={`screenshare`} videoTrackState={screenShare?.tracks?.screenVideo} audioTrackState={screenShare?.tracks?.audio} - isLocalPerson={screenShare?.local} isLarge={isLarge} disableCornerMessage={isScreenShare} onClick={ @@ -181,7 +142,6 @@ export default function Call() { key={`large-${i}`} videoTrackState={t?.tracks?.video} audioTrackState={t?.tracks?.audio} - isLocalPerson={t?.local} isLarge={isLarge} disableCornerMessage={isScreenShare} onClick={ @@ -200,7 +160,6 @@ export default function Call() { const displaySmallTiles = useMemo(() => { const isLarge = false; - // If someone is screensharing if (isScreenShare) { return (
@@ -232,7 +191,6 @@ export default function Call() { key={`small-${i}`} videoTrackState={t.tracks.video} audioTrackState={t.tracks.audio} - isLocalPerson={t.local} isLarge={isLarge} disableCornerMessage={false} onClick={ diff --git a/src/components/Call/callState.js b/src/components/Call/callState.js deleted file mode 100644 index 4999882..0000000 --- a/src/components/Call/callState.js +++ /dev/null @@ -1,159 +0,0 @@ -// /** -// * Call state is comprised of: -// * - "Call items" (inputs to the call, i.e. participants or shared screens) -// * - UI state that depends on call items (for now, just whether to show "click allow" message) -// * -// * Call items are keyed by id: -// * - "local" for the current participant -// * - A session id for each remote participant -// * - "-screen" for each shared screen -// */ -// const initialCallState = { -// callItems: { -// local: { -// videoTrackState: null, -// audioTrackState: null, -// }, -// }, -// clickAllowTimeoutFired: false, -// camOrMicError: null, -// fatalError: null, -// }; - -// // --- Actions --- - -// /** -// * CLICK_ALLOW_TIMEOUT action structure: -// * - type: string -// */ -// const CLICK_ALLOW_TIMEOUT = 'CLICK_ALLOW_TIMEOUT'; - -// /** -// * PARTICIPANTS_CHANGE action structure: -// * - type: string -// * - participants: Object (from Daily callObject.participants()) -// */ -// const PARTICIPANTS_CHANGE = 'PARTICIPANTS_CHANGE'; - -// /** -// * CAM_OR_MIC_ERROR action structure: -// * - type: string -// * - message: string -// */ -// const CAM_OR_MIC_ERROR = 'CAM_OR_MIC_ERROR'; - -// /** -// * CAM_OR_MIC_ERROR action structure: -// * - type: string -// * - message: string -// */ -// const FATAL_ERROR = 'FATAL_ERROR'; - -// // --- Reducer and helpers -- - -// function callReducer(callState, action) { -// switch (action.type) { -// case CLICK_ALLOW_TIMEOUT: -// return { -// ...callState, -// clickAllowTimeoutFired: true, -// }; -// case PARTICIPANTS_CHANGE: -// const callItems = getCallItems(action.participants); -// return { -// ...callState, -// callItems, -// }; -// case CAM_OR_MIC_ERROR: -// return { ...callState, camOrMicError: action.message }; -// case FATAL_ERROR: -// return { ...callState, fatalError: action.message }; -// default: -// throw new Error(); -// } -// } - -// function getLocalCallItem(callItems) { -// return callItems['local']; -// } - -// function getCallItems(participants) { -// let callItems = { ...initialCallState.callItems }; // Ensure we *always* have a local participant -// for (const [id, participant] of Object.entries(participants)) { -// callItems[id] = { -// videoTrackState: participant.tracks.video, -// audioTrackState: participant.tracks.audio, -// }; -// if (shouldIncludeScreenCallItem(participant)) { -// callItems[id + '-screen'] = { -// videoTrackState: participant.tracks.screenVideo, -// audioTrackState: participant.tracks.screenAudio, -// }; -// } -// } -// return callItems; -// } - -// function shouldIncludeScreenCallItem(participant) { -// const trackStatesForInclusion = ['loading', 'playable', 'interrupted']; -// return ( -// trackStatesForInclusion.includes(participant.tracks.screenVideo.state) || -// trackStatesForInclusion.includes(participant.tracks.screenAudio.state) -// ); -// } - -// // --- Derived data --- - -// // True if id corresponds to local participant (*not* their screen share) -// function isLocal(id) { -// return id === 'local'; -// } - -// function isScreenShare(id) { -// return id.endsWith('-screen'); -// } - -// function containsScreenShare(callItems) { -// return Object.keys(callItems).some((id) => isScreenShare(id)); -// } - -// function getMessage(callState) { -// function shouldShowClickAllow() { -// const localCallItem = getLocalCallItem(callState.callItems); -// const hasLoaded = localCallItem && !localCallItem.isLoading; -// return !hasLoaded && callState.clickAllowTimeoutFired; -// } - -// let header = null; -// let detail = null; -// let isError = false; -// if (callState.fatalError) { -// header = `Fatal error: ${callState.fatalError}`; -// isError = true; -// } else if (callState.camOrMicError) { -// header = `Camera or mic access error: ${callState.camOrMicError}`; -// detail = -// 'See https://help.daily.co/en/articles/2528184-unblock-camera-mic-access-on-a-computer to troubleshoot.'; -// isError = true; -// } else if (shouldShowClickAllow()) { -// header = 'Click "Allow" to enable camera and mic access'; -// } else if (Object.keys(callState.callItems).length === 1) { -// header = "Copy and share this page's URL to invite others"; -// detail = window.location.href; -// } -// return header || detail ? { header, detail, isError } : null; -// } - -// export { -// initialCallState, -// CLICK_ALLOW_TIMEOUT, -// PARTICIPANTS_CHANGE, -// CAM_OR_MIC_ERROR, -// FATAL_ERROR, -// callReducer, -// isLocal, -// isScreenShare, -// containsScreenShare, -// shouldIncludeScreenCallItem, -// getMessage, -// };