diff --git a/react/.env.development.conference b/react/.env.development.conference index 8387365c..e56267d6 100644 --- a/react/.env.development.conference +++ b/react/.env.development.conference @@ -69,6 +69,9 @@ REACT_APP_RECORDING_MANAGED_BY_ADMIN=false # Speed Test configurations REACT_APP_SPEED_TEST_BEFORE_JOINING_THE_ROOM=false +# Show play only participants in the participant list +REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS=false + # Auto Pin configurations for screen share REACT_APP_AUTO_PIN_WHEN_SCREEN_SHARE=true diff --git a/react/.env.development.webinar b/react/.env.development.webinar index a0a40ed1..6a1e284a 100644 --- a/react/.env.development.webinar +++ b/react/.env.development.webinar @@ -71,6 +71,9 @@ REACT_APP_FORCE_THEME="white" # Speed Test configurations REACT_APP_SPEED_TEST_BEFORE_JOINING_THE_ROOM=true +# Show play only participants in the participant list +REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS=false + # URL configurations REACT_APP_FOOTER_LOGO_ON_CLICK_URL="" REACT_APP_REPORT_PROBLEM_URL="" diff --git a/react/.env.production b/react/.env.production index 983d5469..d6079532 100644 --- a/react/.env.production +++ b/react/.env.production @@ -70,6 +70,9 @@ REACT_APP_RECORDING_MANAGED_BY_ADMIN=false # Speed Test configurations REACT_APP_SPEED_TEST_BEFORE_JOINING_THE_ROOM=false +# Show play only participants in the participant list +REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS=false + # Virtual Background configurations REACT_APP_VIRTUAL_BACKGROUND_IMAGES="https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background0.png,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background1.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background2.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background3.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background4.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background5.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background7.jpg" diff --git a/react/.env.production.webinar b/react/.env.production.webinar index 41eaf94e..743dd7a0 100644 --- a/react/.env.production.webinar +++ b/react/.env.production.webinar @@ -73,6 +73,9 @@ REACT_APP_FORCE_THEME="white" # Speed Test configurations REACT_APP_SPEED_TEST_BEFORE_JOINING_THE_ROOM=true +# Show play only participants in the participant list +REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS=false + # Virtual Background configurations REACT_APP_VIRTUAL_BACKGROUND_IMAGES="https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background0.png,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background1.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background2.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background3.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background4.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background5.jpg,https://raw.githubusercontent.com/ant-media/conference-call-application/main/static/virtualBackgroundImages/virtual-background7.jpg" diff --git a/react/src/Components/ParticipantTab.js b/react/src/Components/ParticipantTab.js index 4ac7fcc9..14ea3288 100644 --- a/react/src/Components/ParticipantTab.js +++ b/react/src/Components/ParticipantTab.js @@ -140,6 +140,7 @@ function ParticipantTab(props) {
+ {conference.pagedParticipants[streamId]?.status !== "created" ? <> {(typeof conference.pagedParticipants[streamId]?.isPinned !== "undefined") && (conference.pagedParticipants[streamId]?.isPinned === true) ? ( + : + + }
diff --git a/react/src/__tests__/Components/ParticipantTab.test.js b/react/src/__tests__/Components/ParticipantTab.test.js index f60984c0..8eba7bcf 100644 --- a/react/src/__tests__/Components/ParticipantTab.test.js +++ b/react/src/__tests__/Components/ParticipantTab.test.js @@ -55,6 +55,18 @@ const contextValue = { metaData: { isMuted: false } + }, + 'test-play-only-stream-id': { + role: 'host', + participantID: 'test-play-only-participant-id', + streamID: 'test-play-only-stream-id', + videoTrack: 'test-play-only-video-track', + audioTrack: 'test-play-only-audio-track', + videoLabel: 'test-play-only-video-label', + metaData: { + isMuted: false + }, + status: "created" } }, isAdmin: true, @@ -180,5 +192,16 @@ describe('ParticipantTab Component', () => { expect(contextValue.setParticipantIdMuted).toHaveBeenCalled(); expect(contextValue.turnOffYourMicNotification).toHaveBeenCalled(); }); + + it('render play only participat icon', () => { + const { getByTestId } = render( + + + + ); + + const playOnlyParticipant = getByTestId('playonly-test-play-only-stream-id'); + expect(playOnlyParticipant).toBeInTheDocument(); + }); }); diff --git a/react/src/__tests__/pages/AntMedia.test.js b/react/src/__tests__/pages/AntMedia.test.js index 562ebc6b..fafc3262 100644 --- a/react/src/__tests__/pages/AntMedia.test.js +++ b/react/src/__tests__/pages/AntMedia.test.js @@ -84,9 +84,11 @@ jest.mock('@antmedia/webrtc_adaptor', () => ({ closeStream: jest.fn(), closeWebSocket: jest.fn(), playStats: {}, + leaveFromRoom: jest.fn(), enableEffect: jest.fn(), setSelectedVideoEffect: jest.fn(), setBlurEffectRange: jest.fn(), + joinRoom: jest.fn(), getSubtrackCount: jest.fn(), setVolumeLevel: jest.fn(), } @@ -499,13 +501,17 @@ describe('AntMedia Component', () => { currentConference.handleSetDesiredTileCount(5); }); - expect(currentConference.globals.desiredTileCount == 5); + await waitFor(() => { + expect(currentConference.globals.desiredTileCount).toBe(5); + }); await act(async () => { currentConference.updateMaxVideoTrackCount(7); }); - expect(currentConference.globals.maxVideoTrackCount === 7); + await waitFor(() => { + expect(currentConference.globals.maxVideoTrackCount).toBe(7); + }); consoleSpy.mockRestore(); @@ -1144,12 +1150,28 @@ describe('AntMedia Component', () => { expect(webRTCAdaptorConstructor).not.toBe(undefined); }); + let roomName = "room"; + let publishStreamId = "publishStreamId"; + + await act(async () => { + currentConference.setRoomName(roomName); + }); + + await act(async () => { + currentConference.setPublishStreamId(publishStreamId); + }); + + await act(async () => { + process.env.REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS = 'true'; + }); + await act(async () => { currentConference.handleLeaveFromRoom(); }); expect(webRTCAdaptorConstructor.stop).toHaveBeenCalled(); expect(webRTCAdaptorConstructor.closeStream).toHaveBeenCalled(); + expect(webRTCAdaptorConstructor.leaveFromRoom).toHaveBeenCalledWith(roomName, publishStreamId); }); @@ -3453,4 +3475,33 @@ describe('AntMedia Component', () => { }); }); + it('test play only participant join room', async () => { + const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); + + const { container } = render( + + + ); + + await waitFor(() => { + expect(webRTCAdaptorConstructor).not.toBe(undefined); + }); + + await act(async () => { + currentConference.setIsPlayOnly(true); + }); + + await act(async () => { + process.env.REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS = "true"; + }); + + await waitFor(() => { + currentConference.joinRoom("room", "publishStreamId"); + }); + + expect(consoleSpy).toHaveBeenCalledWith("Play only mode is active, joining the room with the generated stream id"); + + consoleSpy.mockRestore(); + }); + }); \ No newline at end of file diff --git a/react/src/pages/AntMedia.js b/react/src/pages/AntMedia.js index 74c7df9b..adb8157b 100644 --- a/react/src/pages/AntMedia.js +++ b/react/src/pages/AntMedia.js @@ -1171,6 +1171,11 @@ function AntMedia(props) { if (!isPlayOnly) { handlePublish(generatedStreamId, token, subscriberId, subscriberCode); + } else if (process.env.REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS === "true") { + // 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, null, streamName, role, getUserStatusMetadata()); + console.log("Play only mode is active, joining the room with the generated stream id"); } webRTCAdaptor?.play(roomName, token, roomName, null, subscriberId, subscriberCode, '{}', role); @@ -1180,6 +1185,7 @@ function AntMedia(props) { if (videoTrackAssignmentsIntervalJob === null) { videoTrackAssignmentsIntervalJob = setInterval(() => { webRTCAdaptor?.requestVideoTrackAssignments(roomName); + webRTCAdaptor?.getSubtrackCount(roomName, null, null); // get the total participant count in the room }, 3000); } } @@ -1523,6 +1529,10 @@ function AntMedia(props) { } } else if (info === "subtrackCount") { if (obj.count !== undefined) { + if (obj.count > participantCount) { + // if the new participant is added, we need to get the subtrack list again + webRTCAdaptor?.getSubtracks(roomName, null, globals.participantListPagination.offset, globals.participantListPagination.pageSize); + } setParticipantCount(obj.count); } } else if (info === "broadcastObject") { @@ -2497,6 +2507,10 @@ function AntMedia(props) { handleStopScreenShare(); } + if (process.env.REACT_APP_SHOW_PLAY_ONLY_PARTICIPANTS === "true") { + webRTCAdaptor?.leaveFromRoom(roomName, publishStreamId); + } + playLeaveRoomSound(); setWaitingOrMeetingRoom("waiting"); @@ -3173,7 +3187,9 @@ function AntMedia(props) { setSpeedTestObjectProgress, calculateThePlaySpeedTestResult, processUpdatedStatsForPlaySpeedTest, - speedTestCounter + speedTestCounter, + setRoomName, + setPublishStreamId }} > {props.children} diff --git a/react/src/styles/sprite.svg b/react/src/styles/sprite.svg index ab5b7cb4..6297ad24 100644 --- a/react/src/styles/sprite.svg +++ b/react/src/styles/sprite.svg @@ -26,6 +26,12 @@ + + + + + +