From 015457a91368727755f15c043b412cfc5b629f3e Mon Sep 17 00:00:00 2001 From: harshithpabbati Date: Thu, 27 Jan 2022 14:36:28 +0530 Subject: [PATCH] import the livestreaming and recording contexts and hooks --- custom/fitness-demo/components/App/App.js | 4 +- .../fitness-demo/components/Call/ChatAside.js | 4 +- .../components/Modals/LiveStreamingModal.js | 157 -------- .../components/Modals/RecordingModal.js | 145 -------- custom/fitness-demo/components/Tray/Record.js | 16 +- custom/fitness-demo/components/Tray/Stream.js | 4 +- .../contexts/LiveStreamingProvider.js | 71 ---- .../contexts/RecordingProvider.js | 337 ------------------ custom/fitness-demo/hooks/useMessageSound.js | 19 - custom/fitness-demo/next.config.js | 3 + custom/fitness-demo/package.json | 4 + custom/fitness-demo/pages/_app.js | 4 +- .../components/LiveStreamingModal.js | 4 +- custom/text-chat/components/ChatAside.js | 2 +- 14 files changed, 25 insertions(+), 749 deletions(-) delete mode 100644 custom/fitness-demo/components/Modals/LiveStreamingModal.js delete mode 100644 custom/fitness-demo/components/Modals/RecordingModal.js delete mode 100644 custom/fitness-demo/contexts/LiveStreamingProvider.js delete mode 100644 custom/fitness-demo/contexts/RecordingProvider.js delete mode 100644 custom/fitness-demo/hooks/useMessageSound.js diff --git a/custom/fitness-demo/components/App/App.js b/custom/fitness-demo/components/App/App.js index ccf5e7f..a86b453 100644 --- a/custom/fitness-demo/components/App/App.js +++ b/custom/fitness-demo/components/App/App.js @@ -1,4 +1,6 @@ import React, { useMemo } from 'react'; +import { LiveStreamingProvider } from '@custom/live-streaming/contexts/LiveStreamingProvider'; +import { RecordingProvider } from '@custom/recording/contexts/RecordingProvider'; import ExpiryTimer from '@custom/shared/components/ExpiryTimer'; import { useCallState } from '@custom/shared/contexts/CallProvider'; import { useCallUI } from '@custom/shared/hooks/useCallUI'; @@ -6,8 +8,6 @@ import PropTypes from 'prop-types'; import { ChatProvider } from '../../contexts/ChatProvider'; import { ClassStateProvider } from '../../contexts/ClassStateProvider'; -import { LiveStreamingProvider } from '../../contexts/LiveStreamingProvider'; -import { RecordingProvider } from '../../contexts/RecordingProvider'; import Room from '../Call/Room'; import { Asides } from './Asides'; import { Modals } from './Modals'; diff --git a/custom/fitness-demo/components/Call/ChatAside.js b/custom/fitness-demo/components/Call/ChatAside.js index f3dc4a8..e4aed31 100644 --- a/custom/fitness-demo/components/Call/ChatAside.js +++ b/custom/fitness-demo/components/Call/ChatAside.js @@ -2,11 +2,10 @@ import React, { useEffect, useRef, useState } from 'react'; import { Aside } from '@custom/shared/components/Aside'; import Button from '@custom/shared/components/Button'; import { TextInput } from '@custom/shared/components/Input'; -import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; import { useUIState } from '@custom/shared/contexts/UIStateProvider'; import { ReactComponent as IconEmoji } from '@custom/shared/icons/emoji-sm.svg'; +import { useMessageSound } from '@custom/text-chat/hooks/useMessageSound'; import { useChat } from '../../contexts/ChatProvider'; -import { useMessageSound } from '../../hooks/useMessageSound'; import AsideHeader from '../App/AsideHeader'; export const CHAT_ASIDE = 'chat'; @@ -15,7 +14,6 @@ export const ChatAside = () => { const { showAside, setShowAside } = useUIState(); const { sendMessage, chatHistory, hasNewMessages, setHasNewMessages } = useChat(); - const { localParticipant } = useParticipants(); const [newMessage, setNewMessage] = useState(''); const playMessageSound = useMessageSound(); const [showEmojis, setShowEmojis] = useState(false); diff --git a/custom/fitness-demo/components/Modals/LiveStreamingModal.js b/custom/fitness-demo/components/Modals/LiveStreamingModal.js deleted file mode 100644 index ea5e34e..0000000 --- a/custom/fitness-demo/components/Modals/LiveStreamingModal.js +++ /dev/null @@ -1,157 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import Button from '@custom/shared/components/Button'; -import { CardBody } from '@custom/shared/components/Card'; -import Field from '@custom/shared/components/Field'; -import { TextInput, SelectInput } from '@custom/shared/components/Input'; -import Modal from '@custom/shared/components/Modal'; -import Well from '@custom/shared/components/Well'; -import { useCallState } from '@custom/shared/contexts/CallProvider'; -import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; -import { useUIState } from '@custom/shared/contexts/UIStateProvider'; -import { useLiveStreaming } from '../../contexts/LiveStreamingProvider'; - -export const LIVE_STREAMING_MODAL = 'live-streaming'; - -const LAYOUTS = [ - { label: 'Grid (default)', value: 'default' }, - { label: 'Single participant', value: 'single-participant' }, - { label: 'Active participant', value: 'active-participant' }, -]; - -export const LiveStreamingModal = () => { - const { callObject } = useCallState(); - const { allParticipants } = useParticipants(); - const { currentModals, closeModal } = useUIState(); - const { isStreaming, streamError } = useLiveStreaming(); - const [pending, setPending] = useState(false); - const [rtmpUrl, setRtmpUrl] = useState(''); - const [layout, setLayout] = useState(0); - const [maxCams, setMaxCams] = useState(9); - const [participant, setParticipant] = useState(0); - - useEffect(() => { - // Reset pending state whenever stream state changes - setPending(false); - }, [isStreaming]); - - function startLiveStream() { - setPending(true); - - const opts = - layout === 'single-participant' - ? { session_id: participant.id } - : { max_cam_streams: maxCams }; - callObject.startLiveStreaming({ rtmpUrl, preset: layout, ...opts }); - } - - function stopLiveStreaming() { - setPending(true); - callObject.stopLiveStreaming(); - } - - return ( - closeModal(LIVE_STREAMING_MODAL)} - actions={[ - , - !isStreaming ? ( - - ) : ( - - ), - ]} - > - live streaming -

Please note: live streaming requires Scale Plan or above

- {streamError && ( - - Unable to start stream. Error message: {streamError} - - )} - - - setLayout(Number(e.target.value))} - value={layout} - > - {LAYOUTS.map((l, i) => ( - - ))} - - - - {layout !== - LAYOUTS.findIndex((l) => l.value === 'single-participant') && ( - - setMaxCams(Number(e.target.value))} - value={maxCams} - > - - - - - - - - - - - - )} - - {layout === - LAYOUTS.findIndex((l) => l.value === 'single-participant') && ( - - setParticipant(e.target.value)} - value={participant} - > - {allParticipants.map((p) => ( - - ))} - - - )} - - - setRtmpUrl(e.target.value)} - /> - - - -
- ); -}; - -export default LiveStreamingModal; \ No newline at end of file diff --git a/custom/fitness-demo/components/Modals/RecordingModal.js b/custom/fitness-demo/components/Modals/RecordingModal.js deleted file mode 100644 index ff52af6..0000000 --- a/custom/fitness-demo/components/Modals/RecordingModal.js +++ /dev/null @@ -1,145 +0,0 @@ -import React, { useEffect } from 'react'; -import Button from '@custom/shared/components/Button'; -import { CardBody } from '@custom/shared/components/Card'; -import Modal from '@custom/shared/components/Modal'; -import Well from '@custom/shared/components/Well'; -import { useCallState } from '@custom/shared/contexts/CallProvider'; -import { useUIState } from '@custom/shared/contexts/UIStateProvider'; -import { - RECORDING_COUNTDOWN_1, - RECORDING_COUNTDOWN_2, - RECORDING_COUNTDOWN_3, - RECORDING_IDLE, - RECORDING_RECORDING, - RECORDING_SAVED, - RECORDING_TYPE_CLOUD, - RECORDING_TYPE_CLOUD_BETA, - RECORDING_TYPE_RTP_TRACKS, - RECORDING_UPLOADING, - useRecording, -} from '../../contexts/RecordingProvider'; - -export const RECORDING_MODAL = 'recording'; - -export const RecordingModal = () => { - const { currentModals, closeModal } = useUIState(); - const { enableRecording } = useCallState(); - const { - recordingStartedDate, - recordingState, - startRecordingWithCountdown, - stopRecording, - } = useRecording(); - - useEffect(() => { - if (recordingState === RECORDING_RECORDING) { - closeModal(RECORDING_MODAL); - } - }, [recordingState, closeModal]); - - const disabled = - enableRecording && - [RECORDING_IDLE, RECORDING_RECORDING].includes(recordingState); - - function renderButtonLabel() { - if (!enableRecording) { - return 'Recording disabled'; - } - - switch (recordingState) { - case RECORDING_COUNTDOWN_3: - return '3...'; - case RECORDING_COUNTDOWN_2: - return '2...'; - case RECORDING_COUNTDOWN_1: - return '1...'; - case RECORDING_RECORDING: - return 'Stop recording'; - case RECORDING_UPLOADING: - case RECORDING_SAVED: - return 'Stopping recording...'; - default: - return 'Start recording'; - } - } - - function handleRecordingClick() { - if (recordingState === RECORDING_IDLE) { - startRecordingWithCountdown(); - } else { - stopRecording(); - } - } - - return ( - closeModal(RECORDING_MODAL)} - actions={[ - , - , - ]} - > - - {!enableRecording ? ( - - Recording is not enabled for this room (or your browser does not - support it.) Please enable recording when creating the room or via - the Daily dashboard. - - ) : ( -

- Recording type enabled: {enableRecording} -

- )} - - {recordingStartedDate && ( -

Recording started: {recordingStartedDate.toString()}

- )} - - {[RECORDING_TYPE_CLOUD, RECORDING_TYPE_CLOUD_BETA].includes( - enableRecording - ) && ( - <> -
- -

- Cloud recordings can be accessed via the Daily dashboard under the - "Recordings" section. -

- - )} - {enableRecording === RECORDING_TYPE_RTP_TRACKS && ( - <> -
- -

- rtp-tracks recordings can be accessed via the Daily API. See the{' '} - - Daily recording guide - {' '} - for details. -

- - )} -
-
- ); -}; - -export default RecordingModal; \ No newline at end of file diff --git a/custom/fitness-demo/components/Tray/Record.js b/custom/fitness-demo/components/Tray/Record.js index 9a3b37a..90d96d5 100644 --- a/custom/fitness-demo/components/Tray/Record.js +++ b/custom/fitness-demo/components/Tray/Record.js @@ -1,19 +1,19 @@ import React, { useEffect } from 'react'; -import { TrayButton } from '@custom/shared/components/Tray'; -import { useCallState } from '@custom/shared/contexts/CallProvider'; -import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; -import { useUIState } from '@custom/shared/contexts/UIStateProvider'; -import { ReactComponent as IconRecord } from '@custom/shared/icons/record-md.svg'; - +import { RECORDING_MODAL } from '@custom/recording/components/RecordingModal'; import { RECORDING_ERROR, RECORDING_RECORDING, RECORDING_SAVED, RECORDING_UPLOADING, useRecording, -} from '../../contexts/RecordingProvider'; -import { RECORDING_MODAL } from '../Modals/RecordingModal'; +} from '@custom/recording/contexts/RecordingProvider'; +import { TrayButton } from '@custom/shared/components/Tray'; +import { useCallState } from '@custom/shared/contexts/CallProvider'; +import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; +import { useUIState } from '@custom/shared/contexts/UIStateProvider'; +import { ReactComponent as IconRecord } from '@custom/shared/icons/record-md.svg'; + export const Tray = () => { const { enableRecording } = useCallState(); diff --git a/custom/fitness-demo/components/Tray/Stream.js b/custom/fitness-demo/components/Tray/Stream.js index a8e9893..a03885e 100644 --- a/custom/fitness-demo/components/Tray/Stream.js +++ b/custom/fitness-demo/components/Tray/Stream.js @@ -1,12 +1,12 @@ import React from 'react'; +import { LIVE_STREAMING_MODAL } from '@custom/live-streaming/components/LiveStreamingModal'; +import { useLiveStreaming } from '@custom/live-streaming/contexts/LiveStreamingProvider'; import { TrayButton } from '@custom/shared/components/Tray'; import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; import { useUIState } from '@custom/shared/contexts/UIStateProvider'; import { ReactComponent as IconStream } from '@custom/shared/icons/streaming-md.svg'; -import { useLiveStreaming } from '../../contexts/LiveStreamingProvider'; -import { LIVE_STREAMING_MODAL } from '../Modals/LiveStreamingModal'; export const Stream = () => { const { openModal } = useUIState(); diff --git a/custom/fitness-demo/contexts/LiveStreamingProvider.js b/custom/fitness-demo/contexts/LiveStreamingProvider.js deleted file mode 100644 index d6bfb4d..0000000 --- a/custom/fitness-demo/contexts/LiveStreamingProvider.js +++ /dev/null @@ -1,71 +0,0 @@ -import React, { - useState, - createContext, - useContext, - useEffect, - useCallback, -} from 'react'; -import { useCallState } from '@custom/shared/contexts/CallProvider'; -import { useUIState } from '@custom/shared/contexts/UIStateProvider'; -import PropTypes from 'prop-types'; - -export const LiveStreamingContext = createContext(); - -export const LiveStreamingProvider = ({ children }) => { - const [isStreaming, setIsStreaming] = useState(false); - const [streamError, setStreamError] = useState(); - const { setCustomCapsule } = useUIState(); - const { callObject } = useCallState(); - - const handleStreamStarted = useCallback(() => { - console.log('📺 Live stream started'); - setIsStreaming(true); - setStreamError(null); - setCustomCapsule({ variant: 'recording', label: 'Live streaming' }); - }, [setCustomCapsule]); - - const handleStreamStopped = useCallback(() => { - console.log('📺 Live stream stopped'); - setIsStreaming(false); - setCustomCapsule(null); - }, [setCustomCapsule]); - - const handleStreamError = useCallback( - (e) => { - setIsStreaming(false); - setCustomCapsule(null); - setStreamError(e.errorMsg); - }, - [setCustomCapsule] - ); - - useEffect(() => { - if (!callObject) { - return false; - } - - console.log('📺 Live streaming provider listening for stream events'); - - callObject.on('live-streaming-started', handleStreamStarted); - callObject.on('live-streaming-stopped', handleStreamStopped); - callObject.on('live-streaming-error', handleStreamError); - - return () => { - callObject.off('live-streaming-started', handleStreamStarted); - callObject.off('live-streaming-stopped', handleStreamStopped); - callObject.on('live-streaming-error', handleStreamError); - }; - }, [callObject, handleStreamStarted, handleStreamStopped, handleStreamError]); - - return ( - - {children} - - ); -}; - -LiveStreamingProvider.propTypes = { - children: PropTypes.node, -}; - -export const useLiveStreaming = () => useContext(LiveStreamingContext); \ No newline at end of file diff --git a/custom/fitness-demo/contexts/RecordingProvider.js b/custom/fitness-demo/contexts/RecordingProvider.js deleted file mode 100644 index dd1b7e1..0000000 --- a/custom/fitness-demo/contexts/RecordingProvider.js +++ /dev/null @@ -1,337 +0,0 @@ -import React, { - createContext, - useCallback, - useContext, - useEffect, - useState, -} from 'react'; - -import { useCallState } from '@custom/shared/contexts/CallProvider'; -import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; -import { useUIState } from '@custom/shared/contexts/UIStateProvider'; -import { - CALL_STATE_REDIRECTING, - CALL_STATE_JOINED, -} from '@custom/shared/contexts/useCallMachine'; -import PropTypes from 'prop-types'; -import { useDeepCompareEffect } from 'use-deep-compare'; - -export const RECORDING_ERROR = 'error'; -export const RECORDING_SAVED = 'saved'; -export const RECORDING_RECORDING = 'recording'; -export const RECORDING_UPLOADING = 'uploading'; -export const RECORDING_COUNTDOWN_1 = 'starting1'; -export const RECORDING_COUNTDOWN_2 = 'starting2'; -export const RECORDING_COUNTDOWN_3 = 'starting3'; -export const RECORDING_IDLE = 'idle'; - -export const RECORDING_TYPE_CLOUD = 'cloud'; -export const RECORDING_TYPE_CLOUD_BETA = 'cloud-beta'; -export const RECORDING_TYPE_LOCAL = 'local'; -export const RECORDING_TYPE_OUTPUT_BYTE_STREAM = 'output-byte-stream'; -export const RECORDING_TYPE_RTP_TRACKS = 'rtp-tracks'; - -const RecordingContext = createContext({ - isRecordingLocally: false, - recordingStartedDate: null, - recordingState: RECORDING_IDLE, - startRecording: null, - stopRecording: null, -}); - -export const RecordingProvider = ({ children }) => { - const { - callObject, - enableRecording, - startCloudRecording, - state, - } = useCallState(); - const { participants } = useParticipants(); - const [recordingStartedDate, setRecordingStartedDate] = useState(null); - const [recordingState, setRecordingState] = useState(RECORDING_IDLE); - const [isRecordingLocally, setIsRecordingLocally] = useState(false); - const [hasRecordingStarted, setHasRecordingStarted] = useState(false); - const { setCustomCapsule } = useUIState(); - - const handleOnUnload = useCallback( - () => 'Unsaved recording in progress. Do you really want to leave?', - [] - ); - - useEffect(() => { - if ( - !enableRecording || - !isRecordingLocally || - recordingState !== RECORDING_RECORDING || - state === CALL_STATE_REDIRECTING - ) - return false; - const prev = window.onbeforeunload; - window.onbeforeunload = handleOnUnload; - return () => { - window.onbeforeunload = prev; - }; - }, [ - enableRecording, - handleOnUnload, - recordingState, - isRecordingLocally, - state, - ]); - - useEffect(() => { - if (!callObject || !enableRecording) return false; - - const handleAppMessage = (ev) => { - switch (ev?.data?.event) { - case 'recording-starting': - setRecordingState(RECORDING_COUNTDOWN_3); - break; - default: - break; - } - }; - - // The 'recording-data' event is emitted when an output-byte-stream recording has started - // When the event emits, start writing data to the stream created in handleRecordingStarted() - const handleRecordingData = async (ev) => { - try { - console.log('got data', ev); - await window.writer.write(ev.data); - if (ev.finished) { - console.log('closing!'); - window.writer.close(); - } - } catch (e) { - console.error(e); - } - }; - - callObject.on('app-message', handleAppMessage); - callObject.on('recording-data', handleRecordingData); - - return () => { - callObject.off('app-message', handleAppMessage); - callObject.off('recording-data', handleRecordingData); - }; - }, [callObject, enableRecording]); - - /** - * Automatically start cloud recording, if startCloudRecording is set. - */ - useEffect(() => { - if ( - hasRecordingStarted || - !callObject || - !startCloudRecording || - enableRecording !== 'cloud' || - state !== CALL_STATE_JOINED - ) - return false; - - // Small timeout, in case other participants are already in-call. - const timeout = setTimeout(() => { - const isSomebodyRecording = participants.some((p) => p.isRecording); - if (!isSomebodyRecording) { - callObject.startRecording(); - setIsRecordingLocally(true); - setHasRecordingStarted(true); - } else { - setHasRecordingStarted(true); - } - }, 500); - - return () => { - clearTimeout(timeout); - }; - }, [ - callObject, - enableRecording, - hasRecordingStarted, - participants, - startCloudRecording, - state, - ]); - - /** - * Handle participant updates to sync recording state. - */ - useDeepCompareEffect(() => { - if (isRecordingLocally || recordingState === RECORDING_SAVED) return; - if (participants.some(({ isRecording }) => isRecording)) { - setRecordingState(RECORDING_RECORDING); - } else { - setRecordingState(RECORDING_IDLE); - } - }, [isRecordingLocally, participants, recordingState]); - - /** - * Handle recording started. - */ - const handleRecordingStarted = useCallback( - (event) => { - console.log('RECORDING'); - console.log(event); - - if (recordingState === RECORDING_RECORDING) return; - setRecordingState(RECORDING_RECORDING); - if (event.local) { - // Recording started locally, either through UI or programmatically - setIsRecordingLocally(true); - if (!recordingStartedDate) setRecordingStartedDate(new Date()); - // If an output-byte-stream recording has started, create a new data stream that can be piped to a third-party (in this case a file) - if (event.type === 'output-byte-stream') { - const { readable, writable } = new TransformStream({ - transform: (chunk, ctrl) => { - chunk.arrayBuffer().then((b) => ctrl.enqueue(new Uint8Array(b))); - }, - }); - window.writer = writable.getWriter(); - readable.pipeTo(window.streamSaver.createWriteStream('test-vid.mp4')); - } - } - }, - [recordingState, recordingStartedDate] - ); - - useEffect(() => { - if (!callObject || !enableRecording) return false; - - callObject.on('recording-started', handleRecordingStarted); - return () => callObject.off('recording-started', handleRecordingStarted); - }, [callObject, enableRecording, handleRecordingStarted]); - - /** - * Handle recording stopped. - */ - useEffect(() => { - if (!callObject || !enableRecording) return false; - - const handleRecordingStopped = (event) => { - console.log(event); - if (isRecordingLocally) return; - setRecordingState(RECORDING_IDLE); - setRecordingStartedDate(null); - }; - - callObject.on('recording-stopped', handleRecordingStopped); - return () => callObject.off('recording-stopped', handleRecordingStopped); - }, [callObject, enableRecording, isRecordingLocally]); - - /** - * Handle recording error. - */ - const handleRecordingError = useCallback(() => { - if (isRecordingLocally) setRecordingState(RECORDING_ERROR); - setIsRecordingLocally(false); - }, [isRecordingLocally]); - - useEffect(() => { - if (!callObject || !enableRecording) return false; - - callObject.on('recording-error', handleRecordingError); - return () => callObject.off('recording-error', handleRecordingError); - }, [callObject, enableRecording, handleRecordingError]); - - const startRecording = useCallback(() => { - if (!callObject || !isRecordingLocally) return; - callObject.startRecording(); - }, [callObject, isRecordingLocally]); - - useEffect(() => { - let timeout; - switch (recordingState) { - case RECORDING_COUNTDOWN_3: - timeout = setTimeout(() => { - setRecordingState(RECORDING_COUNTDOWN_2); - }, 1000); - break; - case RECORDING_COUNTDOWN_2: - timeout = setTimeout(() => { - setRecordingState(RECORDING_COUNTDOWN_1); - }, 1000); - break; - case RECORDING_COUNTDOWN_1: - startRecording(); - break; - case RECORDING_ERROR: - case RECORDING_SAVED: - timeout = setTimeout(() => { - setRecordingState(RECORDING_IDLE); - setIsRecordingLocally(false); - }, 5000); - break; - default: - break; - } - return () => { - clearTimeout(timeout); - }; - }, [recordingState, startRecording]); - - // Show a custom capsule when recording in progress - useEffect(() => { - if (recordingState !== RECORDING_RECORDING) { - setCustomCapsule(null); - } else { - setCustomCapsule({ variant: 'recording', label: 'Recording' }); - } - }, [recordingState, setCustomCapsule]); - - const startRecordingWithCountdown = useCallback(() => { - if (!callObject || !enableRecording) return; - setIsRecordingLocally(true); - setRecordingState(RECORDING_COUNTDOWN_3); - callObject?.sendAppMessage({ - event: 'recording-starting', - }); - }, [callObject, enableRecording]); - - const stopRecording = useCallback(() => { - if (!callObject || !enableRecording || !isRecordingLocally) return; - if (recordingState === RECORDING_RECORDING) { - switch (enableRecording) { - case RECORDING_TYPE_LOCAL: - case RECORDING_TYPE_OUTPUT_BYTE_STREAM: - setRecordingState(RECORDING_SAVED); - setIsRecordingLocally(false); - break; - case RECORDING_TYPE_CLOUD: - case RECORDING_TYPE_CLOUD_BETA: - case RECORDING_TYPE_RTP_TRACKS: - setRecordingState(RECORDING_UPLOADING); - setRecordingState(RECORDING_SAVED); - break; - default: - break; - } - } else if (recordingState === RECORDING_IDLE) { - return; - } else { - setIsRecordingLocally(false); - setRecordingState(RECORDING_IDLE); - } - setRecordingStartedDate(null); - callObject.stopRecording(); - }, [callObject, enableRecording, isRecordingLocally, recordingState]); - - return ( - - {children} - - ); -}; - -RecordingProvider.propTypes = { - children: PropTypes.node, -}; - -export const useRecording = () => useContext(RecordingContext); \ No newline at end of file diff --git a/custom/fitness-demo/hooks/useMessageSound.js b/custom/fitness-demo/hooks/useMessageSound.js deleted file mode 100644 index 7449e10..0000000 --- a/custom/fitness-demo/hooks/useMessageSound.js +++ /dev/null @@ -1,19 +0,0 @@ -import { useEffect, useMemo } from 'react'; - -import { useSound } from '@custom/shared/hooks/useSound'; -import { debounce } from 'debounce'; - -/** - * Convenience hook to play `join.mp3` when participants join the call - */ -export const useMessageSound = () => { - const { load, play } = useSound('assets/message.mp3'); - - useEffect(() => { - load(); - }, [load]); - - return useMemo(() => debounce(() => play(), 5000, true), [play]); -}; - -export default useMessageSound; diff --git a/custom/fitness-demo/next.config.js b/custom/fitness-demo/next.config.js index 9140e28..ec50e25 100644 --- a/custom/fitness-demo/next.config.js +++ b/custom/fitness-demo/next.config.js @@ -2,6 +2,9 @@ const withPlugins = require('next-compose-plugins'); const withTM = require('next-transpile-modules')([ '@custom/shared', '@custom/basic-call', + '@custom/text-chat', + '@custom/live-streaming', + '@custom/recording', ]); const packageJson = require('./package.json'); diff --git a/custom/fitness-demo/package.json b/custom/fitness-demo/package.json index 839e51c..fd34066 100644 --- a/custom/fitness-demo/package.json +++ b/custom/fitness-demo/package.json @@ -11,6 +11,10 @@ }, "dependencies": { "@custom/shared": "*", + "@custom/basic-call": "*", + "@custom/text-chat": "*", + "@custom/live-streaming": "*", + "@custom/recording": "*", "next": "^11.1.2", "pluralize": "^8.0.0" }, diff --git a/custom/fitness-demo/pages/_app.js b/custom/fitness-demo/pages/_app.js index 4eba667..19357e0 100644 --- a/custom/fitness-demo/pages/_app.js +++ b/custom/fitness-demo/pages/_app.js @@ -1,11 +1,11 @@ import React from 'react'; +import LiveStreamingModal from '@custom/live-streaming/components/LiveStreamingModal'; +import RecordingModal from '@custom/recording/components/RecordingModal'; import GlobalStyle from '@custom/shared/components/GlobalStyle'; import Head from 'next/head'; import PropTypes from 'prop-types'; import { App as CustomApp } from '../components/App/App'; import ChatAside from '../components/Call/ChatAside'; -import LiveStreamingModal from '../components/Modals/LiveStreamingModal'; -import RecordingModal from '../components/Modals/RecordingModal'; import Tray from '../components/Tray'; function App({ Component, pageProps }) { diff --git a/custom/live-streaming/components/LiveStreamingModal.js b/custom/live-streaming/components/LiveStreamingModal.js index 698f0d4..97896c8 100644 --- a/custom/live-streaming/components/LiveStreamingModal.js +++ b/custom/live-streaming/components/LiveStreamingModal.js @@ -1,10 +1,10 @@ import React, { useEffect, useState } from 'react'; -import { Button } from '@custom/shared/components/Button'; +import Button from '@custom/shared/components/Button'; import { CardBody } from '@custom/shared/components/Card'; import Field from '@custom/shared/components/Field'; import { TextInput, SelectInput } from '@custom/shared/components/Input'; import Modal from '@custom/shared/components/Modal'; -import { Well } from '@custom/shared/components/Well'; +import Well from '@custom/shared/components/Well'; import { useCallState } from '@custom/shared/contexts/CallProvider'; import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; import { useUIState } from '@custom/shared/contexts/UIStateProvider'; diff --git a/custom/text-chat/components/ChatAside.js b/custom/text-chat/components/ChatAside.js index 3d1a21b..4a62bde 100644 --- a/custom/text-chat/components/ChatAside.js +++ b/custom/text-chat/components/ChatAside.js @@ -4,8 +4,8 @@ import Button from '@custom/shared/components/Button'; import { TextInput } from '@custom/shared/components/Input'; import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider'; import { useUIState } from '@custom/shared/contexts/UIStateProvider'; +import { useMessageSound } from '@custom/text-chat/hooks/useMessageSound'; import { useChat } from '../contexts/ChatProvider'; -import { useMessageSound } from '../hooks/useMessageSound'; export const CHAT_ASIDE = 'chat';