Skip to content

Latest commit

 

History

History
91 lines (63 loc) · 6.24 KB

File metadata and controls

91 lines (63 loc) · 6.24 KB

import { Meta } from '@storybook/addon-docs';

Best Practices

We are sharing some of our recommended best practices when handling state with Azure Communication Services UI Library.

Use the Stateful Clients

Managing the complex state of a calling or chat sesion can be challenging. This was a complex problem we found we were in and we think many of our developer community will run into this challenge themselves. We wanted to find a convenient way to store this information on the client in a way that plays nicely with our components we are offering. By using the stateful client for calling or chat, you are on our recommended path for powering your own communications experience using Azure Communication Services.

Use usePropsFor

If you are using our provided UI Components, usePropsFor will help you get integrated with the underlying functionality quickly. This provides a series of properties our provided components are expecting from the stateful client to render an experience your users will be expecting. This is the fastest way to get your experience up and running with Azure Communication Services.

You can use your own UI Components

Today you can use useSelector to connect your own components to create your own experiences! We use useSelector under the hood when you leverage our usePropsFor hook. We wanted to ensure that developers wanting to create custom components had the same development path that we were using as well. Using this development path allows you to start on the path that we use as well to create amazing components.

Populating the DeviceManager State

When using Stateful Calling, the call related state will be automatically retrieved for you. However, this is not the case for DeviceManager state. To be able to retrieve DeviceManager state from the StatefulCallClient’s state, you must trigger the appropriate APIs to populate the DeviceManager state.

  • DeviceManager.askPermission() – this must be called to ask for device permissions from the user. The result of their decisions will be stored in DeviceManagerState.deviceAccess.
  • DeviceManager.getCameras() – When called, the result will be stored in DeviceManagerState.cameras.
  • DeviceManager.getMicrophones() – When called, the result will be stored in DeviceManagerState.microphones.
  • DeviceManager.getSpeakers() – When called, the result will be stored in DeviceManagerState.speakers

Use of selectedCamera inside the DeviceManager

To make Stateful Calling easier to use we’ve added a property to the DeviceManagerState called selectedCamera. This is not a proxy of the SDK state and is completely controlled by you. It is populated when you set it and updated when you update it. It has no bearing on the function of the SDK and not automatically used by the SDK.

Use of createView and disposeView on the StatefulCallClient

To allow developers to generate a HTMLElement/view of a Stateful VideoStream, we provide a createView and disposeView API. These APIs are located in StatefulCallClient and should only be used for scenarios where developers want to generate their own components to use in conjunction with the UI Library. There are three scenarios to using these APIs:

  1. Rendering a RemoteVideoStreamState You are required to call createView with a valid callId, participantIdentifier, and remoteVideoStreamState. The createView is async and if your architecture can support awaiting for it we recommend you do that. Once the createView completes the view will be stored under CallState.RemoteParticipants.[your remote participant].videoStream.[your videostream].view. If you cannot await the result of createView, it is fine to call createView again, createView will no-op the second call. Once the view has been created, the call state will be automatically updated and you can check the state for the view. CreateView will not allow creating multiple view of the same stream.

  2. Rendering a LocalVideoStreamState in a Call Same as #1 except this time createView only requires a valid callId and LocalVideoStreamState. Note that this will only work if the LocalVideoStream is already part of the call (you’ll have to first call Call.startVideo to add the LocalVideoStream to the Call). Everything else is the same as #1 after this except the view can be found in CallState.localVideoStreams.(your videostream).view.

  3. Rendering a LocalVideoStreamState when not in a call This scenario supports the case if you want to see a video render without adding that stream to the call, for instance LocalPreview scenario. In this case createView requires only a valid LocalVideoStreamState. CreateView will put the created view under DeviceManagerState.unparentedViews.(your videostream).view. You can access this Map using your original LocalVideoStreamState as the key.

To debug createView and disposeView, they emit console.warns when used incorrectly that can be tracked.

Track Changes to callId

One major gotcha with using Stateful Calling is that callId may change and callId is used to look up data in Stateful state. If you have an old callId and the callId changed, you will not be able to access or find CallState in CallClientState. To work around, we recommend you do not cache the callId and instead cache the entire call object. The id in the call object will be kept up to date and when ever you access CallClientState use the call.id.

Detecting Screenshare Participant

To make Stateful Calling easier to use we added a screenshareRemoteParticipant property to the state of any Call. If there is a remote participant screensharing, you can easily access the participant using CallState.screenShareRemoteParticipant:

const remoteScreenshareParticipant = statefulCallClient.getState().calls[CALL_ID].screenShareRemoteParticipant;

This property will be undefined if there are no remote participants screensharing. Note that this only applies to remote screenshares and not local screenshares.

Detecting Transcription and Recording

Stateful Calling will manage transcription/recording for you. You only need to simply check the states under CallState.transcription and CallState.recording.