Skip to content
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

Add mechanism to get the listener's name in the Webinar Mode #381

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
34 changes: 34 additions & 0 deletions react/src/Components/ParticipantTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ function ParticipantTab(props) {
);
};

const getPlayOnlyParticipantItem = (streamId) => {
return (
<Grid
id={"play-only-participant-item-" + streamId}
key={streamId}
container
alignItems="center"
justifyContent="space-between"
style={{ borderBottomWidth: 1 }}
sx={{ borderColor: "primary.main" }}
>
<Grid item sx={{ pr: 1 }}>
<ParticipantName variant="body1">{streamId}</ParticipantName>
</Grid>
</Grid>
);
};

return (
<div style={{width: "100%", overflow: "hidden"}}>
<Stack sx={{width: "100%",}} spacing={2}>
Expand All @@ -142,6 +160,22 @@ function ParticipantTab(props) {
return "";
}
})}
<Grid container alignItems="center" style={{ marginTop: 21, marginBottom: 12 }}>
<Typography variant="body2" style={{ marginRight: 4, fontWeight: 500 }}>
Play Only Participants
</Typography>
<SvgIcon size={28} name="participants" color={theme.palette?.participantListIcon?.primary} />
<ParticipantName variant="body2" style={{ marginLeft: 4, fontWeight: 500 }}>
{conference.playOnlyParticipants.length}
</ParticipantName>
</Grid>
{conference.playOnlyParticipants.map((streamId) => {
if (conference.publishStreamId !== streamId) {
return getPlayOnlyParticipantItem(streamId);
} else {
return "";
}
})}
</Stack>
</div>
);
Expand Down
22 changes: 22 additions & 0 deletions react/src/__tests__/Components/ParticipantTab.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const contextValue = {
videoLabel: 'test-video-label',
},
},
playOnlyParticipants: ["test-play-only-stream-id"],
publishStreamId: 'test-stream-id',
pinVideo: jest.fn(),
makeParticipantPresenter: jest.fn(),
Expand Down Expand Up @@ -68,6 +69,27 @@ describe('ParticipantTab Component', () => {
expect(participantItem).toBe(true);
});

it('renders play only participants correctly', () => {
const { container } = render(
<ThemeProvider theme={theme(ThemeList.Green)}>
<ParticipantTab />
</ThemeProvider>
);
const playOnlyParticipantItem = container.innerHTML.includes('play-only-participant-item-'+contextValue.playOnlyParticipants[0]);
expect(playOnlyParticipantItem).toBe(true);
});

it('does not render play only participant if it matches publishStreamId', () => {
contextValue.playOnlyParticipants = [contextValue.publishStreamId];
const { container } = render(
<ThemeProvider theme={theme(ThemeList.Green)}>
<ParticipantTab />
</ThemeProvider>
);
const playOnlyParticipantItem = container.innerHTML.includes('play-only-participant-item-'+contextValue.publishStreamId);
expect(playOnlyParticipantItem).toBe(false);
});

