abstracted tray and added ability to pass custom component

This commit is contained in:
J Taylor 2021-06-22 14:02:47 +01:00
parent 9b79d2a510
commit dadd8c6d2b
11 changed files with 111 additions and 70 deletions

View File

@ -8,11 +8,11 @@ import { Asides } from './Asides';
import { Modals } from './Modals';
export const App = () => {
const { state, leave } = useCallState();
const { state } = useCallState();
const componentForState = useCallUI({
state,
room: () => <Room onLeave={() => leave()} />,
room: () => <Room />,
});
// Memoize children to avoid unnecassary renders from HOC

View File

@ -1,48 +1,23 @@
import React from 'react';
import { Audio } from '@dailyjs/shared/components/Audio';
import { Tray, TrayButton } from '@dailyjs/shared/components/Tray';
import { BasicTray } from '@dailyjs/shared/components/Tray';
import {
WaitingRoomModal,
WaitingRoomNotification,
} from '@dailyjs/shared/components/WaitingRoom';
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
import { useMediaDevices } from '@dailyjs/shared/contexts/MediaDeviceProvider';
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
import { useWaitingRoom } from '@dailyjs/shared/contexts/WaitingRoomProvider';
import useJoinSound from '@dailyjs/shared/hooks/useJoinSound';
import { ReactComponent as IconCameraOff } from '@dailyjs/shared/icons/camera-off-md.svg';
import { ReactComponent as IconCameraOn } from '@dailyjs/shared/icons/camera-on-md.svg';
import { ReactComponent as IconLeave } from '@dailyjs/shared/icons/leave-md.svg';
import { ReactComponent as IconMicOff } from '@dailyjs/shared/icons/mic-off-md.svg';
import { ReactComponent as IconMicOn } from '@dailyjs/shared/icons/mic-on-md.svg';
import { ReactComponent as IconPeople } from '@dailyjs/shared/icons/people-md.svg';
import { ReactComponent as IconSettings } from '@dailyjs/shared/icons/settings-md.svg';
import PropTypes from 'prop-types';
import { PEOPLE_ASIDE } from '../../../shared/components/Aside/PeopleAside';
import { VideoGrid } from '../VideoGrid';
import { Header } from './Header';
export const Room = ({ onLeave }) => {
const { callObject } = useCallState();
const { setShowDeviceModal, setShowAside } = useUIState();
const { isCamMuted, isMicMuted } = useMediaDevices();
export const Room = () => {
const { setShowModal, showModal } = useWaitingRoom();
const { localParticipant } = useParticipants();
useJoinSound();
const toggleCamera = (newState) => {
if (!callObject) return false;
return callObject.setLocalVideo(newState);
};
const toggleMic = (newState) => {
if (!callObject) return false;
return callObject.setLocalAudio(newState);
};
return (
<div className="room">
<Header />
@ -61,39 +36,7 @@ export const Room = ({ onLeave }) => {
</>
)}
<Tray>
<TrayButton
label="Camera"
onClick={() => toggleCamera(isCamMuted)}
orange={isCamMuted}
>
{isCamMuted ? <IconCameraOff /> : <IconCameraOn />}
</TrayButton>
<TrayButton
label="Mic"
onClick={() => toggleMic(isMicMuted)}
orange={isMicMuted}
>
{isMicMuted ? <IconMicOff /> : <IconMicOn />}
</TrayButton>
<TrayButton label="Settings" onClick={() => setShowDeviceModal(true)}>
<IconSettings />
</TrayButton>
<TrayButton
label="People"
onClick={() => setShowAside((p) => (p ? null : PEOPLE_ASIDE))}
>
<IconPeople />
</TrayButton>
<span className="divider" />
<TrayButton label="Leave" onClick={onLeave} orange>
<IconLeave />
</TrayButton>
</Tray>
<BasicTray />
<Audio />
<style jsx>{`
@ -118,8 +61,4 @@ export const Room = ({ onLeave }) => {
);
};
Room.propTypes = {
onLeave: PropTypes.func.isRequired,
};
export default Room;

View File

@ -12,7 +12,11 @@ function App({ Component, pageProps }) {
</Head>
<GlobalHead />
<GlobalStyle />
<Component asides={App.asides} {...pageProps} />
<Component
asides={App.asides}
customTrayComponent={App.customTrayComponent}
{...pageProps}
/>
</>
);
}
@ -28,5 +32,6 @@ App.propTypes = {
};
App.asides = [];
App.customTrayComponent = null;
export default App;

View File

@ -17,7 +17,12 @@ import { Intro, NotConfigured } from '../components/Intro';
* - Set call owner status
* - Finally, renders the main application loop
*/
export default function Index({ domain, isConfigured = false, asides }) {
export default function Index({
domain,
isConfigured = false,
asides,
customTrayComponent,
}) {
const [roomName, setRoomName] = useState('');
const [fetchingToken, setFetchingToken] = useState(false);
const [token, setToken] = useState();
@ -92,7 +97,7 @@ export default function Index({ domain, isConfigured = false, asides }) {
* Main call UI
*/
return (
<UIStateProvider asides={asides}>
<UIStateProvider asides={asides} customTrayComponent={customTrayComponent}>
<CallProvider domain={domain} room={roomName} token={token}>
<ParticipantsProvider>
<TracksProvider>
@ -112,6 +117,7 @@ Index.propTypes = {
isConfigured: PropTypes.bool.isRequired,
domain: PropTypes.string,
asides: PropTypes.arrayOf(PropTypes.func),
customTrayComponent: PropTypes.node,
};
export async function getStaticProps() {

View File

@ -0,0 +1,68 @@
import React from 'react';
import { PEOPLE_ASIDE } from '@dailyjs/shared/components/Aside/PeopleAside';
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
import { useMediaDevices } from '@dailyjs/shared/contexts/MediaDeviceProvider';
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
import { ReactComponent as IconCameraOff } from '@dailyjs/shared/icons/camera-off-md.svg';
import { ReactComponent as IconCameraOn } from '@dailyjs/shared/icons/camera-on-md.svg';
import { ReactComponent as IconLeave } from '@dailyjs/shared/icons/leave-md.svg';
import { ReactComponent as IconMicOff } from '@dailyjs/shared/icons/mic-off-md.svg';
import { ReactComponent as IconMicOn } from '@dailyjs/shared/icons/mic-on-md.svg';
import { ReactComponent as IconPeople } from '@dailyjs/shared/icons/people-md.svg';
import { ReactComponent as IconSettings } from '@dailyjs/shared/icons/settings-md.svg';
import { Tray, TrayButton } from './Tray';
export const BasicTray = () => {
const { callObject, leave } = useCallState();
const { customTrayComponent, setShowDeviceModal, setShowAside } =
useUIState();
const { isCamMuted, isMicMuted } = useMediaDevices();
const toggleCamera = (newState) => {
if (!callObject) return false;
return callObject.setLocalVideo(newState);
};
const toggleMic = (newState) => {
if (!callObject) return false;
return callObject.setLocalAudio(newState);
};
return (
<Tray>
<TrayButton
label="Camera"
onClick={() => toggleCamera(isCamMuted)}
orange={isCamMuted}
>
{isCamMuted ? <IconCameraOff /> : <IconCameraOn />}
</TrayButton>
<TrayButton
label="Mic"
onClick={() => toggleMic(isMicMuted)}
orange={isMicMuted}
>
{isMicMuted ? <IconMicOff /> : <IconMicOn />}
</TrayButton>
<TrayButton label="Settings" onClick={() => setShowDeviceModal(true)}>
<IconSettings />
</TrayButton>
<TrayButton
label="People"
onClick={() => setShowAside((p) => (p ? null : PEOPLE_ASIDE))}
>
<IconPeople />
</TrayButton>
{customTrayComponent}
<span className="divider" />
<TrayButton label="Leave" onClick={() => leave()} orange>
<IconLeave />
</TrayButton>
</Tray>
);
};
export default BasicTray;

View File

@ -1,2 +1,3 @@
export { Tray as default } from './Tray';
export { Tray, TrayButton } from './Tray';
export { BasicTray } from './BasicTray';

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
export const UIStateContext = createContext();
export const UIStateProvider = ({ asides, children }) => {
export const UIStateProvider = ({ asides, customTrayComponent, children }) => {
const [showDeviceModal, setShowDeviceModal] = useState(false);
const [showAside, setShowAside] = useState();
@ -11,6 +11,7 @@ export const UIStateProvider = ({ asides, children }) => {
<UIStateContext.Provider
value={{
asides,
customTrayComponent,
showDeviceModal,
setShowDeviceModal,
showAside,
@ -25,6 +26,7 @@ export const UIStateProvider = ({ asides, children }) => {
UIStateProvider.propTypes = {
children: PropTypes.node,
asides: PropTypes.arrayOf(PropTypes.func),
customTrayComponent: PropTypes.node,
};
export const useUIState = () => useContext(UIStateContext);

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>comments</title><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" fill="none" stroke="currentColor"><path d="M23,5V16a2,2,0,0,1-2,2H19v4l-6-4H12" stroke="currentColor"></path><path d="M17,2H3A2,2,0,0,0,1,4v8a2,2,0,0,0,2,2H5v5l7-5h5a2,2,0,0,0,2-2V4A2,2,0,0,0,17,2Z"></path></g></svg>

After

Width:  |  Height:  |  Size: 389 B

View File

@ -0,0 +1,14 @@
import React from 'react';
import { TrayButton } from '@dailyjs/shared/components/Tray';
import { ReactComponent as IconChat } from '@dailyjs/shared/icons/chat-md.svg';
export const Tray = () => (
<>
<TrayButton label="Chat">
<IconChat />
</TrayButton>
</>
);
export default Tray;

View File

@ -0,0 +1 @@
export { Tray as default } from './Tray';

View File

@ -1,5 +1,9 @@
import React from 'react';
import App from '@dailyjs/basic-call/pages/_app';
import Tray from '../components/Tray';
App.asides = [];
App.customTrayComponent = <Tray />;
export default App;