Created
May 21, 2024 12:43
-
-
Save Tushkiz/972164766504112f87d7f6f5b488cd19 to your computer and use it in GitHub Desktop.
Meeting with self video in PiP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useDyteMeeting, useDyteSelector } from '@dytesdk/react-web-core'; | |
import { | |
DyteAudioVisualizer, | |
DyteParticipantTile, | |
DyteNameTag, | |
DyteAvatar, | |
DyteMeetingTitle, | |
DyteClock, | |
DyteMicToggle, | |
DyteCameraToggle, | |
DyteParticipantCount, | |
DyteParticipantsAudio, | |
DyteSetupScreen, | |
DytePipToggle, | |
} from '@dytesdk/react-ui-kit'; | |
import { useEffect, useMemo, useRef } from 'react'; | |
import { createGrid } from 'good-grid'; | |
import { useGridDimensions } from 'good-grid/react'; | |
import clsx from 'clsx'; | |
function UI() { | |
const $grid = useRef<HTMLElement>(null); | |
const dimensions = useGridDimensions($grid); | |
const { meeting } = useDyteMeeting(); | |
const self = useDyteSelector((meeting) => meeting.self); | |
const activeParticipants = useDyteSelector((meeting) => | |
meeting.participants.active.toArray() | |
); | |
const pinnedParticipants = useDyteSelector((meeting) => | |
meeting.participants.pinned.toArray() | |
); | |
// show pinned participants first | |
const participants = [ | |
...pinnedParticipants, | |
...activeParticipants.filter((p) => !pinnedParticipants.includes(p)), | |
self | |
]; | |
const onParticipantTileLoad = ( | |
event: CustomEvent<{ participant: any; videoElement: HTMLVideoElement }>, | |
) => { | |
if (!meeting) return; | |
const { participant, videoElement } = event.detail; | |
if (!participant || !videoElement) return; | |
if (meeting.self.userId !== participant.userId) return; | |
meeting.participants.pip?.addSource( | |
participant.id, | |
videoElement, | |
participant.videoEnabled, | |
false, | |
participant.name, | |
); | |
if (participant.videoEnabled) { | |
meeting.participants.pip?.enableSource(participant.id); | |
} | |
}; | |
const onParticipantTileUnload = (event: CustomEvent<any>) => { | |
if (!meeting) return; | |
const participant = event.detail; | |
meeting.participants.pip?.removeSource(participant.id); | |
}; | |
const { width, height, getPosition } = useMemo( | |
() => | |
createGrid({ | |
dimensions, | |
count: participants.length, | |
aspectRatio: '4:3', | |
gap: 12, | |
}), | |
[participants] | |
); | |
return ( | |
<div className="w-full h-full flex flex-col"> | |
<DyteParticipantsAudio meeting={meeting} /> | |
<header className="h-12 flex items-center justify-between px-4 border-b"> | |
<div className="flex items-center gap-1 md:gap-2"> | |
<img | |
src="https://assets.dyte.io/logo-outlined.png" | |
className="h-6 md:h-7" | |
/> | |
<div className="w-px h-7 mx-1 rotate-[18deg] bg-zinc-200"></div> | |
<DyteMeetingTitle | |
meeting={meeting} | |
className="mx-0 font-medium text-xs md:text-sm font-sans" | |
/> | |
</div> | |
<div> | |
<DyteParticipantCount | |
meeting={meeting} | |
className="text-xs md:text-sm" | |
/> | |
<DyteClock meeting={meeting} className="text-xs md:text-sm" /> | |
</div> | |
</header> | |
<main | |
className="flex-grow flex-shrink-0 relative flex flex-wrap content-center justify-center gap-4 p-4 overflow-clip" | |
ref={$grid} | |
> | |
{participants.map((participant, index) => { | |
const { top, left } = getPosition(index); | |
return ( | |
<DyteParticipantTile | |
participant={participant} | |
meeting={meeting} | |
key={participant.id} | |
className={clsx( | |
'absolute transition-all border bg-zinc-100', | |
participant.audioEnabled | |
? 'border-dyte-blue shadow-md shadow-dyte-blue/30' | |
: 'border-zinc-200' | |
)} | |
style={{ | |
width, | |
height, | |
top, | |
left, | |
}} | |
onTileLoad={onParticipantTileLoad} | |
onTileUnload={onParticipantTileUnload} | |
> | |
<DyteAvatar participant={participant} size="md" /> | |
<DyteNameTag participant={participant} meeting={meeting}> | |
<DyteAudioVisualizer participant={participant} slot="start" /> | |
</DyteNameTag> | |
</DyteParticipantTile> | |
); | |
})} | |
</main> | |
<footer className="py-2 flex items-center justify-center"> | |
<DyteMicToggle meeting={meeting} /> | |
<DyteCameraToggle meeting={meeting} /> | |
<DytePipToggle meeting={meeting} /> | |
</footer> | |
</div> | |
); | |
} | |
export default function Meeting() { | |
const { meeting } = useDyteMeeting(); | |
const roomJoined = useDyteSelector((meeting) => meeting.self.roomJoined); | |
useEffect(() => { | |
if (roomJoined && !meeting.participants.pip.isActive) { | |
const pipSupported = | |
meeting.participants.pip?.isSupported() && meeting.self.config?.pipMode; | |
if (pipSupported) { | |
meeting.participants.pip.init(); | |
} | |
} | |
}, [roomJoined]); | |
if (!roomJoined) { | |
return <DyteSetupScreen meeting={meeting} />; | |
} | |
return <UI />; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment