From fc01dc13b754d43de775635af81712e5aa5d845a Mon Sep 17 00:00:00 2001 From: Chukwuebuka Nwankwo Date: Fri, 17 Jan 2025 22:38:39 +0000 Subject: [PATCH 1/2] Cleanup code logic --- .../src/baseSelectors.ts | 12 +++- .../src/handlers/createCommonHandlers.ts | 5 +- .../src/handlers/createTeamsCallHandlers.ts | 6 +- .../src/notificationStackSelector.ts | 1 - .../src/utils/videoGalleryUtils.ts | 11 ++++ .../src/videoGallerySelector.ts | 37 ++++++++++-- .../src/CallContext.ts | 2 +- .../src/TogetherModeSubscriber.ts | 58 ++++++++++--------- .../review/beta/communication-react.api.md | 4 ++ 9 files changed, 93 insertions(+), 43 deletions(-) diff --git a/packages/calling-component-bindings/src/baseSelectors.ts b/packages/calling-component-bindings/src/baseSelectors.ts index c412696bd08..a4406ac0bca 100644 --- a/packages/calling-component-bindings/src/baseSelectors.ts +++ b/packages/calling-component-bindings/src/baseSelectors.ts @@ -28,7 +28,8 @@ import { ConferencePhoneInfo } from '@internal/calling-stateful-client'; import { CallNotifications } from '@internal/calling-stateful-client'; /* @conditional-compile-remove(media-access) */ import { CapabilitiesChangeInfo } from '@azure/communication-calling'; - +/* @conditional-compile-remove(together-mode) */ +import { TogetherModeCallFeatureState } from '@internal/calling-stateful-client'; /** * Common props used to reference calling declarative client state. * @@ -306,3 +307,12 @@ export const getAssignedBreakoutRoom = ( ): BreakoutRoom | undefined => { return state.calls[props.callId]?.breakoutRooms?.assignedBreakoutRoom; }; + +/* @conditional-compile-remove(together-mode) */ +/** + * @private + */ +export const getTogetherModeCallFeature = ( + state: CallClientState, + props: CallingBaseSelectorProps +): TogetherModeCallFeatureState | undefined => state.calls[props.callId]?.togetherMode; diff --git a/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts b/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts index 65080a30f45..dd56579db8e 100644 --- a/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts +++ b/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts @@ -807,7 +807,6 @@ export const createDefaultCommonCallingHandlers = memoizeOne( ? { view: createViewResult?.view } : undefined; } - return togetherModeCreateViewResult; }; @@ -929,9 +928,9 @@ export const createDefaultCommonCallingHandlers = memoizeOne( /* @conditional-compile-remove(together-mode) */ onStartTogetherMode: notImplemented, /* @conditional-compile-remove(together-mode) */ - onDisposeTogetherModeStreamView, - /* @conditional-compile-remove(together-mode) */ onSetTogetherModeSceneSize, + /* @conditional-compile-remove(together-mode) */ + onDisposeTogetherModeStreamView, /* @conditional-compile-remove(media-access) */ onForbidAudio, /* @conditional-compile-remove(media-access) */ diff --git a/packages/calling-component-bindings/src/handlers/createTeamsCallHandlers.ts b/packages/calling-component-bindings/src/handlers/createTeamsCallHandlers.ts index 7197392dd66..7727839b078 100644 --- a/packages/calling-component-bindings/src/handlers/createTeamsCallHandlers.ts +++ b/packages/calling-component-bindings/src/handlers/createTeamsCallHandlers.ts @@ -137,10 +137,8 @@ export const createDefaultTeamsCallingHandlers = memoizeOne( if (!callState) { return; } - if (!callState.togetherMode.isActive) { - const togetherModeFeature = call?.feature(Features.TogetherMode); - await togetherModeFeature?.start(); - } + const togetherModeFeature = call?.feature(Features.TogetherMode); + await togetherModeFeature?.start(); } }; } diff --git a/packages/calling-component-bindings/src/notificationStackSelector.ts b/packages/calling-component-bindings/src/notificationStackSelector.ts index f337006b4c8..9a9643002d7 100644 --- a/packages/calling-component-bindings/src/notificationStackSelector.ts +++ b/packages/calling-component-bindings/src/notificationStackSelector.ts @@ -308,7 +308,6 @@ export const notificationStackSelector: NotificationStackSelector = createSelect autoDismiss: true }); } - /* @conditional-compile-remove(together-mode) */ if (latestNotifications['togetherModeEnded']) { activeNotifications.push({ diff --git a/packages/calling-component-bindings/src/utils/videoGalleryUtils.ts b/packages/calling-component-bindings/src/utils/videoGalleryUtils.ts index 665641dbb31..c843bddc2f5 100644 --- a/packages/calling-component-bindings/src/utils/videoGalleryUtils.ts +++ b/packages/calling-component-bindings/src/utils/videoGalleryUtils.ts @@ -262,3 +262,14 @@ export const memoizeLocalParticipant = memoizeOne( export const memoizeSpotlightedParticipantIds = memoizeOne((spotlightedParticipants) => spotlightedParticipants?.map((p: SpotlightedParticipant) => toFlatCommunicationIdentifier(p.identifier)) ); + +/** @private */ +export const memoizeTogetherModeStreams = memoizeOne((togetherModeStreams) => ({ + mainVideoStream: { + id: togetherModeStreams?.mainVideoStream?.id, + isReceiving: togetherModeStreams?.mainVideoStream?.isReceiving, + isAvailable: togetherModeStreams?.mainVideoStream?.isAvailable, + renderElement: togetherModeStreams?.mainVideoStream?.view?.target, + streamSize: togetherModeStreams?.mainVideoStream?.streamSize + } +})); diff --git a/packages/calling-component-bindings/src/videoGallerySelector.ts b/packages/calling-component-bindings/src/videoGallerySelector.ts index 5ea4e85116f..39357cd424d 100644 --- a/packages/calling-component-bindings/src/videoGallerySelector.ts +++ b/packages/calling-component-bindings/src/videoGallerySelector.ts @@ -4,6 +4,11 @@ import { toFlatCommunicationIdentifier } from '@internal/acs-ui-common'; import { CallClientState, RemoteParticipantState } from '@internal/calling-stateful-client'; import { VideoGalleryRemoteParticipant, VideoGalleryLocalParticipant } from '@internal/react-components'; +/* @conditional-compile-remove(together-mode) */ +import { + VideoGalleryTogetherModeStreams, + VideoGalleryTogetherModeParticipantPosition +} from '@internal/react-components'; import { createSelector } from 'reselect'; import { CallingBaseSelectorProps, @@ -16,6 +21,8 @@ import { getRole, getScreenShareRemoteParticipant } from './baseSelectors'; +/* @conditional-compile-remove(together-mode) */ +import { getTogetherModeCallFeature } from './baseSelectors'; import { isHideAttendeeNamesEnabled } from './baseSelectors'; import { getOptimalVideoCount } from './baseSelectors'; import { _updateUserDisplayNames } from './utils/callUtils'; @@ -24,7 +31,8 @@ import { _videoGalleryRemoteParticipantsMemo, _dominantSpeakersWithFlatId, convertRemoteParticipantToVideoGalleryRemoteParticipant, - memoizeLocalParticipant + memoizeLocalParticipant, + /* @conditional-compile-remove(together-mode) */ memoizeTogetherModeStreams } from './utils/videoGalleryUtils'; import { memoizeSpotlightedParticipantIds } from './utils/videoGalleryUtils'; import { getLocalParticipantRaisedHand } from './baseSelectors'; @@ -49,6 +57,14 @@ export type VideoGallerySelector = ( optimalVideoCount?: number; spotlightedParticipants?: string[]; maxParticipantsToSpotlight?: number; + /* @conditional-compile-remove(together-mode) */ + isTogetherModeActive?: boolean; + /* @conditional-compile-remove(together-mode) */ + startTogetherModeEnabled?: boolean; + /* @conditional-compile-remove(together-mode) */ + togetherModeStreams?: VideoGalleryTogetherModeStreams; + /* @conditional-compile-remove(together-mode) */ + togetherModeSeatingCoordinates?: VideoGalleryTogetherModeParticipantPosition; }; /** @@ -71,7 +87,9 @@ export const videoGallerySelector: VideoGallerySelector = createSelector( isHideAttendeeNamesEnabled, getLocalParticipantReactionState, getSpotlightCallFeature, - getCapabilities + getCapabilities, + /* @conditional-compile-remove(together-mode) */ + getTogetherModeCallFeature ], ( screenShareRemoteParticipantId, @@ -88,7 +106,9 @@ export const videoGallerySelector: VideoGallerySelector = createSelector( isHideAttendeeNamesEnabled, localParticipantReaction, spotlightCallFeature, - capabilities + capabilities, + /* @conditional-compile-remove(together-mode) */ + togetherModeCallFeature ) => { const screenShareRemoteParticipant = screenShareRemoteParticipantId && remoteParticipants @@ -102,7 +122,6 @@ export const videoGallerySelector: VideoGallerySelector = createSelector( const noRemoteParticipants: RemoteParticipantState[] = []; const localParticipantReactionState = memoizedConvertToVideoTileReaction(localParticipantReaction); const spotlightedParticipantIds = memoizeSpotlightedParticipantIds(spotlightCallFeature?.spotlightedParticipants); - return { screenShareParticipant: screenShareRemoteParticipant ? convertRemoteParticipantToVideoGalleryRemoteParticipant( @@ -145,7 +164,15 @@ export const videoGallerySelector: VideoGallerySelector = createSelector( dominantSpeakers: dominantSpeakerIds, maxRemoteVideoStreams: optimalVideoCount, spotlightedParticipants: spotlightedParticipantIds, - maxParticipantsToSpotlight: spotlightCallFeature?.maxParticipantsToSpotlight + maxParticipantsToSpotlight: spotlightCallFeature?.maxParticipantsToSpotlight, + /* @conditional-compile-remove(together-mode) */ + togetherModeStreams: memoizeTogetherModeStreams(togetherModeCallFeature?.streams), + /* @conditional-compile-remove(together-mode) */ + togetherModeSeatingCoordinates: togetherModeCallFeature?.seatingPositions, + /* @conditional-compile-remove(together-mode) */ + isTogetherModeActive: togetherModeCallFeature?.isActive, + /* @conditional-compile-remove(together-mode) */ + startTogetherModeEnabled: capabilities?.startTogetherMode.isPresent }; } ); diff --git a/packages/calling-stateful-client/src/CallContext.ts b/packages/calling-stateful-client/src/CallContext.ts index 2542a36e731..85960a0a899 100644 --- a/packages/calling-stateful-client/src/CallContext.ts +++ b/packages/calling-stateful-client/src/CallContext.ts @@ -500,7 +500,7 @@ export class CallContext { if (call) { const stream = call.togetherMode.streams.mainVideoStream; if (stream && stream?.id === streamId) { - stream.isReceiving = isAvailable; + stream.isAvailable = isAvailable; } } }); diff --git a/packages/calling-stateful-client/src/TogetherModeSubscriber.ts b/packages/calling-stateful-client/src/TogetherModeSubscriber.ts index d9c0e08d9d0..8b5b3d66031 100644 --- a/packages/calling-stateful-client/src/TogetherModeSubscriber.ts +++ b/packages/calling-stateful-client/src/TogetherModeSubscriber.ts @@ -67,7 +67,9 @@ export class TogetherModeSubscriber { }; private addRemoteVideoStreamSubscriber = (togetherModeVideoStream: TogetherModeVideoStream): void => { - this._togetherModeVideoStreamSubscribers.get(togetherModeVideoStream.id)?.unsubscribe(); + if (this._togetherModeVideoStreamSubscribers.has(togetherModeVideoStream.id)) { + return; + } this._togetherModeVideoStreamSubscribers.set( togetherModeVideoStream.id, new TogetherModeVideoStreamSubscriber(this._callIdRef, togetherModeVideoStream, this._context) @@ -78,7 +80,7 @@ export class TogetherModeSubscriber { addedStreams: TogetherModeVideoStream[], removedStreams: TogetherModeVideoStream[] ): void => { - for (const stream of removedStreams) { + removedStreams.forEach((stream) => { this._togetherModeVideoStreamSubscribers.get(stream.id)?.unsubscribe(); this._togetherModeVideoStreamSubscribers.delete(stream.id); this._internalContext.deleteCallFeatureRenderInfo( @@ -86,39 +88,39 @@ export class TogetherModeSubscriber { this._featureName, stream.mediaStreamType ); - } + }); + + addedStreams + .filter((stream) => stream.isAvailable) + .forEach((stream) => { + this._internalContext.setCallFeatureRenderInfo( + this._callIdRef.callId, + this._featureName, + stream.mediaStreamType, + stream as RemoteVideoStream, + 'NotRendered', + undefined + ); + this.addRemoteVideoStreamSubscriber(stream); + }); - for (const stream of addedStreams) { - this._internalContext.setCallFeatureRenderInfo( - this._callIdRef.callId, - this._featureName, - stream.mediaStreamType, - stream as RemoteVideoStream, - 'NotRendered', - undefined - ); - this.addRemoteVideoStreamSubscriber(stream); - } this._context.setTogetherModeVideoStreams( this._callIdRef.callId, - addedStreams.map((stream) => - convertSdkCallFeatureStreamToDeclarativeCallFeatureStream(stream, this._featureName) - ), + addedStreams + .filter((stream) => stream.isAvailable) + .map((stream) => convertSdkCallFeatureStreamToDeclarativeCallFeatureStream(stream, this._featureName)), removedStreams.map((stream) => convertSdkCallFeatureStreamToDeclarativeCallFeatureStream(stream, this._featureName) ) ); - if (this._togetherMode.togetherModeStream.length) { - this._context.setLatestNotification(this._callIdRef.callId, { - target: 'togetherModeStarted', - timestamp: new Date(Date.now()) - }); - } else { - this._context.setLatestNotification(this._callIdRef.callId, { - target: 'togetherModeEnded', - timestamp: new Date(Date.now()) - }); - } + + const notificationTarget = this._togetherMode.togetherModeStream.length + ? 'togetherModeStarted' + : 'togetherModeEnded'; + this._context.setLatestNotification(this._callIdRef.callId, { + target: notificationTarget, + timestamp: new Date() + }); }; private onTogetherModeStreamUpdated = (args: { diff --git a/packages/communication-react/review/beta/communication-react.api.md b/packages/communication-react/review/beta/communication-react.api.md index 68bbd9eae29..4868e659fa7 100644 --- a/packages/communication-react/review/beta/communication-react.api.md +++ b/packages/communication-react/review/beta/communication-react.api.md @@ -5624,6 +5624,10 @@ export type VideoGallerySelector = (state: CallClientState, props: CallingBaseSe optimalVideoCount?: number; spotlightedParticipants?: string[]; maxParticipantsToSpotlight?: number; + isTogetherModeActive?: boolean; + startTogetherModeEnabled?: boolean; + togetherModeStreams?: VideoGalleryTogetherModeStreams; + togetherModeSeatingCoordinates?: VideoGalleryTogetherModeParticipantPosition; }; // @public From 09acf48b5cb4143595f638475493047a16ab6e91 Mon Sep 17 00:00:00 2001 From: Chukwuebuka Nwankwo Date: Thu, 23 Jan 2025 20:37:47 +0000 Subject: [PATCH 2/2] Change files --- ...cation-react-78a7f897-1bb2-46b1-8734-39b60d38c251.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 change-beta/@azure-communication-react-78a7f897-1bb2-46b1-8734-39b60d38c251.json diff --git a/change-beta/@azure-communication-react-78a7f897-1bb2-46b1-8734-39b60d38c251.json b/change-beta/@azure-communication-react-78a7f897-1bb2-46b1-8734-39b60d38c251.json new file mode 100644 index 00000000000..23e128b04dd --- /dev/null +++ b/change-beta/@azure-communication-react-78a7f897-1bb2-46b1-8734-39b60d38c251.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "area": "feature", + "workstream": "together-mode", + "comment": "Cleanup code logic", + "packageName": "@azure/communication-react", + "dependentChangeType": "patch" +}