-
Notifications
You must be signed in to change notification settings - Fork 737
Ahoyapps 46 dominant speaker area #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
02f0847
84b25a1
e4d5bca
5647e64
4536f5c
ac1b772
8c95bb6
4b946c0
f7e44b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,33 @@ | ||
| import React from 'react'; | ||
| import ParticipantStrip from '../ParticipantStrip/ParticipantStrip'; | ||
| import { styled } from '@material-ui/core/styles'; | ||
| import useMainSpeaker from '../../hooks/useMainSpeaker/useMainSpeaker'; | ||
| import Participant from '../Participant/Participant'; | ||
|
|
||
| const Container = styled('div')({ | ||
| position: 'relative', | ||
| height: '100%', | ||
| }); | ||
|
|
||
| const MainParticipantContainer = styled('div')(({ theme }) => ({ | ||
| position: 'absolute', | ||
| left: theme.sidebarPosition, | ||
| right: 0, | ||
| top: 0, | ||
| bottom: 0, | ||
| '& > div': { | ||
| height: '100%', | ||
| }, | ||
| })); | ||
|
|
||
| export default function Room() { | ||
| const mainParticipant = useMainSpeaker(); | ||
| return ( | ||
| <Container> | ||
| <ParticipantStrip /> | ||
| <MainParticipantContainer> | ||
| <Participant participant={mainParticipant} disableAudio /> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is audio disabled by default in VBT?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. Can you add a comment on this line and put what you just said? |
||
| </MainParticipantContainer> | ||
| </Container> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { act, renderHook } from '@testing-library/react-hooks'; | ||
| import EventEmitter from 'events'; | ||
| import useDominantSpeaker from './useDominantSpeaker'; | ||
| import { useVideoContext } from '../context'; | ||
|
|
||
| jest.mock('../context'); | ||
| const mockUseVideoContext = useVideoContext as jest.Mock<any>; | ||
|
|
||
| describe('the useDominantSpeaker hook', () => { | ||
| const mockRoom: any = new EventEmitter(); | ||
| mockRoom.dominantSpeaker = 'mockDominantSpeaker'; | ||
| mockUseVideoContext.mockImplementation(() => ({ room: mockRoom })); | ||
|
|
||
| it('should return room.dominantSpeaker by default', () => { | ||
| const { result } = renderHook(useDominantSpeaker); | ||
| expect(result.current).toBe('mockDominantSpeaker'); | ||
| }); | ||
|
|
||
| it('should return respond to "dominantSpeakerChanged" events', async () => { | ||
| const { result } = renderHook(useDominantSpeaker); | ||
| act(() => { | ||
| mockRoom.emit('dominantSpeakerChanged', 'newDominantSpeaker'); | ||
| }); | ||
| expect(result.current).toBe('newDominantSpeaker'); | ||
| }); | ||
|
|
||
| it('should clean up listeners on unmount', () => { | ||
| const { unmount } = renderHook(useDominantSpeaker); | ||
| unmount(); | ||
| expect(mockRoom.listenerCount('dominantSpeakerChanged')).toBe(0); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import { useEffect, useState } from 'react'; | ||
| import { useVideoContext } from '../context'; | ||
|
|
||
| export default function useDominantSpeaker() { | ||
| const { room } = useVideoContext(); | ||
| const [dominantSpeaker, setDominantSpeaker] = useState(room.dominantSpeaker); | ||
|
|
||
| useEffect(() => { | ||
| room.on('dominantSpeakerChanged', setDominantSpeaker); | ||
| return () => { | ||
| room.off('dominantSpeakerChanged', setDominantSpeaker); | ||
| }; | ||
| }, [room]); | ||
|
|
||
| return dominantSpeaker; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import useMainSpeaker from './useMainSpeaker'; | ||
| import { renderHook } from '@testing-library/react-hooks'; | ||
| import { useVideoContext } from '../context'; | ||
| import { EventEmitter } from 'events'; | ||
|
|
||
| jest.mock('../context'); | ||
| const mockUseVideoContext = useVideoContext as jest.Mock<any>; | ||
|
|
||
| describe('the useMainSpeaker hook', () => { | ||
| it('should return the dominant speaker if it exists', () => { | ||
| const mockRoom: any = new EventEmitter(); | ||
| mockRoom.dominantSpeaker = 'dominantSpeaker'; | ||
| mockRoom.participants = new Map([[0, 'participant']]) as any; | ||
| mockRoom.localParticipant = 'localParticipant'; | ||
| mockUseVideoContext.mockImplementation(() => ({ room: mockRoom })); | ||
| const { result } = renderHook(useMainSpeaker); | ||
| expect(result.current).toBe('dominantSpeaker'); | ||
| }); | ||
|
|
||
| it('should return the first remote participant if it exists', () => { | ||
| const mockRoom: any = new EventEmitter(); | ||
| mockRoom.dominantSpeaker = null; | ||
| mockRoom.participants = new Map([ | ||
| [0, 'participant'], | ||
| [1, 'secondParticipant'], | ||
| ]) as any; | ||
| mockRoom.localParticipant = 'localParticipant'; | ||
| mockUseVideoContext.mockImplementation(() => ({ room: mockRoom })); | ||
| const { result } = renderHook(useMainSpeaker); | ||
| expect(result.current).toBe('participant'); | ||
| }); | ||
|
|
||
| it('should return the local participant if it exists', () => { | ||
| const mockRoom: any = new EventEmitter(); | ||
| mockRoom.dominantSpeaker = null; | ||
| mockRoom.participants = new Map() as any; | ||
| mockRoom.localParticipant = 'localParticipant'; | ||
| mockUseVideoContext.mockImplementation(() => ({ room: mockRoom })); | ||
| const { result } = renderHook(useMainSpeaker); | ||
| expect(result.current).toBe('localParticipant'); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { useVideoContext } from '../context'; | ||
| import useDominantSpeaker from '../useDominantSpeaker/useDominantSpeaker'; | ||
| import useParticipants from '../useParticipants/useParticipants'; | ||
|
|
||
| export default function useMainSpeaker() { | ||
| const { room } = useVideoContext(); | ||
| const participants = useParticipants(); | ||
| const dominantSpeaker = useDominantSpeaker(); | ||
|
|
||
| return dominantSpeaker || participants[0] || room.localParticipant; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,22 @@ | ||
| import { createMuiTheme } from '@material-ui/core'; | ||
|
|
||
| declare module '@material-ui/core/styles/createMuiTheme' { | ||
| interface Theme { | ||
| sidebarPosition: string; | ||
| } | ||
|
|
||
| // allow configuration using `createMuiTheme` | ||
| interface ThemeOptions { | ||
| sidebarPosition?: string; | ||
| } | ||
| } | ||
|
|
||
| export default createMuiTheme({ | ||
| palette: { | ||
| type: 'dark', | ||
| primary: { | ||
| main: '#cc2b33', | ||
| }, | ||
| }, | ||
| sidebarPosition: '15%', | ||
| }); |
Uh oh!
There was an error while loading. Please reload this page.