initial people aside bar
This commit is contained in:
parent
f6229317d8
commit
84a9e3ea3e
|
|
@ -3,6 +3,7 @@ import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
|||
import { useCallUI } from '@dailyjs/shared/hooks/useCallUI';
|
||||
|
||||
import Room from '../Room';
|
||||
import { Asides } from './Asides';
|
||||
import { Modals } from './Modals';
|
||||
|
||||
export const App = () => {
|
||||
|
|
@ -19,6 +20,7 @@ export const App = () => {
|
|||
<div className="app">
|
||||
{componentForState()}
|
||||
<Modals />
|
||||
<Asides />
|
||||
<style jsx>{`
|
||||
color: white;
|
||||
height: 100vh;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react';
|
||||
import { PeopleAside } from '@dailyjs/shared/components/Aside';
|
||||
|
||||
export const Asides = () => (
|
||||
<>
|
||||
<PeopleAside />
|
||||
</>
|
||||
);
|
||||
|
||||
export default Asides;
|
||||
|
|
@ -14,6 +14,7 @@ import { ReactComponent as IconCameraOn } from '@dailyjs/shared/icons/camera-on-
|
|||
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';
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ import { Tray, TrayButton } from './Tray';
|
|||
|
||||
export const Room = ({ onLeave }) => {
|
||||
const { callObject } = useCallState();
|
||||
const { setShowDeviceModal } = useUIState();
|
||||
const { setShowDeviceModal, setShowPeopleAside } = useUIState();
|
||||
const { isCamMuted, isMicMuted } = useMediaDevices();
|
||||
const { setShowModal, showModal } = useWaitingRoom();
|
||||
const { localParticipant } = useParticipants();
|
||||
|
|
@ -75,6 +76,13 @@ export const Room = ({ onLeave }) => {
|
|||
<IconSettings />
|
||||
</TrayButton>
|
||||
|
||||
<TrayButton
|
||||
label="People"
|
||||
onClick={() => setShowPeopleAside((p) => !p)}
|
||||
>
|
||||
<IconPeople />
|
||||
</TrayButton>
|
||||
|
||||
<span className="divider" />
|
||||
|
||||
<TrayButton label="Leave" onClick={onLeave} orange>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const ASIDE_WIDTH = 380;
|
||||
|
||||
export const Aside = ({ children }) => (
|
||||
<aside className="call-aside">
|
||||
<div className="inner">{children}</div>
|
||||
<style jsx>{`
|
||||
.call-aside {
|
||||
background: white;
|
||||
width: ${ASIDE_WIDTH}px;
|
||||
height: 100vh;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0px 15px 35px rgba(18, 26, 36, 0.25);
|
||||
color: var(--text-default);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.call-aside .inner {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
`}</style>
|
||||
</aside>
|
||||
);
|
||||
|
||||
Aside.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
export default Aside;
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
import React from 'react';
|
||||
import Aside from '@dailyjs/shared/components/Aside';
|
||||
import { ReactComponent as IconCamOff } from '@dailyjs/shared/icons/camera-off-sm.svg';
|
||||
import { ReactComponent as IconCamOn } from '@dailyjs/shared/icons/camera-on-sm.svg';
|
||||
import { ReactComponent as IconMicOff } from '@dailyjs/shared/icons/mic-off-sm.svg';
|
||||
import { ReactComponent as IconMicOn } from '@dailyjs/shared/icons/mic-on-sm.svg';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useCallState } from '../../contexts/CallProvider';
|
||||
import { useParticipants } from '../../contexts/ParticipantsProvider';
|
||||
import { useUIState } from '../../contexts/UIStateProvider';
|
||||
import { Button } from '../Button';
|
||||
|
||||
const PersonRow = ({ participant, isOwner = false }) => (
|
||||
<div className="person-row">
|
||||
<div>
|
||||
{participant.name} {participant.isLocal && '(You)'}
|
||||
</div>
|
||||
<div className="actions">
|
||||
{!isOwner ? (
|
||||
<>
|
||||
<span
|
||||
className={participant.isCamMuted ? 'state error' : 'state success'}
|
||||
>
|
||||
{participant.isCamMuted ? <IconCamOff /> : <IconCamOn />}
|
||||
</span>
|
||||
<span
|
||||
className={participant.isMicMuted ? 'state error' : 'state success'}
|
||||
>
|
||||
{participant.isMicMuted ? <IconMicOff /> : <IconMicOn />}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
size="medium-square"
|
||||
variant={participant.isCamMuted ? 'error-light' : 'success-light'}
|
||||
>
|
||||
{participant.isCamMuted ? <IconCamOff /> : <IconCamOn />}
|
||||
</Button>
|
||||
<Button
|
||||
size="medium-square"
|
||||
variant={participant.isMicMuted ? 'error-light' : 'success-light'}
|
||||
>
|
||||
{participant.isMicMuted ? <IconMicOff /> : <IconMicOn />}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.person-row {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--gray-light);
|
||||
padding: var(--spacing-xs) 0;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 0 var(--spacing-xs);
|
||||
}
|
||||
|
||||
.person-row .actions {
|
||||
display: flex;
|
||||
gap: var(--spacing-xxs);
|
||||
}
|
||||
|
||||
.mute-state {
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.state.error {
|
||||
color: var(--red-default);
|
||||
}
|
||||
.state.success {
|
||||
color: var(--green-default);
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
PersonRow.propTypes = {
|
||||
participant: PropTypes.object,
|
||||
isOwner: PropTypes.bool,
|
||||
};
|
||||
|
||||
export const PeopleAside = () => {
|
||||
const { callObject } = useCallState();
|
||||
const { showPeopleAside } = useUIState();
|
||||
const { allParticipants, isOwner } = useParticipants();
|
||||
|
||||
if (!showPeopleAside) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Aside>
|
||||
{isOwner && (
|
||||
<>
|
||||
<Button
|
||||
onClick={() =>
|
||||
callObject.updateParticipants({ '*': { setAudio: false } })
|
||||
}
|
||||
>
|
||||
Mute all mics
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() =>
|
||||
callObject.updateParticipants({ '*': { setVideo: false } })
|
||||
}
|
||||
>
|
||||
Mute all cam
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{allParticipants.map((p) => (
|
||||
<PersonRow participant={p} key={p.id} isOwner={isOwner} />
|
||||
))}
|
||||
</Aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default PeopleAside;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export { Aside as default } from './Aside';
|
||||
export { Aside } from './Aside';
|
||||
export { PeopleAside } from './PeopleAside';
|
||||
|
|
@ -121,17 +121,42 @@ export const Button = forwardRef(
|
|||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.button.error {
|
||||
.button.warning {
|
||||
background: var(--secondary-default);
|
||||
border-color: var(--secondary-default);
|
||||
}
|
||||
.button.error:focus {
|
||||
.button.warning:focus {
|
||||
box-shadow: 0 0 0px 3px ${hexa(theme.secondary.default, 0.35)};
|
||||
}
|
||||
.button.error:hover {
|
||||
.button.warning:hover {
|
||||
border-color: var(--secondary-dark);
|
||||
}
|
||||
|
||||
.button.error {
|
||||
background: var(--red-default);
|
||||
border-color: var(--red-default);
|
||||
}
|
||||
.button.error:focus {
|
||||
box-shadow: 0 0 0px 3px ${hexa(theme.red.default, 0.35)};
|
||||
}
|
||||
.button.error:hover {
|
||||
border-color: var(--red-dark);
|
||||
}
|
||||
|
||||
.button.error-light {
|
||||
background: var(--red-light);
|
||||
border-color: var(--red-light);
|
||||
color: var(--red-default);
|
||||
}
|
||||
.button.error-light:focus {
|
||||
box-shadow: 0 0 0px 3px ${hexa(theme.red.default, 0.35)};
|
||||
}
|
||||
.button.error-light:hover {
|
||||
color: white;
|
||||
background: var(--red-default);
|
||||
border-color: var(--red-default);
|
||||
}
|
||||
|
||||
.button.success {
|
||||
background: var(--green-default);
|
||||
border-color: var(--green-default);
|
||||
|
|
@ -143,6 +168,20 @@ export const Button = forwardRef(
|
|||
border-color: var(--green-dark);
|
||||
}
|
||||
|
||||
.button.success-light {
|
||||
background: var(--green-light);
|
||||
border-color: var(--green-light);
|
||||
color: var(--green-default);
|
||||
}
|
||||
.button.success-light:focus {
|
||||
box-shadow: 0 0 0px 3px ${hexa(theme.green.default, 0.35)};
|
||||
}
|
||||
.button.success-light:hover {
|
||||
color: white;
|
||||
background: var(--green-default);
|
||||
border-color: var(--green-default);
|
||||
}
|
||||
|
||||
.button.shadow {
|
||||
box-shadow: 0 0 4px 0 rgb(0 0 0 / 8%), 0 4px 4px 0 rgb(0 0 0 / 4%);
|
||||
}
|
||||
|
|
@ -179,7 +218,6 @@ export const Button = forwardRef(
|
|||
color: white;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.button.translucent:hover,
|
||||
.button.translucent:focus,
|
||||
.button.translucent:active {
|
||||
|
|
@ -194,7 +232,6 @@ export const Button = forwardRef(
|
|||
color: white;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.button.blur:hover,
|
||||
.button.blur:focus,
|
||||
.button.blur:active {
|
||||
|
|
@ -202,7 +239,6 @@ export const Button = forwardRef(
|
|||
box-shadow: none;
|
||||
background: ${hexa(theme.blue.default, 1)};
|
||||
}
|
||||
|
||||
.button.blur:focus {
|
||||
box-shadow: 0 0 0px 3px ${hexa(theme.blue.default, 0.35)};
|
||||
}
|
||||
|
|
@ -212,14 +248,12 @@ export const Button = forwardRef(
|
|||
color: white;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.button.dark:hover,
|
||||
.button.dark:focus,
|
||||
.button.dark:active {
|
||||
background: ${theme.blue.default};
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.button.dark:focus {
|
||||
box-shadow: 0 0 0px 3px rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export const WaitingParticipantRow = ({ participant }) => {
|
|||
<Button onClick={handleAllowClick} size="small" variant="success">
|
||||
Allow
|
||||
</Button>
|
||||
<Button onClick={handleDenyClick} size="small" variant="error">
|
||||
<Button onClick={handleDenyClick} size="small" variant="warning">
|
||||
Deny
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export const WaitingRoomModal = ({ onClose }) => {
|
|||
<Button fullWidth onClick={handleAllowAllClick} variant="success">
|
||||
Allow all
|
||||
</Button>,
|
||||
<Button fullWidth onClick={handleDenyAllClick} variant="error">
|
||||
<Button fullWidth onClick={handleDenyAllClick} variant="warning">
|
||||
Deny all
|
||||
</Button>,
|
||||
]}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export const WaitingRoomNotification = () => {
|
|||
Allow
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={handleDenyClick} size="small" variant="error">
|
||||
<Button onClick={handleDenyClick} size="small" variant="warning">
|
||||
{hasMultiplePeopleWaiting ? 'Deny All' : 'Deny'}
|
||||
</Button>
|
||||
</CardFooter>
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ export const ParticipantsProvider = ({ children }) => {
|
|||
[allParticipants]
|
||||
);
|
||||
|
||||
const isOwner = useDeepCompareMemo(
|
||||
() => localParticipant?.isOwner,
|
||||
[localParticipant]
|
||||
);
|
||||
|
||||
/**
|
||||
* The participant who should be rendered prominently right now
|
||||
*/
|
||||
|
|
@ -221,6 +226,7 @@ export const ParticipantsProvider = ({ children }) => {
|
|||
setUsername,
|
||||
swapParticipantPosition,
|
||||
username,
|
||||
isOwner,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,15 @@ export const UIStateContext = createContext();
|
|||
|
||||
export const UIStateProvider = ({ children }) => {
|
||||
const [showDeviceModal, setShowDeviceModal] = useState(false);
|
||||
const [showPeopleAside, setShowPeopleAside] = useState(false);
|
||||
|
||||
return (
|
||||
<UIStateContext.Provider
|
||||
value={{
|
||||
showDeviceModal,
|
||||
setShowDeviceModal,
|
||||
showPeopleAside,
|
||||
setShowPeopleAside,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><g fill="currentColor"><path d="M10,12H8.242l-2,2H10a2,2,0,0,0,2-2V9.6L16,12V4.242l-6,6Z" fill="currentColor"></path><path d="M15.707.293a1,1,0,0,0-1.414,0L11.674,2.912A2,2,0,0,0,10,2H2A2,2,0,0,0,0,4v8a2,2,0,0,0,.912,1.674l-.619.619a1,1,0,1,0,1.414,1.414l14-14A1,1,0,0,0,15.707.293ZM2,12V4h8v.586L2.586,12Z" fill="currentColor"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 428 B |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><g fill="currentColor"><path d="M16,4,12,6.4V4a2,2,0,0,0-2-2H2A2,2,0,0,0,0,4v8a2,2,0,0,0,2,2h8a2,2,0,0,0,2-2V9.6L16,12ZM2,12V4h8v8Z" fill="currentColor"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 253 B |
|
|
@ -6,8 +6,5 @@
|
|||
<path d="M3.00007 16.5C2.81644 16.4998 2.63639 16.4491 2.47968 16.3534C2.32297 16.2576 2.19565 16.1206 2.11167 15.9573C2.02769 15.794 1.9903 15.6107 2.0036 15.4276C2.0169 15.2444 2.08038 15.0685 2.18707 14.919L12.1871 0.918991C12.3412 0.703105 12.5747 0.557273 12.8363 0.513577C13.0979 0.469881 13.3662 0.5319 13.5821 0.685991C13.798 0.840082 13.9438 1.07362 13.9875 1.33524C14.0312 1.59685 13.9692 1.8651 13.8151 2.08099L3.81507 16.081C3.72246 16.2107 3.60017 16.3165 3.45839 16.3893C3.31662 16.4622 3.15948 16.5002 3.00007 16.5Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white" transform="translate(0 0.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.0 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><title>microphone</title><g fill="currentColor"><path fill="currentColor" d="M8,10c2.2,0,4-1.8,4-4V4c0-2.2-1.8-4-4-4C5.8,0,4,1.8,4,4v2C4,8.2,5.8,10,8,10z"></path> <path d="M15.9,7.1C16,6.6,15.6,6.1,15.1,6c-0.5-0.1-1.1,0.3-1.1,0.8C13.5,9.8,11,12,8,12 S2.5,9.8,2.1,6.9C2,6.3,1.5,5.9,0.9,6C0.4,6.1,0,6.6,0.1,7.1c0.5,3.6,3.4,6.3,6.9,6.8V16h2v-2.1C12.5,13.5,15.4,10.7,15.9,7.1z"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 474 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19 21H23V16.677C22.9999 16.4772 22.9399 16.282 22.8278 16.1166C22.7157 15.9512 22.5566 15.8231 22.371 15.749L18.629 14.249C18.4438 14.175 18.2849 14.0473 18.1728 13.8823C18.0607 13.7173 18.0005 13.5225 18 13.323V12.445C18.6065 12.097 19.1107 11.5953 19.4617 10.9906C19.8128 10.3858 19.9985 9.69929 20 9.00001V7.00001C20.0002 6.29779 19.8154 5.6079 19.4644 4.9997C19.1134 4.3915 18.6085 3.88642 18.0004 3.53524C17.3923 3.18406 16.7024 2.99915 16.0002 2.99911C15.298 2.99908 14.6081 3.1839 14 3.53501" stroke="currentColor" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.371 16.749L10.629 15.249C10.4438 15.175 10.2849 15.0473 10.1728 14.8823C10.0607 14.7172 10.0005 14.5225 10 14.323V13.445C10.6065 13.0969 11.1107 12.5953 11.4617 11.9906C11.8128 11.3858 11.9985 10.6993 12 10V8C12 6.93913 11.5786 5.92172 10.8284 5.17157C10.0783 4.42143 9.06087 4 8 4C6.93913 4 5.92172 4.42143 5.17157 5.17157C4.42143 5.92172 4 6.93913 4 8V10C4.00153 10.6993 4.18717 11.3858 4.53826 11.9906C4.88935 12.5953 5.3935 13.0969 6 13.445V14.323C5.99987 14.5228 5.93989 14.718 5.82777 14.8834C5.71566 15.0488 5.55656 15.1769 5.371 15.251L1.629 16.751C1.44375 16.825 1.28488 16.9527 1.17279 17.1177C1.0607 17.2828 1.00053 17.4775 1 17.677V21H15V17.677C14.9999 17.4772 14.9399 17.282 14.8278 17.1166C14.7157 16.9512 14.5566 16.8231 14.371 16.749Z" stroke="currentColor" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
Loading…
Reference in New Issue