Commit 52f997c5 authored by Thisara Kavinda's avatar Thisara Kavinda

feat: implemented MeetingGrid

parent 37f6fb5d
......@@ -32,7 +32,7 @@ const Lobby = ({ handleJoinClick }: Props) => {
}}
>
<Box
width={'40%'}
width={'35%'}
borderRadius={'20px'}
sx={{ backgroundColor: '#262625', display: 'flex', flexDirection: 'column' }}
>
......
import React, { useEffect, useRef, useState } from 'react'
import { Box, Grid } from '@mui/material'
import { useTheme, type Theme } from '@mui/material/styles'
import useMediaQuery from '@mui/material/useMediaQuery'
import {
LocalVideoTrack,
RemoteUser,
useLocalCameraTrack,
useLocalMicrophoneTrack,
useRTCClient,
useRemoteUsers,
useClientEvent,
} from 'agora-rtc-react'
const MeetingGrid = () => {
const theme: Theme = useTheme()
const isSm = useMediaQuery(theme.breakpoints.up('sm'))
const isMd = useMediaQuery(theme.breakpoints.up('md'))
const isLg = useMediaQuery(theme.breakpoints.up('lg'))
const agoraEngine = useRTCClient()
const { localCameraTrack } = useLocalCameraTrack()
const { localMicrophoneTrack } = useLocalMicrophoneTrack()
const remoteUsers = useRemoteUsers()
useClientEvent(agoraEngine, 'user-joined', (user) => {
console.log('The user', user.uid, ' has joined the channel')
})
useClientEvent(agoraEngine, 'user-left', (user) => {
console.log('The user', user.uid, ' has left the channel')
})
useClientEvent(agoraEngine, 'user-published', (user, mediaType) => {
console.log('The user', user.uid, ' has published media in the channel')
})
const gridContainerRef = useRef<HTMLDivElement>(null)
const [gridContainerHeight, setGridContainerHeight] = useState(0)
const [totalUsers, setTotalUsers] = useState(20)
const [itemOffset, setItemOffset] = useState(12)
const [itemHeight, setItemHeight] = useState(230)
const [numOfItems, setNumOfItems] = useState(1)
const maxUsersDisplay = isLg ? 12 : isMd ? 9 : isSm ? 4 : 2
useEffect(() => {
setTotalUsers(remoteUsers.length + 1)
}, [remoteUsers])
useEffect(() => {
setNumOfItems(totalUsers > maxUsersDisplay ? maxUsersDisplay : totalUsers)
}, [totalUsers])
useEffect(() => {
if (gridContainerRef.current) {
setGridContainerHeight(gridContainerRef.current.offsetHeight)
}
}, [gridContainerRef?.current?.offsetHeight])
useEffect(() => {
switch (numOfItems) {
case 1:
setItemOffset(12)
setItemHeight(gridContainerHeight)
break
case 2:
setItemOffset(isSm ? 6 : 12)
setItemHeight(isSm ? gridContainerHeight : (gridContainerHeight - 16) / 2)
break
case 3:
setItemOffset(isMd ? 4 : isSm ? 6 : 12)
setItemHeight(
isMd
? gridContainerHeight
: isSm
? (gridContainerHeight - 16) / 2
: (gridContainerHeight - 32) / 3,
)
break
case 4:
setItemOffset(isSm ? 6 : 12)
setItemHeight(isSm ? (gridContainerHeight - 16) / 2 : (gridContainerHeight - 16 * 3) / 4)
break
case 5:
setItemOffset(isMd ? 4 : isSm ? 6 : 12)
setItemHeight(
isMd
? (gridContainerHeight - 16) / 2
: isSm
? (gridContainerHeight - 16 * 2) / 3
: (gridContainerHeight - 32 * 4) / 5,
)
break
case 6:
setItemOffset(isMd ? 4 : isSm ? 6 : 12)
setItemHeight(
isMd
? (gridContainerHeight - 16) / 2
: isSm
? (gridContainerHeight - 16 * 2) / 3
: (gridContainerHeight - 32 * 5) / 6,
)
break
case 7:
setItemOffset(isLg ? 3 : isMd ? 4 : isSm ? 6 : 12)
setItemHeight(
isLg
? (gridContainerHeight - 16) / 2
: isMd
? (gridContainerHeight - 16 * 2) / 3
: isSm
? (gridContainerHeight - 16 * 3) / 4
: (gridContainerHeight - 32 * 6) / 7,
)
break
case 8:
setItemOffset(isLg ? 3 : isMd ? 4 : isSm ? 6 : 12)
setItemHeight(
isLg
? (gridContainerHeight - 16) / 2
: isMd
? (gridContainerHeight - 16 * 2) / 3
: isSm
? (gridContainerHeight - 16 * 3) / 4
: (gridContainerHeight - 32 * 7) / 8,
)
break
case 9:
setItemOffset(isMd ? 4 : isSm ? 6 : 12)
setItemHeight(
isMd
? (gridContainerHeight - 16 * 2) / 3
: isSm
? (gridContainerHeight - 16 * 4) / 5
: (gridContainerHeight - 32 * 8) / 9,
)
break
default:
setItemOffset(isLg ? 3 : isMd ? 4 : isSm ? 6 : 12)
setItemHeight(
isLg ? (gridContainerHeight - 16 * 2) / 3 : (gridContainerHeight - 16 * 3) / 4,
)
}
}, [totalUsers, isSm, isMd, isLg, gridContainerHeight, numOfItems])
return (
<Box
sx={{
width: '100%',
height: '80%',
backgroundColor: theme.palette.background.default,
padding: '30px',
display: 'flex',
flexDirection: 'column',
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
width: '100%',
height: '100%',
}}
ref={gridContainerRef}
>
<Box sx={{ display: 'flex', width: '100%' }}>
<Grid container spacing={3} width={'100%'} padding={0}>
<Grid item xs={itemOffset}>
<Box
sx={{
backgroundColor: '#262625',
height: `${itemHeight}px`,
borderRadius: '15px',
}}
>
<LocalVideoTrack track={localCameraTrack} play={true} />
</Box>
</Grid>
{remoteUsers.map((remoteUser, index) => (
<Grid item xs={itemOffset} key={index}>
<Box
sx={{
backgroundColor: '#262625',
height: `${itemHeight}px`,
borderRadius: '15px',
}}
>
<RemoteUser user={remoteUser} playVideo={true} playAudio={true} />
</Box>
</Grid>
))}
</Grid>
</Box>
</Box>
</Box>
)
}
export default MeetingGrid
import {
LocalVideoTrack,
RemoteUser,
useJoin,
useLocalCameraTrack,
useLocalMicrophoneTrack,
usePublish,
useRTCClient,
useRemoteUsers,
useClientEvent,
} from 'agora-rtc-react'
import { useJoin, useLocalCameraTrack, useLocalMicrophoneTrack } from 'agora-rtc-react'
import React, { createContext, useContext, useEffect } from 'react'
import type { IMicrophoneAudioTrack, ICameraVideoTrack } from 'agora-rtc-sdk-ng'
import { Box } from '@mui/material'
import { useTheme, type Theme } from '@mui/material/styles'
import MeetingLoading from '../../Components/MeetingLoading/MeetingLoading'
import MeetingGrid from '../../Components/MeetingGrid/MeetingGrid'
interface AgoraContextType {
localCameraTrack: ICameraVideoTrack | null
......@@ -42,7 +33,6 @@ export const useAgoraContext = () => {
export const AgoraManager = ({ children }: { children: React.ReactNode }) => {
const theme: Theme = useTheme()
const agoraEngine = useRTCClient()
const {
data: uid,
......@@ -57,21 +47,6 @@ export const AgoraManager = ({ children }: { children: React.ReactNode }) => {
})
const { isLoading: isLoadingCam, localCameraTrack } = useLocalCameraTrack()
const { isLoading: isLoadingMic, localMicrophoneTrack } = useLocalMicrophoneTrack()
const remoteUsers = useRemoteUsers()
usePublish([localMicrophoneTrack, localCameraTrack])
useClientEvent(agoraEngine, 'user-joined', (user) => {
console.log('The user', user.uid, ' has joined the channel')
})
useClientEvent(agoraEngine, 'user-left', (user) => {
console.log('The user', user.uid, ' has left the channel')
})
useClientEvent(agoraEngine, 'user-published', (user, mediaType) => {
console.log('The user', user.uid, ' has published media in the channel')
})
useEffect(() => {
return () => {
......@@ -81,7 +56,14 @@ export const AgoraManager = ({ children }: { children: React.ReactNode }) => {
}, [])
return (
<Box sx={{ width: '100%', height: '100%', backgroundColor: theme.palette.background.default }}>
<Box
sx={{
width: '100%',
height: '100%',
backgroundColor: theme.palette.background.default,
display: 'flex',
}}
>
{isJoining ? (
<MeetingLoading variant='joining' />
) : isLoadingCam || isLoadingMic ? (
......@@ -91,19 +73,7 @@ export const AgoraManager = ({ children }: { children: React.ReactNode }) => {
localCameraTrack={localCameraTrack}
localMicrophoneTrack={localMicrophoneTrack}
>
{children}
<div id='videos'>
{/* Render the local video track */}
<div className='vid' style={{ height: 300, width: 600 }}>
<LocalVideoTrack track={localCameraTrack} play={true} />
</div>
{/* Render remote users' video and audio tracks */}
{remoteUsers.map((remoteUser) => (
<div className='vid' style={{ height: 300, width: 600 }} key={remoteUser.uid}>
<RemoteUser user={remoteUser} playVideo={true} playAudio={true} />
</div>
))}
</div>
<MeetingGrid />
</AgoraProvider>
) : joinError ? (
<MeetingLoading variant='error' />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment