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
6f5da362
Commit
6f5da362
authored
Mar 16, 2024
by
Thisara Kavinda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: implemented control buttons
parent
e6ce68d9
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
274 additions
and
29 deletions
+274
-29
src/Components/ControlCenter/ControlCenter.tsx
src/Components/ControlCenter/ControlCenter.tsx
+91
-0
src/Components/ControlsButtonGroup/ControlsButtonGroup.tsx
src/Components/ControlsButtonGroup/ControlsButtonGroup.tsx
+124
-0
src/Components/MeetingLayout/MeetingLayout.tsx
src/Components/MeetingLayout/MeetingLayout.tsx
+26
-14
src/Components/PinnedGrid/PinnedGrid.tsx
src/Components/PinnedGrid/PinnedGrid.tsx
+4
-1
src/Components/SymmetricGrid/SymmetricGrid.tsx
src/Components/SymmetricGrid/SymmetricGrid.tsx
+4
-1
src/Components/UserCard/UserCard.tsx
src/Components/UserCard/UserCard.tsx
+11
-4
src/Pages/VideoCall/VideoCall.tsx
src/Pages/VideoCall/VideoCall.tsx
+1
-5
src/Services/AgoraManager/AgoraManager.tsx
src/Services/AgoraManager/AgoraManager.tsx
+13
-4
No files found.
src/Components/ControlCenter/ControlCenter.tsx
0 → 100644
View file @
6f5da362
import
{
Box
,
Typography
}
from
'
@mui/material
'
import
{
useTheme
,
type
Theme
}
from
'
@mui/material/styles
'
import
ControlsButtonGroup
from
'
../ControlsButtonGroup/ControlsButtonGroup
'
import
type
{
IMicrophoneAudioTrack
,
ICameraVideoTrack
}
from
'
agora-rtc-sdk-ng
'
import
React
,
{
useEffect
}
from
'
react
'
interface
Props
{
setJoined
:
(
x
:
boolean
)
=>
void
localCameraTrack
:
ICameraVideoTrack
|
null
localMicrophoneTrack
:
IMicrophoneAudioTrack
|
null
}
const
ControlCenter
=
({
setJoined
,
localCameraTrack
,
localMicrophoneTrack
}:
Props
)
=>
{
const
theme
:
Theme
=
useTheme
()
const
[
currentTime
,
setCurrentTime
]
=
React
.
useState
(
new
Date
())
const
updateTime
=
()
=>
{
setCurrentTime
(
new
Date
())
}
useEffect
(()
=>
{
const
interval
=
setInterval
(
updateTime
,
6000
)
return
()
=>
clearInterval
(
interval
)
},
[])
return
(
<
Box
sx=
{
{
height
:
'
100%
'
,
width
:
'
100%
'
,
display
:
'
flex
'
,
flexDirection
:
'
row
'
,
justifyContent
:
'
space-between
'
,
alignItems
:
'
center
'
,
}
}
>
<
Box
sx=
{
{
width
:
'
20%
'
,
paddingLeft
:
'
0px
'
,
alignItems
:
'
center
'
,
justifyContent
:
'
flex-start
'
,
textAlign
:
'
left
'
,
}
}
>
<
Typography
sx=
{
{
fontSize
:
'
18px
'
,
color
:
theme
.
palette
.
common
.
white
,
fontWeight
:
600
,
textAlign
:
'
left
'
,
paddingLeft
:
'
50px
'
,
}
}
>
{
currentTime
.
toLocaleTimeString
(
'
en-US
'
,
{
hour
:
'
2-digit
'
,
minute
:
'
2-digit
'
,
hour12
:
true
,
})
}
</
Typography
>
</
Box
>
<
Box
sx=
{
{
display
:
'
flex
'
,
flexDirection
:
'
row
'
,
justifyContent
:
'
center
'
,
alignItems
:
'
center
'
,
}
}
>
<
ControlsButtonGroup
setJoined=
{
setJoined
}
localCameraTrack=
{
localCameraTrack
}
localMicrophoneTrack=
{
localMicrophoneTrack
}
/>
</
Box
>
<
Box
sx=
{
{
width
:
'
20%
'
,
display
:
'
flex
'
,
flexDirection
:
'
row
'
,
justifyContent
:
'
flex-end
'
,
paddingRight
:
'
50px
'
,
alignItems
:
'
center
'
,
}
}
></
Box
>
</
Box
>
)
}
export
default
ControlCenter
src/Components/ControlsButtonGroup/ControlsButtonGroup.tsx
0 → 100644
View file @
6f5da362
import
React
,
{
useState
}
from
'
react
'
import
type
{
IMicrophoneAudioTrack
,
ICameraVideoTrack
}
from
'
agora-rtc-sdk-ng
'
import
{
Box
,
IconButton
}
from
'
@mui/material
'
import
MicIcon
from
'
@mui/icons-material/Mic
'
import
VideocamIcon
from
'
@mui/icons-material/Videocam
'
import
{
useTheme
,
type
Theme
}
from
'
@mui/material/styles
'
import
ClosedCaptionIcon
from
'
@mui/icons-material/ClosedCaption
'
import
PresentToAllIcon
from
'
@mui/icons-material/PresentToAll
'
import
MicOffIcon
from
'
@mui/icons-material/MicOff
'
import
CallEndIcon
from
'
@mui/icons-material/CallEnd
'
import
VideocamOffIcon
from
'
@mui/icons-material/VideocamOff
'
interface
Props
{
setJoined
:
(
x
:
boolean
)
=>
void
localCameraTrack
:
ICameraVideoTrack
|
null
localMicrophoneTrack
:
IMicrophoneAudioTrack
|
null
}
const
ControlsButtonGroup
=
({
setJoined
,
localCameraTrack
,
localMicrophoneTrack
}:
Props
)
=>
{
const
theme
:
Theme
=
useTheme
()
const
[
isAudioEnable
,
setIsAudioEnable
]
=
useState
(
localMicrophoneTrack
?.
enabled
)
const
[
isVideoEnabled
,
setIsVideoEnabled
]
=
useState
(
localCameraTrack
?.
enabled
)
const
toogleAudio
=
async
()
=>
{
if
(
isAudioEnable
)
{
await
localMicrophoneTrack
?.
setEnabled
(
false
)
setIsAudioEnable
(
false
)
}
else
{
await
localMicrophoneTrack
?.
setEnabled
(
true
)
setIsAudioEnable
(
true
)
}
}
const
toogleVideo
=
async
()
=>
{
if
(
isVideoEnabled
)
{
await
localCameraTrack
?.
setEnabled
(
false
)
setIsVideoEnabled
(
false
)
}
else
{
await
localCameraTrack
?.
setEnabled
(
true
)
setIsVideoEnabled
(
true
)
}
}
const
handleLeaveCall
=
()
=>
{
localCameraTrack
?.
close
()
localMicrophoneTrack
?.
close
()
setJoined
(
false
)
}
return
(
<
Box
sx=
{
{
height
:
'
100%
'
,
width
:
'
100%
'
}
}
>
<
IconButton
sx=
{
{
borderRadius
:
'
50%
'
,
padding
:
'
15px
'
,
marginX
:
'
15px
'
,
backgroundColor
:
isAudioEnable
?
'
green
'
:
'
#363739
'
,
'
&:hover
'
:
{
backgroundColor
:
isAudioEnable
?
'
green
'
:
'
#363739
'
},
}
}
onClick=
{
toogleAudio
}
>
{
isAudioEnable
?
(
<
MicIcon
sx=
{
{
color
:
theme
.
palette
.
common
.
white
}
}
/>
)
:
(
<
MicOffIcon
sx=
{
{
color
:
theme
.
palette
.
common
.
white
}
}
/>
)
}
</
IconButton
>
<
IconButton
sx=
{
{
borderRadius
:
'
50%
'
,
padding
:
'
15px
'
,
marginX
:
'
15px
'
,
backgroundColor
:
isVideoEnabled
?
'
green
'
:
'
#363739
'
,
'
&:hover
'
:
{
backgroundColor
:
isVideoEnabled
?
'
green
'
:
'
#363739
'
},
}
}
onClick=
{
toogleVideo
}
>
{
isVideoEnabled
?
(
<
VideocamIcon
sx=
{
{
color
:
theme
.
palette
.
common
.
white
}
}
/>
)
:
(
<
VideocamOffIcon
sx=
{
{
color
:
theme
.
palette
.
common
.
white
}
}
/>
)
}
</
IconButton
>
<
IconButton
sx=
{
{
borderRadius
:
'
50%
'
,
padding
:
'
15px
'
,
marginX
:
'
15px
'
,
backgroundColor
:
'
#363739
'
,
'
&:hover
'
:
{
backgroundColor
:
'
#363739
'
},
}
}
>
<
ClosedCaptionIcon
sx=
{
{
color
:
theme
.
palette
.
common
.
white
}
}
/>
</
IconButton
>
<
IconButton
sx=
{
{
borderRadius
:
'
50%
'
,
padding
:
'
15px
'
,
marginX
:
'
15px
'
,
backgroundColor
:
'
#363739
'
,
'
&:hover
'
:
{
backgroundColor
:
'
#363739
'
},
}
}
>
<
PresentToAllIcon
sx=
{
{
color
:
theme
.
palette
.
common
.
white
}
}
/>
</
IconButton
>
<
IconButton
sx=
{
{
borderRadius
:
'
40%
'
,
padding
:
'
15px
'
,
paddingX
:
'
25px
'
,
marginX
:
'
15px
'
,
backgroundColor
:
'
red
'
,
'
&:hover
'
:
{
backgroundColor
:
'
red
'
},
}
}
onClick=
{
handleLeaveCall
}
>
<
CallEndIcon
sx=
{
{
color
:
theme
.
palette
.
common
.
white
}
}
/>
</
IconButton
>
</
Box
>
)
}
export
default
ControlsButtonGroup
src/Components/MeetingLayout/MeetingLayout.tsx
View file @
6f5da362
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'
react
'
import
{
Box
}
from
'
@mui/material
'
import
{
useTheme
,
type
Theme
}
from
'
@mui/material/styles
'
import
{
useLocalCameraTrack
,
useLocalMicrophoneTrack
,
useRemoteUsers
,
usePublish
,
useRTCClient
,
useClientEvent
,
}
from
'
agora-rtc-react
'
import
{
useRemoteUsers
,
usePublish
,
useRTCClient
,
useClientEvent
}
from
'
agora-rtc-react
'
import
SymmetricGrid
from
'
../SymmetricGrid/SymmetricGrid
'
import
PinnedGrid
from
'
../PinnedGrid/PinnedGrid
'
import
type
{
IAgoraRTCRemoteUser
}
from
'
agora-rtc-sdk-ng
'
import
type
{
IAgoraRTCRemoteUser
,
ICameraVideoTrack
,
IMicrophoneAudioTrack
,
}
from
'
agora-rtc-sdk-ng
'
import
ControlCenter
from
'
../ControlCenter/ControlCenter
'
const
MeetingLayout
=
()
=>
{
interface
Props
{
setJoined
:
(
x
:
boolean
)
=>
void
localCameraTrack
:
ICameraVideoTrack
|
null
localMicrophoneTrack
:
IMicrophoneAudioTrack
|
null
}
const
MeetingLayout
=
({
setJoined
,
localCameraTrack
,
localMicrophoneTrack
}:
Props
)
=>
{
const
theme
:
Theme
=
useTheme
()
const
agoraEngine
=
useRTCClient
()
const
{
localCameraTrack
}
=
useLocalCameraTrack
()
const
{
localMicrophoneTrack
}
=
useLocalMicrophoneTrack
()
usePublish
([
localMicrophoneTrack
,
localCameraTrack
])
const
remoteUsers
:
IAgoraRTCRemoteUser
[]
=
useRemoteUsers
()
...
...
@@ -52,11 +54,12 @@ const MeetingLayout = () => {
<
Box
sx=
{
{
width
:
'
100%
'
,
height
:
'
8
0%
'
,
height
:
'
10
0%
'
,
backgroundColor
:
theme
.
palette
.
background
.
default
,
padding
:
'
30px
'
,
display
:
'
flex
'
,
flexDirection
:
'
column
'
,
justifyContent
:
'
space-between
'
,
}
}
>
<
Box
...
...
@@ -64,7 +67,7 @@ const MeetingLayout = () => {
display
:
'
flex
'
,
flexDirection
:
'
row
'
,
width
:
'
100%
'
,
height
:
'
10
0%
'
,
height
:
'
8
0%
'
,
}
}
ref=
{
gridContainerRef
}
>
...
...
@@ -75,6 +78,7 @@ const MeetingLayout = () => {
setIsPinned=
{
setIsPinned
}
pinnedUser=
{
pinnedUser
}
setPinnedUser=
{
setPinnedUser
}
localCameraTrack=
{
localCameraTrack
}
/>
)
:
(
<
SymmetricGrid
...
...
@@ -83,9 +87,17 @@ const MeetingLayout = () => {
isPinned=
{
isPinned
}
setIsPinned=
{
setIsPinned
}
setPinnedUser=
{
setPinnedUser
}
localCameraTrack=
{
localCameraTrack
}
/>
)
}
</
Box
>
<
Box
sx=
{
{
height
:
'
10%
'
,
width
:
'
100%
'
,
display
:
'
flex
'
,
marginBottom
:
'
40px
'
}
}
>
<
ControlCenter
setJoined=
{
setJoined
}
localCameraTrack=
{
localCameraTrack
}
localMicrophoneTrack=
{
localMicrophoneTrack
}
/>
</
Box
>
</
Box
>
)
}
...
...
src/Components/PinnedGrid/PinnedGrid.tsx
View file @
6f5da362
import
React
,
{
useEffect
}
from
'
react
'
import
type
{
IAgoraRTCRemoteUser
}
from
'
agora-rtc-sdk-ng
'
import
type
{
IAgoraRTCRemoteUser
,
ICameraVideoTrack
}
from
'
agora-rtc-sdk-ng
'
import
{
Box
,
Button
,
IconButton
,
Popover
,
Stack
}
from
'
@mui/material
'
import
useMediaQuery
from
'
@mui/material/useMediaQuery
'
import
{
RemoteUser
,
useRemoteUsers
}
from
'
agora-rtc-react
'
...
...
@@ -13,6 +13,7 @@ interface Props {
setIsPinned
:
(
value
:
boolean
)
=>
void
pinnedUser
:
IAgoraRTCRemoteUser
setPinnedUser
:
(
value
:
IAgoraRTCRemoteUser
|
null
)
=>
void
localCameraTrack
:
ICameraVideoTrack
|
null
}
const
PinnedGrid
=
({
...
...
@@ -21,6 +22,7 @@ const PinnedGrid = ({
setIsPinned
,
pinnedUser
,
setPinnedUser
,
localCameraTrack
,
}:
Props
)
=>
{
const
theme
:
Theme
=
useTheme
()
const
isSm
=
useMediaQuery
(
theme
.
breakpoints
.
up
(
'
sm
'
))
...
...
@@ -144,6 +146,7 @@ const PinnedGrid = ({
itemHeight=
{
itemHeight
}
setIsPinned=
{
setIsPinned
}
setPinnedUser=
{
setPinnedUser
}
localCameraTrack=
{
localCameraTrack
}
/>
{
remoteUsers
.
length
>
1
&&
remoteUsers
...
...
src/Components/SymmetricGrid/SymmetricGrid.tsx
View file @
6f5da362
...
...
@@ -3,7 +3,7 @@ import { Box, Grid } from '@mui/material'
import
useMediaQuery
from
'
@mui/material/useMediaQuery
'
import
{
useRemoteUsers
}
from
'
agora-rtc-react
'
import
{
useTheme
,
type
Theme
}
from
'
@mui/material/styles
'
import
type
{
IAgoraRTCRemoteUser
}
from
'
agora-rtc-sdk-ng
'
import
type
{
IAgoraRTCRemoteUser
,
ICameraVideoTrack
}
from
'
agora-rtc-sdk-ng
'
import
UserCard
from
'
../UserCard/UserCard
'
interface
Props
{
...
...
@@ -12,6 +12,7 @@ interface Props {
isPinned
:
boolean
setIsPinned
:
(
value
:
boolean
)
=>
void
setPinnedUser
:
(
value
:
IAgoraRTCRemoteUser
|
null
)
=>
void
localCameraTrack
:
ICameraVideoTrack
|
null
}
const
SymmetricGrid
=
({
...
...
@@ -20,6 +21,7 @@ const SymmetricGrid = ({
isPinned
,
setIsPinned
,
setPinnedUser
,
localCameraTrack
,
}:
Props
)
=>
{
const
theme
:
Theme
=
useTheme
()
const
isSm
=
useMediaQuery
(
theme
.
breakpoints
.
up
(
'
sm
'
))
...
...
@@ -133,6 +135,7 @@ const SymmetricGrid = ({
itemHeight=
{
itemHeight
}
setIsPinned=
{
setIsPinned
}
setPinnedUser=
{
setPinnedUser
}
localCameraTrack=
{
localCameraTrack
}
/>
</
Grid
>
{
remoteUsers
.
map
((
remoteUser
,
index
)
=>
(
...
...
src/Components/UserCard/UserCard.tsx
View file @
6f5da362
import
{
Box
,
Button
,
IconButton
,
Popover
}
from
'
@mui/material
'
import
MoreVertIcon
from
'
@mui/icons-material/MoreVert
'
import
{
LocalVideoTrack
,
RemoteUser
,
useLocalCameraTrack
}
from
'
agora-rtc-react
'
import
type
{
IAgoraRTCRemoteUser
}
from
'
agora-rtc-sdk-ng
'
import
{
LocalVideoTrack
,
RemoteUser
}
from
'
agora-rtc-react
'
import
type
{
IAgoraRTCRemoteUser
,
ICameraVideoTrack
}
from
'
agora-rtc-sdk-ng
'
import
{
useTheme
,
type
Theme
}
from
'
@mui/material/styles
'
import
React
,
{
useEffect
}
from
'
react
'
...
...
@@ -11,11 +11,18 @@ interface Props {
setIsPinned
:
(
value
:
boolean
)
=>
void
setPinnedUser
:
(
value
:
IAgoraRTCRemoteUser
|
null
)
=>
void
remoteUser
?:
IAgoraRTCRemoteUser
localCameraTrack
?:
ICameraVideoTrack
|
null
}
const
UserCard
=
({
type
,
remoteUser
,
itemHeight
,
setIsPinned
,
setPinnedUser
}:
Props
)
=>
{
const
UserCard
=
({
type
,
remoteUser
,
itemHeight
,
setIsPinned
,
setPinnedUser
,
localCameraTrack
,
}:
Props
)
=>
{
const
theme
:
Theme
=
useTheme
()
const
{
localCameraTrack
}
=
useLocalCameraTrack
()
const
[
anchorEl
,
setAnchorEl
]
=
React
.
useState
<
HTMLButtonElement
|
null
>
(
null
)
...
...
src/Pages/VideoCall/VideoCall.tsx
View file @
6f5da362
...
...
@@ -13,15 +13,11 @@ const VideoCall = () => {
setJoined
(
true
)
}
// const handleLeaveClick = () => {
// setJoined(false)
// }
return
(
<
Box
sx=
{
{
height
:
'
100vh
'
,
width
:
'
100vw
'
,
overflow
:
'
hidden
'
}
}
>
{
joined
?
(
<
AgoraRTCProvider
client=
{
agoraEngine
}
>
<
AgoraManager
>
<
AgoraManager
setJoined=
{
setJoined
}
>
<
div
>
asas
</
div
>
</
AgoraManager
>
</
AgoraRTCProvider
>
...
...
src/Services/AgoraManager/AgoraManager.tsx
View file @
6f5da362
import
{
useJoin
,
useLocalCameraTrack
,
useLocalMicrophoneTrack
}
from
'
agora-rtc-react
'
import
React
,
{
createContext
,
useContext
,
useEffect
}
from
'
react
'
import
{
useJoin
,
useLocalCameraTrack
,
useLocalMicrophoneTrack
}
from
'
agora-rtc-react
'
import
type
{
IMicrophoneAudioTrack
,
ICameraVideoTrack
}
from
'
agora-rtc-sdk-ng
'
import
{
Box
}
from
'
@mui/material
'
import
{
useTheme
,
type
Theme
}
from
'
@mui/material/styles
'
...
...
@@ -31,7 +30,13 @@ export const useAgoraContext = () => {
return
context
}
export
const
AgoraManager
=
({
children
}:
{
children
:
React
.
ReactNode
})
=>
{
export
const
AgoraManager
=
({
setJoined
,
children
,
}:
{
setJoined
:
(
x
:
boolean
)
=>
void
children
:
React
.
ReactNode
})
=>
{
const
theme
:
Theme
=
useTheme
()
const
{
...
...
@@ -73,7 +78,11 @@ export const AgoraManager = ({ children }: { children: React.ReactNode }) => {
localCameraTrack=
{
localCameraTrack
}
localMicrophoneTrack=
{
localMicrophoneTrack
}
>
<
MeetingLayout
/>
<
MeetingLayout
setJoined=
{
setJoined
}
localCameraTrack=
{
localCameraTrack
}
localMicrophoneTrack=
{
localMicrophoneTrack
}
/>
</
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