Skip to main content

Send presentation

In the previous lesson we learnt how to receive a presentation from other participants and display it in our interface. Now we will do the reverse. We will add a new button to the interface that, when clicked, will ask the user what they want to share (tab, window or whole screen) and after that, remote users will see that content.

info

Screen sharing from a mobile browser to other devices is not permitted by mobile browsers. Mobile browsers don't support this feature due to security restrictions. If you want to use this feature in a mobile, you will need to create a native application using our Mobile SDKs.

However, a mobile web application is still able to receive screen shares from other devices. The limitation only prevents mobile browsers from sending screen shares.

You can download the starter code from Step.05-Exercise-Send-presentation.

App component

We will start by making some modifications in the src/App.tsx file.

The first step is to modify the handleDisconnect function and define a couple of lines that will stop the presentation:

const handleDisconnect = () => {
presentationStream?.getTracks().forEach((track) => track.stop());
setPresentationStream(null);
...
};

This way, in case the user pushes the hang up button, the presentation will be stopped and we will free the resources.

Then we will define the function that will be called once the user click on the share screen button to activate or deactivate this feature:

const handleScreenShare = async (share: boolean, onEnded: () => void) => {
if (share) {
const stream = await navigator.mediaDevices.getDisplayMedia();
stream.getVideoTracks()[0].onended = () => {
onEnded();
setPresentationStream(null);
infinityClient.stopPresenting();
};
infinityClient.present(stream);
setPresentationStream(stream);
} else {
presentationStream?.getTracks().forEach(track => track.stop());
setPresentationStream(null);
infinityClient.stopPresenting();
}
};

You can observe that we have two input parameters for this function:

  • share: Indicates if we are activating the feature (true) or deactivating it (false).
  • onEnded: The function that will be triggered when the screen sharing stops. This function will be defined in the Toolbar and we will use it to change the button state to deactivated.

In this function the first thing that we will do is to check the value of share, and depending of its value we will activate the feature or not:

  • share=true: In this case we will activate this feature. The first step is to get the MediaStream and for that we will use the browser API getDisplayMedia(). Once we have this stream, we attach a callback function to onended. This function will be called when the user clicks on the native browser message "Stop sharing". This way we can inform the Toolbar through the onEnded() callback that the feature was deactivated.

    Then we call infinityClient.present(stream) and at this point the stream will be sent to Pexip Infinity and to other participants. The last call to infinityClient.setPresentationStream(stream) will make our stream visible in our interface.

  • share=false: The first thing that we do in this case is to stop all the tracks in the same way that we do with video mute. Then we set the state variable to null to remove the video from the interface, and finally, we call infinityClient.stopPresenting() to stop sending the stream to Pexip Infinity.

Now it's the turn to pass the handleScreenShare function to the Conference component:

<Conference
localStream={localStream}
remoteStream={remoteStream}
presentationStream={presentationStream}
onAudioMute={handleAudioMute}
onVideoMute={handleVideoMute}
onScreenShare={handleScreenShare}
onDisconnect={handleDisconnect}
/>

Conference component

We have to include some modifications in the conference component. So the first step is to open src/components/Conference/Conference.tsx.

We will start by including onScreenShare in the list of props:

interface ConferenceProps {
localStream: MediaStream | null;
remoteStream: MediaStream | null;
presentationStream: MediaStream | null;
onAudioMute: (mute: boolean) => void;
onVideoMute: (mute: boolean) => void;
onScreenShare: (share: boolean, onEnded: () => void) => void;
onDisconnect: () => void;
}

Now we add the onScreenShare when we define the Toolbar component:

<Toolbar
className="toolbar"
onAudioMute={props.onAudioMute}
onVideoMute={props.onVideoMute}
onScreenShare={async (share: boolean, onEnded: () => void) => {
setPresentationInMain(false);
await props.onScreenShare(share, onEnded);
}}
onDisconnect={props.onDisconnect}
/>

In this case, instead of passing the onEnded function directly to the Toolbar, we reset the value of presentationInMain so the video with the remote the participants will appear in the main region.

Toolbar component

Next we will modify the file src/components/Conference/Toolbar/Toolbar.tsx and create the button that the user will use to start or stop sharing their screen.

The first step is to add onScreenShare to the list of props:

interface ToolbarProps {
className: string;
onAudioMute: (mute: boolean) => void;
onVideoMute: (mute: boolean) => void;
onScreenShare: (share: boolean, onEnded: () => void) => void;
onDisconnect: () => void;
}

Now we define the state variable for our button that will indicate its visual style:

const [screenShared, setScreenShared] = useState(false);

After that, we will define the function that will be triggered each time the user clicks on the screen share button. This function will call the function defined in props and change the button state:

const handleScreenShare = async () => {
try {
await props.onScreenShare(!screenShared, () => {
setScreenShared(false);
});
setScreenShared(!screenShared);
} catch (error) {
console.error(error);
}
};

The final step is to return the button itself with the rest of the components from the toolbar:

<Button
onClick={handleScreenShare}
selected={screenShared}
icon={<ScreenShareIcon />}
/>

Run the app

Now we have all in place to test our functionality the new functionality. The user only have to push the screen share button and the rest of the users will start seeing the shared content.

You can compare your code with the solution in Step.05-Solution-Send-presentation. You can also check the differences with the previous lesson in the git diff.

Send Presentation