Skip to content

Commit fbde556

Browse files
authored
VIDSOL-28: On the participants list, on muting the publisher the muted icon is not displayed (#211)
1 parent c3e958b commit fbde556

File tree

3 files changed

+58
-3
lines changed

3 files changed

+58
-3
lines changed

docs/KNOWN_ISSUES.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Known Issues
22
- `VIDSOL-32`: When using an iPhone camera as your video input device, disconnecting your iPhone camera may cause your video to freeze and the video input may not automatically switch.
3-
- `VIDSOL-28`: The publisher does not display a muted icon in the participant list when their audio is muted.
43
- `VIDSOL-5`: Subscriber videos may be disabled without warning.
54
- `VIDSOL-19`: The maximum number of displayed users is 10, even when the screen can accommodate more.
65
- `VIDSOL-127`: New video input devices added to the user's machine do not prompt the user to switch devices.

frontend/src/components/MeetingRoom/ParticipantList/ParticipantList.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { SubscriberWrapper } from '../../../types/session';
1111
import getParticipantColor from '../../../utils/getParticipantColor';
1212
import useRoomShareUrl from '../../../hooks/useRoomShareUrl';
1313
import RightPanelTitle from '../RightPanel/RightPanelTitle';
14+
import usePublisherContext from '../../../hooks/usePublisherContext';
1415

1516
const compareNameAlphabetically = (a: SubscriberWrapper, b: SubscriberWrapper) => {
1617
const nameA = a.subscriber?.stream?.name;
@@ -49,6 +50,8 @@ const ParticipantList = ({ handleClose, isOpen }: ParticipantListProps): ReactEl
4950
},
5051
} = useUserContext();
5152
const roomShareUrl = useRoomShareUrl();
53+
const { isAudioEnabled } = usePublisherContext();
54+
5255
const copyUrl = () => {
5356
navigator.clipboard.writeText(roomShareUrl);
5457

@@ -90,7 +93,8 @@ const ParticipantList = ({ handleClose, isOpen }: ParticipantListProps): ReactEl
9093
<ParticipantListItem
9194
key="you"
9295
dataTestId="participant-list-item-you"
93-
audioLevel={publisherAudio}
96+
hasAudio={isAudioEnabled}
97+
audioLevel={isAudioEnabled ? publisherAudio : undefined}
9498
name={`${name} (You)`}
9599
initials={getInitials(name)}
96100
avatarColor={getParticipantColor(name)}

frontend/src/components/MeetingRoom/ParticipantListItem/ParticipantListItem.spec.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
import { describe, expect, it } from 'vitest';
1+
import { describe, expect, it, beforeEach, vi, Mock } from 'vitest';
22
import { render, screen } from '@testing-library/react';
33
import { Stream } from '@vonage/client-sdk-video';
44
import ParticipantListItem, { ParticipantListItemProps } from './ParticipantListItem';
5+
import useAudioLevels from '../../../hooks/useAudioLevels';
6+
import usePublisherContext from '../../../hooks/usePublisherContext';
7+
import { PublisherContextType } from '../../../Context/PublisherProvider';
8+
9+
vi.mock('../../../hooks/useAudioLevels');
10+
vi.mock('../../../hooks/usePublisherContext');
11+
12+
const mockUseAudioLevels = useAudioLevels as Mock<[], number | undefined>;
13+
const mockUsePublisherContext = usePublisherContext as Mock<[], PublisherContextType>;
514

615
describe('ParticipantListItem', () => {
716
const mockStream: Stream = {
@@ -72,4 +81,47 @@ describe('ParticipantListItem', () => {
7281
fontSize: '14px',
7382
});
7483
});
84+
85+
describe('Publisher audio state handling', () => {
86+
let publisherContext: PublisherContextType;
87+
beforeEach(() => {
88+
publisherContext = {
89+
isAudioEnabled: true,
90+
} as unknown as PublisherContextType;
91+
mockUsePublisherContext.mockImplementation(() => publisherContext);
92+
mockUseAudioLevels.mockReturnValue(50);
93+
});
94+
95+
it('shows active audio state for publisher when microphone is enabled', () => {
96+
mockUsePublisherContext.mockImplementation(() => ({
97+
...publisherContext,
98+
isAudioEnabled: true,
99+
}));
100+
mockUseAudioLevels.mockReturnValue(75);
101+
102+
render(<ParticipantListItem {...defaultProps} audioLevel={undefined} hasAudio />);
103+
104+
const participantItem = screen.getByTestId('participant-list-item');
105+
expect(participantItem).toBeInTheDocument();
106+
107+
const audioIndicator = screen.getByTestId('audio-indicator');
108+
expect(audioIndicator).toBeInTheDocument();
109+
110+
const micIcon = screen.getByTestId('MicIcon');
111+
expect(micIcon).toBeInTheDocument();
112+
});
113+
114+
it('shows muted state when hasAudio is false', () => {
115+
render(<ParticipantListItem {...defaultProps} audioLevel={undefined} hasAudio={false} />);
116+
117+
const participantItem = screen.getByTestId('participant-list-item');
118+
expect(participantItem).toBeInTheDocument();
119+
120+
const audioIndicator = screen.getByTestId('audio-indicator');
121+
expect(audioIndicator).toBeInTheDocument();
122+
123+
const micOffIcon = screen.getByTestId('MicOffIcon');
124+
expect(micOffIcon).toBeInTheDocument();
125+
});
126+
});
75127
});

0 commit comments

Comments
 (0)