diff --git a/custom/basic-call/components/App/Asides.js b/custom/basic-call/components/App/Asides.js index be0e418..4afbca0 100644 --- a/custom/basic-call/components/App/Asides.js +++ b/custom/basic-call/components/App/Asides.js @@ -1,5 +1,6 @@ import React from 'react'; -import { PeopleAside } from '@custom/shared/components/Aside/PeopleAside'; +import { NetworkAside } from '@custom/shared/components/Aside'; +import { PeopleAside } from '@custom/shared/components/Aside'; import { useUIState } from '@custom/shared/contexts/UIStateProvider'; export const Asides = () => { @@ -8,6 +9,7 @@ export const Asides = () => { return ( <> + {asides.map((AsideComponent) => ( ))} diff --git a/custom/live-fitness/.babelrc b/custom/live-fitness/.babelrc deleted file mode 100644 index a6f4434..0000000 --- a/custom/live-fitness/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["next/babel"], - "plugins": ["inline-react-svg"] -} diff --git a/custom/live-fitness/README.md b/custom/live-fitness/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/custom/live-fitness/components/App/App.js b/custom/live-fitness/components/App/App.js deleted file mode 100644 index 2d44366..0000000 --- a/custom/live-fitness/components/App/App.js +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; - -import App from '@custom/basic-call/components/App'; -import { RecordingProvider } from '../../contexts/RecordingProvider'; - -// Extend our basic call app component with the recording context -export const AppWithRecording = () => ( - - - -); - -export default AppWithRecording; diff --git a/custom/live-fitness/components/App/index.js b/custom/live-fitness/components/App/index.js deleted file mode 100644 index 82a89dc..0000000 --- a/custom/live-fitness/components/App/index.js +++ /dev/null @@ -1 +0,0 @@ -export { AppWithRecording as default } from './App'; diff --git a/custom/live-fitness/components/Tray/Tray.js b/custom/live-fitness/components/Tray/Tray.js deleted file mode 100644 index 2c12cae..0000000 --- a/custom/live-fitness/components/Tray/Tray.js +++ /dev/null @@ -1,47 +0,0 @@ -import React, { useEffect } from 'react'; - -import { TrayButton } from '@custom/shared/components/Tray'; -import { useUIState } from '@custom/shared/contexts/UIStateProvider'; -import { ReactComponent as IconRecord } from '@custom/shared/icons/record-md.svg'; - -import { - RECORDING_ERROR, - RECORDING_RECORDING, - RECORDING_SAVED, - RECORDING_UPLOADING, - useRecording, -} from '../../contexts/RecordingProvider'; -import { RECORDING_MODAL } from '../RecordingModal'; - -export const Tray = () => { - const { openModal } = useUIState(); - const { recordingState } = useRecording(); - - useEffect(() => { - console.log(`⏺️ Recording state: ${recordingState}`); - - if (recordingState === RECORDING_ERROR) { - // show error modal here - } - }, [recordingState]); - - const isRecording = [ - RECORDING_RECORDING, - RECORDING_UPLOADING, - RECORDING_SAVED, - ].includes(recordingState); - - return ( - <> - openModal(RECORDING_MODAL)} - > - - - - ); -}; - -export default Tray; diff --git a/custom/live-fitness/components/Tray/index.js b/custom/live-fitness/components/Tray/index.js deleted file mode 100644 index 100bcc8..0000000 --- a/custom/live-fitness/components/Tray/index.js +++ /dev/null @@ -1 +0,0 @@ -export { Tray as default } from './Tray'; diff --git a/custom/live-fitness/env.example b/custom/live-fitness/env.example deleted file mode 100644 index 5ab7e03..0000000 --- a/custom/live-fitness/env.example +++ /dev/null @@ -1,8 +0,0 @@ -# Domain excluding 'https://' and 'daily.co' e.g. 'somedomain' -DAILY_DOMAIN= - -# Obtained from https://dashboard.daily.co/developers -DAILY_API_KEY= - -# Daily REST API endpoint -DAILY_REST_DOMAIN=https://api.daily.co/v1 diff --git a/custom/live-fitness/next.config.js b/custom/live-fitness/next.config.js deleted file mode 100644 index 9140e28..0000000 --- a/custom/live-fitness/next.config.js +++ /dev/null @@ -1,13 +0,0 @@ -const withPlugins = require('next-compose-plugins'); -const withTM = require('next-transpile-modules')([ - '@custom/shared', - '@custom/basic-call', -]); - -const packageJson = require('./package.json'); - -module.exports = withPlugins([withTM], { - env: { - PROJECT_TITLE: packageJson.description, - }, -}); diff --git a/custom/live-fitness/package.json b/custom/live-fitness/package.json deleted file mode 100644 index dab6395..0000000 --- a/custom/live-fitness/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@custom/live-fitness", - "description": "Live Fitness", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@custom/shared": "*", - "@custom/basic-call": "*", - "next": "^11.0.0", - "pluralize": "^8.0.0", - "react": "^17.0.2", - "react-dom": "^17.0.2" - }, - "devDependencies": { - "babel-plugin-module-resolver": "^4.1.0", - "next-compose-plugins": "^2.2.1", - "next-transpile-modules": "^8.0.0" - } -} diff --git a/custom/live-fitness/pages/_app.js b/custom/live-fitness/pages/_app.js deleted file mode 100644 index 7636341..0000000 --- a/custom/live-fitness/pages/_app.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import App from '@custom/basic-call/pages/_app'; -import AppWithRecording from '../components/App'; - -import { RecordingModal } from '../components/RecordingModal'; -import Tray from '../components/Tray'; - -App.modals = [RecordingModal]; -App.customAppComponent = ; -App.customTrayComponent = ; - -export default App; diff --git a/custom/live-fitness/pages/api b/custom/live-fitness/pages/api deleted file mode 120000 index 999f604..0000000 --- a/custom/live-fitness/pages/api +++ /dev/null @@ -1 +0,0 @@ -../../basic-call/pages/api \ No newline at end of file diff --git a/custom/live-fitness/pages/index.js b/custom/live-fitness/pages/index.js deleted file mode 100644 index f61b429..0000000 --- a/custom/live-fitness/pages/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import Index from '@custom/basic-call/pages'; -import getDemoProps from '@custom/shared/lib/demoProps'; - -export async function getStaticProps() { - const defaultProps = getDemoProps(); - - return { - props: { - ...defaultProps, - forceFetchToken: true, - forceOwner: true, - }, - }; -} - -export default Index; diff --git a/custom/live-fitness/public b/custom/live-fitness/public deleted file mode 120000 index 33a6e67..0000000 --- a/custom/live-fitness/public +++ /dev/null @@ -1 +0,0 @@ -../basic-call/public \ No newline at end of file diff --git a/custom/shared/components/Aside/NetworkAside.js b/custom/shared/components/Aside/NetworkAside.js new file mode 100644 index 0000000..0f4d61c --- /dev/null +++ b/custom/shared/components/Aside/NetworkAside.js @@ -0,0 +1,107 @@ +import React, { useCallback, useMemo, useEffect, useState } from 'react'; +import { Aside } from '@custom/shared/components/Aside'; +import { useCallState } from '../../contexts/CallProvider'; +import { useUIState } from '../../contexts/UIStateProvider'; +import Capsule from '../Capsule'; + +export const NETWORK_ASIDE = 'network'; + +const NETWORK_QUALITY_LABELS = { + low: 'Low', + 'very-low': 'Very Low', + good: 'Good', +}; + +export const NetworkAside = () => { + const { callObject } = useCallState(); + const { showAside, setShowAside } = useUIState(); + const [networkStats, setNetworkStats] = useState(); + + const updateStats = useCallback(async () => { + setNetworkStats(await callObject.getNetworkStats()); + }, [callObject]); + + useEffect(() => { + if (!callObject) { + return; + } + + updateStats(); + + const i = setInterval(updateStats, 2000); + + return () => clearInterval(i); + }, [callObject, updateStats]); + + const downloadKbs = useMemo( + () => + Math.round( + (networkStats?.stats?.latest?.videoRecvBitsPerSecond ?? 0) / 1000 + ), + [networkStats] + ); + + const uploadKbs = useMemo( + () => + Math.round( + (networkStats?.stats?.latest?.videoSendBitsPerSecond ?? 0) / 1000 + ), + [networkStats] + ); + + if (!showAside || showAside !== NETWORK_ASIDE) { + return null; + } + + return ( + + ); +}; + +export default NetworkAside; diff --git a/custom/shared/components/Aside/index.js b/custom/shared/components/Aside/index.js index 072ca0e..b21056d 100644 --- a/custom/shared/components/Aside/index.js +++ b/custom/shared/components/Aside/index.js @@ -1,2 +1,3 @@ export { Aside } from './Aside'; export { PeopleAside } from './PeopleAside'; +export { NetworkAside } from './NetworkAside'; diff --git a/custom/shared/components/Capsule/Capsule.js b/custom/shared/components/Capsule/Capsule.js new file mode 100644 index 0000000..09362b0 --- /dev/null +++ b/custom/shared/components/Capsule/Capsule.js @@ -0,0 +1,42 @@ +import React from 'react'; +import classNames from 'classnames'; +import PropTypes from 'prop-types'; + +export const Capsule = ({ children, variant }) => ( + + {children} + + +); + +Capsule.propTypes = { + children: PropTypes.node, + variant: PropTypes.oneOf(['success', 'warning', 'error', 'info']), +}; + +export default Capsule; diff --git a/custom/shared/components/Capsule/index.js b/custom/shared/components/Capsule/index.js new file mode 100644 index 0000000..eb1b21c --- /dev/null +++ b/custom/shared/components/Capsule/index.js @@ -0,0 +1 @@ +export { Capsule as default } from './Capsule'; diff --git a/custom/shared/components/MessageCard/MessageCard.js b/custom/shared/components/MessageCard/MessageCard.js index 425f54e..ad48d65 100644 --- a/custom/shared/components/MessageCard/MessageCard.js +++ b/custom/shared/components/MessageCard/MessageCard.js @@ -15,7 +15,7 @@ export const MessageCard = ({ hideBack = false, onBack, }) => ( - + {header && {header}} {children && {children}} {!hideBack && ( @@ -23,7 +23,7 @@ export const MessageCard = ({ {onBack ? ( ) : ( - + )} )} diff --git a/custom/shared/components/Tray/BasicTray.js b/custom/shared/components/Tray/BasicTray.js index abe2b2f..d9a80fb 100644 --- a/custom/shared/components/Tray/BasicTray.js +++ b/custom/shared/components/Tray/BasicTray.js @@ -1,4 +1,5 @@ import React from 'react'; +import { NETWORK_ASIDE } from '@custom/shared/components/Aside/NetworkAside'; import { PEOPLE_ASIDE } from '@custom/shared/components/Aside/PeopleAside'; import { DEVICE_MODAL } from '@custom/shared/components/DeviceSelectModal'; import { useCallState } from '@custom/shared/contexts/CallProvider'; @@ -9,6 +10,7 @@ import { ReactComponent as IconCameraOn } from '@custom/shared/icons/camera-on-m import { ReactComponent as IconLeave } from '@custom/shared/icons/leave-md.svg'; import { ReactComponent as IconMicOff } from '@custom/shared/icons/mic-off-md.svg'; import { ReactComponent as IconMicOn } from '@custom/shared/icons/mic-on-md.svg'; +import { ReactComponent as IconNetwork } from '@custom/shared/icons/network-md.svg'; import { ReactComponent as IconPeople } from '@custom/shared/icons/people-md.svg'; import { ReactComponent as IconSettings } from '@custom/shared/icons/settings-md.svg'; import { Tray, TrayButton } from './Tray'; @@ -47,7 +49,9 @@ export const BasicTray = () => { openModal(DEVICE_MODAL)}> - + toggleAside(NETWORK_ASIDE)}> + + toggleAside(PEOPLE_ASIDE)}> diff --git a/custom/shared/hooks/useCallUI.js b/custom/shared/hooks/useCallUI.js index ea8c44c..846db8f 100644 --- a/custom/shared/hooks/useCallUI.js +++ b/custom/shared/hooks/useCallUI.js @@ -81,7 +81,8 @@ export const useCallUI = ({ callEnded() ) : ( - You have left the call. We hope you had fun! + You have left the call (either manually or because the room + expired). We hope you had fun! ); default: @@ -89,11 +90,7 @@ export const useCallUI = ({ } return ( - window.location.reload()} - > + A fatal error occured in the call loop. Please check you have entered a valid DAILY_DOMAIN and DAILY_API_KEY{' '} environmental variables. diff --git a/custom/shared/icons/network-md.svg b/custom/shared/icons/network-md.svg new file mode 100644 index 0000000..1259c14 --- /dev/null +++ b/custom/shared/icons/network-md.svg @@ -0,0 +1 @@ + \ No newline at end of file