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.
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 theMediaStream
and for that we will use the browser APIgetDisplayMedia()
. Once we have this stream, we attach a callback function toonended
. This function will be called when the user clicks on the native browser message "Stop sharing". This way we can inform theToolbar
through theonEnded()
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 toinfinityClient.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 tonull
to remove the video from the interface, and finally, we callinfinityClient.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.