it('renders getAdminButtons without crashing', () => {
contextValue.isAdmin = true;
process.env.REACT_APP_PARTICIPANT_TAB_ADMIN_MODE_ENABLED=true
Expand Down
36 changes: 34 additions & 2 deletions react/src/__tests__/pages/AntMedia.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ConferenceContext } from "pages/AntMedia";
import { ThemeProvider } from '@mui/material/styles';
import {ThemeList} from "styles/themeList";
import theme from "styles/theme";
import { times } from 'lodash';
import {forEach, times} from 'lodash';
import { useParams } from 'react-router-dom';

var webRTCAdaptorConstructor, webRTCAdaptorScreenConstructor, webRTCAdaptorPublishSpeedTestPlayOnlyConstructor, webRTCAdaptorPublishSpeedTestConstructor, webRTCAdaptorPlaySpeedTestConstructor;
Expand Down Expand Up @@ -47,6 +47,7 @@ jest.mock('@antmedia/webrtc_adaptor', () => ({
init : jest.fn(),
publish : jest.fn().mockImplementation(() => console.log('publishhhhhh')),
play : jest.fn(),
joinRoom : jest.fn(),
unpublish : jest.fn(),
leaveRoom : jest.fn(),
startPublishing : jest.fn(),
Expand Down Expand Up @@ -80,7 +81,6 @@ jest.mock('@antmedia/webrtc_adaptor', () => ({
createSpeedTestForPlayWebRtcAdaptor: jest.fn(),
requestVideoTrackAssignments: jest.fn(),
stopSpeedTest: jest.fn().mockImplementation(() => console.log('stopSpeedTest')),
getSubtracks: jest.fn(),
closeStream: jest.fn(),
closeWebSocket: jest.fn(),
}
Expand Down Expand Up @@ -1923,4 +1923,36 @@ describe('AntMedia Component', () => {
});
});

it('sets play only participants to all participants when none are in temp', async () => {
const {container} = render(
<ThemeProvider theme={theme(ThemeList.Green)}>
<AntMedia isTest={true}>
<MockChild/>
</AntMedia>
</ThemeProvider>);

await waitFor(() => {
expect(webRTCAdaptorConstructor).not.toBe(undefined);
});

currentConference.allParticipants = {};
currentConference.playOnlyParticipants = [];

var obj = {};
let broadcastObject = {streamId: "room", name: "room", subTrackStreamIds: ["pid1", "pid2", "pid3"]};
let broadcastObjectMessage = JSON.stringify(broadcastObject);

obj.broadcast = broadcastObjectMessage;
obj.streamId = "room";

await act(async () => {
webRTCAdaptorConstructor.callback("broadcastObject", obj);
});

await waitFor(() => {
expect(currentConference.playOnlyParticipants).toEqual(broadcastObject.subTrackStreamIds);
});

});

});
19 changes: 18 additions & 1 deletion react/src/pages/AntMedia.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,8 @@ function AntMedia(props) {
*/
const [allParticipants, setAllParticipants] = useState({});

const [playOnlyParticipants, setPlayOnlyParticipants] = useState([]);

const [audioTracks, setAudioTracks] = useState([]);

const [talkers, setTalkers] = useState([]);
Expand Down Expand Up @@ -1012,13 +1014,18 @@ function AntMedia(props) {
handlePublish(generatedStreamId, token, subscriberId, subscriberCode);
}

// if the user is in playOnly mode, it will join the room with the generated stream id
// so we can get the list of play only participants in the room
webRTCAdaptor?.joinRoom(roomName, generatedStreamId);

webRTCAdaptor?.play(roomName, token, roomName, null, subscriberId, subscriberCode, '{}', role);
}

function requestVideoTrackAssignmentsInterval() {
if (videoTrackAssignmentsIntervalJob === null) {
videoTrackAssignmentsIntervalJob = setInterval(() => {
webRTCAdaptor?.requestVideoTrackAssignments(roomName);
webRTCAdaptor?.getBroadcastObject(roomName);
}, 3000);
}
}
Expand Down Expand Up @@ -1138,6 +1145,15 @@ function AntMedia(props) {
delete temp[trackId];
}
});

let tempPlayOnlyParticipants = [];
forEach(participantIds, function (pid) {
if (temp[pid] === undefined) {
tempPlayOnlyParticipants.push(pid);
}
});
setPlayOnlyParticipants(tempPlayOnlyParticipants);

console.log("handleMainTrackBroadcastObject setAllParticipants:"+JSON.stringify(temp));
setAllParticipants(temp);
setParticipantUpdated(!participantUpdated);
Expand Down Expand Up @@ -2803,7 +2819,8 @@ function AntMedia(props) {
stopSpeedTest,
statsList,
getTrackStats,
isBroadcasting
isBroadcasting,
playOnlyParticipants
}}
>
{props.children}
Expand Down
Loading