Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
SpeakEzy_Frontend
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Thisara Kavinda
SpeakEzy_Frontend
Commits
52f997c5
Commit
52f997c5
authored
Mar 15, 2024
by
Thisara Kavinda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: implemented MeetingGrid
parent
37f6fb5d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
213 additions
and
42 deletions
+213
-42
src/Components/Lobby/Lobby.tsx
src/Components/Lobby/Lobby.tsx
+1
-1
src/Components/MeetingGrid/MeetingGrid.tsx
src/Components/MeetingGrid/MeetingGrid.tsx
+201
-0
src/Services/AgoraManager/AgoraManager.tsx
src/Services/AgoraManager/AgoraManager.tsx
+11
-41
No files found.
src/Components/Lobby/Lobby.tsx
View file @
52f997c5
...
...
@@ -32,7 +32,7 @@ const Lobby = ({ handleJoinClick }: Props) => {
}
}
>
<
Box
width=
{
'
40
%
'
}
width=
{
'
35
%
'
}
borderRadius=
{
'
20px
'
}
sx=
{
{
backgroundColor
:
'
#262625
'
,
display
:
'
flex
'
,
flexDirection
:
'
column
'
}
}
>
...
...
src/Components/MeetingGrid/MeetingGrid.tsx
0 → 100644
View file @
52f997c5
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
src/Services/AgoraManager/AgoraManager.tsx
View file @
52f997c5
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'
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment