UNPKG

communication-react-19

Version:

React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)

101 lines 5.3 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { useEffect, useMemo, useState } from 'react'; import { callingComponentLogger } from '../utils/Logger'; /** * Helper hook to maintain the video stream lifecycle. This calls onCreateStreamView and onDisposeStreamView * appropriately based on react lifecycle events and prop changes. * * @remarks * * Notes on handling changes to scaling mode: * * Ideally we have access to the original StreamRenderView and can call view.updateScalingMode() and do not need to recreate the stream view. * However, to support backwards compat we cannot guarantee this. If we don't have access to the original StreamRenderView we need to dispose * the old view and create a new one. * * Supporting both of these scenarios became too complex and fragile. When we introduce a breaking change this should be update to ensure that * onCreateStreamView _must_ return a view object with updateScalingMode and update logic in this hook to call view.updateScalingMode instead * of recreating the stream. * * @private */ const useVideoStreamLifecycleMaintainer = (props) => { const { isMirrored, isScreenSharingOn, isStreamAvailable, onCreateStreamView, onDisposeStreamView, renderElementExists, scalingMode, streamId, isVideoPermitted } = props; const [videoStreamViewResult, setVideoStreamViewResult] = useState(); useEffect(() => { var _a; if (isVideoPermitted !== false && isStreamAvailable && !renderElementExists) { (_a = onCreateStreamView === null || onCreateStreamView === void 0 ? void 0 : onCreateStreamView({ isMirrored, scalingMode })) === null || _a === void 0 ? void 0 : _a.then((result) => { result && setVideoStreamViewResult(result); }); } // Always clean up element to make tile up to date and be able to dispose correctly return () => { if (renderElementExists) { // TODO: Remove `if isScreenSharingOn` when we isolate dispose behavior for screen share if (!isScreenSharingOn) { onDisposeStreamView === null || onDisposeStreamView === void 0 ? void 0 : onDisposeStreamView(); } } else { callingComponentLogger.warning('Stream view element does not exist when disposing stream view'); } }; }, [ isMirrored, isScreenSharingOn, isStreamAvailable, onCreateStreamView, onDisposeStreamView, renderElementExists, scalingMode, streamId, isVideoPermitted ]); // The execution order for above useEffect is onCreateRemoteStreamView =>(async time gap) RenderElement generated => element disposed => onDisposeRemoteStreamView // Element disposed could happen during async time gap, which still cause leaks for unused renderElement. // Need to do an entire cleanup when remoteTile gets disposed and make sure element gets correctly disposed useEffect(() => { return () => { // TODO: Remove `if isScreenSharingOn` when we isolate dispose behavior for screen share if (!isScreenSharingOn) { onDisposeStreamView === null || onDisposeStreamView === void 0 ? void 0 : onDisposeStreamView(); } }; }, [isScreenSharingOn, onDisposeStreamView]); return videoStreamViewResult; }; /** * Extension of {@link useVideoStreamLifecycleMaintainer} specifically for local video streams * * @private */ export const useLocalVideoStreamLifecycleMaintainer = (props) => { const { onCreateLocalStreamView, onDisposeLocalStreamView } = props; const onCreateStreamView = useMemo(() => (options) => { return onCreateLocalStreamView === null || onCreateLocalStreamView === void 0 ? void 0 : onCreateLocalStreamView(options); }, [onCreateLocalStreamView]); const onDisposeStreamView = useMemo(() => () => { onDisposeLocalStreamView === null || onDisposeLocalStreamView === void 0 ? void 0 : onDisposeLocalStreamView(); }, [onDisposeLocalStreamView]); return useVideoStreamLifecycleMaintainer(Object.assign(Object.assign({}, props), { onCreateStreamView, onDisposeStreamView })); }; /** * Extension of {@link useVideoStreamLifecycleMaintainer} specifically for remote video streams * * @private */ export const useRemoteVideoStreamLifecycleMaintainer = (props) => { const { remoteParticipantId, onCreateRemoteStreamView, onDisposeRemoteStreamView } = props; const onCreateStreamView = useMemo(() => (options) => { return onCreateRemoteStreamView === null || onCreateRemoteStreamView === void 0 ? void 0 : onCreateRemoteStreamView(remoteParticipantId, options); }, [onCreateRemoteStreamView, remoteParticipantId]); const onDisposeStreamView = useMemo(() => () => { onDisposeRemoteStreamView === null || onDisposeRemoteStreamView === void 0 ? void 0 : onDisposeRemoteStreamView(remoteParticipantId); }, [onDisposeRemoteStreamView, remoteParticipantId]); return useVideoStreamLifecycleMaintainer(Object.assign(Object.assign({}, props), { onCreateStreamView, onDisposeStreamView })); }; //# sourceMappingURL=useVideoStreamLifecycleMaintainer.js.map