Send presentation
In the previous lesson we have learnt how to receive a presentation from other participant and display it in our interface. Now we will do it the other way around. We will add a new button to the interface that, by clicking on it, we will ask the user what he wants to share (tab, window or whole screen) and after that, the remote users will see that content.
Screen sharing from a mobile browser to other device is not available. The 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 will still be able to receive the screen shared from other device. The limitation applies only if the mobile is the one that captures the screen.
App component
We will start by making some modifications in the src/App.tsx
file.
The first step is to 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 enable 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 the other participants. The last call toinfinityClient.setPresentationStream(stream)
will make our stream visible in our interface.share=false
: The first thing that we do is to stop all the tracks in the same way that we do with video mute. Then we set the state variable tonull
that will remove the video from the interface and, finally, we callinfinityClient.stopPresenting()
that will 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 include 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
Now 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 include onScreenShare
in 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 of sharing the screen.