@azure/communication-react 1.11.0-alpha-202312070013 → 1.11.0-alpha-202312080012

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/communication-react.d.ts +3 -1
  2. package/dist/dist-cjs/communication-react/index.js +199 -120
  3. package/dist/dist-cjs/communication-react/index.js.map +1 -1
  4. package/dist/dist-esm/acs-ui-common/src/telemetry.js +3 -1
  5. package/dist/dist-esm/acs-ui-common/src/telemetry.js.map +1 -1
  6. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  7. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  8. package/dist/dist-esm/calling-stateful-client/src/CallContext.d.ts +2 -2
  9. package/dist/dist-esm/calling-stateful-client/src/CallContext.js +22 -7
  10. package/dist/dist-esm/calling-stateful-client/src/CallContext.js.map +1 -1
  11. package/dist/dist-esm/calling-stateful-client/src/CallSubscriber.js +23 -45
  12. package/dist/dist-esm/calling-stateful-client/src/CallSubscriber.js.map +1 -1
  13. package/dist/dist-esm/calling-stateful-client/src/InternalCallContext.d.ts +9 -11
  14. package/dist/dist-esm/calling-stateful-client/src/InternalCallContext.js +28 -13
  15. package/dist/dist-esm/calling-stateful-client/src/InternalCallContext.js.map +1 -1
  16. package/dist/dist-esm/calling-stateful-client/src/StreamUtils.js +52 -40
  17. package/dist/dist-esm/calling-stateful-client/src/StreamUtils.js.map +1 -1
  18. package/dist/dist-esm/calling-stateful-client/src/StreamUtilsLogging.d.ts +1 -1
  19. package/dist/dist-esm/calling-stateful-client/src/StreamUtilsLogging.js.map +1 -1
  20. package/dist/dist-esm/react-components/src/components/LocalVideoCameraButton.d.ts +2 -0
  21. package/dist/dist-esm/react-components/src/components/LocalVideoCameraButton.js +2 -2
  22. package/dist/dist-esm/react-components/src/components/LocalVideoCameraButton.js.map +1 -1
  23. package/dist/dist-esm/react-components/src/components/VideoGallery.d.ts +1 -1
  24. package/dist/dist-esm/react-components/src/components/VideoGallery.js +8 -6
  25. package/dist/dist-esm/react-components/src/components/VideoGallery.js.map +1 -1
  26. package/dist/dist-esm/react-components/src/components/styles/MessageThread.styles.js +14 -0
  27. package/dist/dist-esm/react-components/src/components/styles/MessageThread.styles.js.map +1 -1
  28. package/dist/dist-esm/react-components/src/components/styles/VideoGallery.styles.d.ts +1 -1
  29. package/dist/dist-esm/react-components/src/components/styles/VideoGallery.styles.js +3 -3
  30. package/dist/dist-esm/react-components/src/components/styles/VideoGallery.styles.js.map +1 -1
  31. package/dist/dist-esm/react-components/src/theming/v9ThemeShim.js +1 -1
  32. package/dist/dist-esm/react-components/src/theming/v9ThemeShim.js.map +1 -1
  33. package/dist/dist-esm/react-composites/src/composites/CallComposite/CallComposite.js +2 -0
  34. package/dist/dist-esm/react-composites/src/composites/CallComposite/CallComposite.js.map +1 -1
  35. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/LobbyTile.d.ts +1 -0
  36. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/LobbyTile.js +8 -2
  37. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/LobbyTile.js.map +1 -1
  38. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/LobbyPage.js +1 -1
  39. package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/LobbyPage.js.map +1 -1
  40. package/dist/dist-esm/react-composites/src/composites/CallComposite/styles/LobbyTile.styles.d.ts +5 -1
  41. package/dist/dist-esm/react-composites/src/composites/CallComposite/styles/LobbyTile.styles.js +6 -0
  42. package/dist/dist-esm/react-composites/src/composites/CallComposite/styles/LobbyTile.styles.js.map +1 -1
  43. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.d.ts +8 -0
  44. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js +8 -4
  45. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js.map +1 -1
  46. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/useConsoleErrors.d.ts +6 -0
  47. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/useConsoleErrors.js +31 -0
  48. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/useConsoleErrors.js.map +1 -0
  49. package/package.json +1 -1
@@ -176,7 +176,7 @@ const _isValidIdentifier = (identifier) => {
176
176
  // Copyright (c) Microsoft Corporation.
177
177
  // Licensed under the MIT License.
178
178
  // GENERATED FILE. DO NOT EDIT MANUALLY.
179
- var telemetryVersion = '1.11.0-alpha-202312070013';
179
+ var telemetryVersion = '1.11.0-alpha-202312080012';
180
180
 
181
181
  // Copyright (c) Microsoft Corporation.
182
182
  /**
@@ -226,7 +226,9 @@ const getTelemetryImplementationHint = (telemetryImplementationHint) => {
226
226
  * @internal
227
227
  */
228
228
  const _getApplicationId = (telemetryImplementationHint) => {
229
- const highLevelArtifact = 0;
229
+ // We assume AzureCommunicationLibrary, as we don't currently have any public API to inject otherwise.
230
+ // This is consistent with the native iOS and Android implementations of telemetry.
231
+ const highLevelArtifact = 1;
230
232
  const specificImplementation = getTelemetryImplementationHint(telemetryImplementationHint);
231
233
  const implementationDetails = 0;
232
234
  const version = telemetryVersion;
@@ -1983,11 +1985,25 @@ class CallContext$2 {
1983
1985
  }
1984
1986
  });
1985
1987
  }
1986
- setCallLocalVideoStream(callId, streams) {
1988
+ setCallLocalVideoStream(callId, streamsAdded, streamsRemoved) {
1987
1989
  this.modifyState((draft) => {
1988
1990
  const call = draft.calls[this._callIdHistory.latestCallId(callId)];
1989
1991
  if (call) {
1990
- call.localVideoStreams = streams;
1992
+ for (const removedStream of streamsRemoved) {
1993
+ const index = call.localVideoStreams.findIndex((i) => i.mediaStreamType === removedStream.mediaStreamType);
1994
+ if (index > -1) {
1995
+ call.localVideoStreams.splice(index, 1);
1996
+ }
1997
+ }
1998
+ for (const addedStream of streamsAdded) {
1999
+ const index = call.localVideoStreams.findIndex((i) => i.mediaStreamType === addedStream.mediaStreamType);
2000
+ if (index > -1) {
2001
+ call.localVideoStreams[index] = addedStream;
2002
+ }
2003
+ else {
2004
+ call.localVideoStreams.push(addedStream);
2005
+ }
2006
+ }
1991
2007
  }
1992
2008
  });
1993
2009
  }
@@ -2101,12 +2117,13 @@ class CallContext$2 {
2101
2117
  }
2102
2118
  });
2103
2119
  }
2104
- setLocalVideoStreamRendererView(callId, view) {
2120
+ setLocalVideoStreamRendererView(callId, localVideoMediaStreamType, view) {
2105
2121
  this.modifyState((draft) => {
2106
2122
  const call = draft.calls[this._callIdHistory.latestCallId(callId)];
2107
2123
  if (call) {
2108
- if (call.localVideoStreams.length > 0) {
2109
- call.localVideoStreams[0].view = view;
2124
+ const localVideoStream = call.localVideoStreams.find((localVideoStream) => localVideoStream.mediaStreamType === localVideoMediaStreamType);
2125
+ if (localVideoStream) {
2126
+ localVideoStream.view = view;
2110
2127
  }
2111
2128
  }
2112
2129
  });
@@ -2388,7 +2405,7 @@ class CallContext$2 {
2388
2405
  }
2389
2406
  deleteDeviceManagerUnparentedView(localVideoStream) {
2390
2407
  this.modifyState((draft) => {
2391
- const foundIndex = draft.deviceManager.unparentedViews.findIndex((stream) => stream.source.id === localVideoStream.source.id && stream.mediaStreamType === localVideoStream.mediaStreamType);
2408
+ const foundIndex = draft.deviceManager.unparentedViews.findIndex((stream) => stream.mediaStreamType === localVideoStream.mediaStreamType);
2392
2409
  if (foundIndex !== -1) {
2393
2410
  draft.deviceManager.unparentedViews.splice(foundIndex, 1);
2394
2411
  }
@@ -2397,7 +2414,7 @@ class CallContext$2 {
2397
2414
  /* @conditional-compile-remove(video-background-effects) */
2398
2415
  setDeviceManagerUnparentedViewVideoEffects(localVideoStream, videoEffects) {
2399
2416
  this.modifyState((draft) => {
2400
- const foundIndex = draft.deviceManager.unparentedViews.findIndex((stream) => stream.source.id === localVideoStream.source.id && stream.mediaStreamType === localVideoStream.mediaStreamType);
2417
+ const foundIndex = draft.deviceManager.unparentedViews.findIndex((stream) => stream.mediaStreamType === localVideoStream.mediaStreamType);
2401
2418
  if (foundIndex !== -1) {
2402
2419
  draft.deviceManager.unparentedViews[foundIndex].videoEffects = videoEffects;
2403
2420
  }
@@ -2996,20 +3013,27 @@ function createViewVideo(context, internalContext, callId, stream, participantId
2996
3013
  throw new Error('unparented createView not implemented yet here');
2997
3014
  }
2998
3015
  const streamType = stream === null || stream === void 0 ? void 0 : stream.mediaStreamType;
2999
- const streamId = stream.id;
3016
+ const localStreamKey = stream.mediaStreamType;
3017
+ const remoteStreamId = stream.id;
3000
3018
  // we want to check to see if there is a participantId this will tell us whether its a local stream or a remote one.
3001
3019
  const participantKey = streamEventType === 'createViewRemote' && participantId
3002
3020
  ? typeof participantId === 'string'
3003
3021
  ? participantId
3004
3022
  : toFlatCommunicationIdentifier(participantId)
3005
3023
  : undefined;
3006
- const streamLogInfo = { callId, participantKey, streamId, streamType, streamEventType };
3024
+ const streamLogInfo = {
3025
+ callId,
3026
+ participantKey,
3027
+ streamId: remoteStreamId !== null && remoteStreamId !== void 0 ? remoteStreamId : localStreamKey,
3028
+ streamType,
3029
+ streamEventType
3030
+ };
3007
3031
  // make different logging announcement based on whether or not we are starting a local or remote
3008
3032
  _logStreamEvent(EventNames.CREATING_VIEW, streamLogInfo);
3009
3033
  // if we have a participant Id and a stream get the remote info, else get the local render info from state.
3010
3034
  const renderInfo = streamEventType === 'createViewRemote' && participantKey
3011
- ? internalContext.getRemoteRenderInfoForParticipant(callId, participantKey, streamId)
3012
- : internalContext.getLocalRenderInfo(callId);
3035
+ ? internalContext.getRemoteRenderInfoForParticipant(callId, participantKey, remoteStreamId)
3036
+ : internalContext.getLocalRenderInfo(callId, localStreamKey);
3013
3037
  if (!renderInfo) {
3014
3038
  _logStreamEvent(EventNames.STREAM_NOT_FOUND, streamLogInfo);
3015
3039
  return;
@@ -3029,18 +3053,18 @@ function createViewVideo(context, internalContext, callId, stream, participantId
3029
3053
  if (renderInfo.status === 'Stopping') {
3030
3054
  if (streamEventType === 'createViewRemote' && participantKey) {
3031
3055
  _logStreamEvent(EventNames.STREAM_STOPPING, streamLogInfo);
3032
- internalContext.setRemoteRenderInfo(callId, participantKey, streamId, renderInfo.stream, 'Rendering', renderInfo.renderer);
3056
+ internalContext.setRemoteRenderInfo(callId, participantKey, remoteStreamId, renderInfo.stream, 'Rendering', renderInfo.renderer);
3033
3057
  }
3034
3058
  else if (streamEventType === 'createViewLocal') {
3035
3059
  _logStreamEvent(EventNames.STREAM_STOPPING, streamLogInfo);
3036
- internalContext.setLocalRenderInfo(callId, renderInfo.stream, 'Rendering', renderInfo.renderer);
3060
+ internalContext.setLocalRenderInfo(callId, localStreamKey, renderInfo.stream, 'Rendering', renderInfo.renderer);
3037
3061
  }
3038
3062
  return;
3039
3063
  }
3040
3064
  const renderer = new communicationCalling.VideoStreamRenderer(renderInfo.stream);
3041
3065
  streamEventType === 'createViewRemote' && participantKey
3042
- ? internalContext.setRemoteRenderInfo(callId, participantKey, streamId, renderInfo.stream, 'Rendering', undefined)
3043
- : internalContext.setLocalRenderInfo(callId, renderInfo.stream, 'Rendering', renderer);
3066
+ ? internalContext.setRemoteRenderInfo(callId, participantKey, remoteStreamId, renderInfo.stream, 'Rendering', undefined)
3067
+ : internalContext.setLocalRenderInfo(callId, localStreamKey, renderInfo.stream, 'Rendering', renderer);
3044
3068
  let view;
3045
3069
  try {
3046
3070
  view = yield renderer.createView(options);
@@ -3048,52 +3072,52 @@ function createViewVideo(context, internalContext, callId, stream, participantId
3048
3072
  catch (e) {
3049
3073
  if (streamEventType === 'createViewRemote' && participantKey) {
3050
3074
  _logStreamEvent(EventNames.CREATE_STREAM_FAIL, streamLogInfo);
3051
- internalContext.setRemoteRenderInfo(callId, participantKey, streamId, renderInfo.stream, 'NotRendered', undefined);
3075
+ internalContext.setRemoteRenderInfo(callId, participantKey, remoteStreamId, renderInfo.stream, 'NotRendered', undefined);
3052
3076
  }
3053
3077
  else if (streamEventType === 'createViewLocal') {
3054
3078
  _logStreamEvent(EventNames.CREATE_STREAM_FAIL, streamLogInfo, e);
3055
- internalContext.setLocalRenderInfo(callId, renderInfo.stream, 'NotRendered', undefined);
3079
+ internalContext.setLocalRenderInfo(callId, localStreamKey, renderInfo.stream, 'NotRendered', undefined);
3056
3080
  }
3057
3081
  throw e;
3058
3082
  }
3059
3083
  // Since render could take some time, we need to check if the stream is still valid and if we received a signal to
3060
3084
  // stop rendering.
3061
3085
  const refreshedRenderInfo = streamEventType === 'createViewRemote' && participantKey
3062
- ? internalContext.getRemoteRenderInfoForParticipant(callId, participantKey, streamId)
3063
- : internalContext.getLocalRenderInfo(callId);
3086
+ ? internalContext.getRemoteRenderInfoForParticipant(callId, participantKey, remoteStreamId)
3087
+ : internalContext.getLocalRenderInfo(callId, localStreamKey);
3064
3088
  if (!refreshedRenderInfo) {
3065
3089
  // RenderInfo was removed. This should not happen unless stream was removed from the call so dispose the renderer
3066
3090
  // and clean up the state.
3067
3091
  _logStreamEvent(EventNames.RENDER_INFO_NOT_FOUND, streamLogInfo);
3068
3092
  renderer.dispose();
3069
3093
  streamEventType === 'createViewRemote' && participantKey
3070
- ? context.setRemoteVideoStreamRendererView(callId, participantKey, streamId, undefined)
3071
- : context.setLocalVideoStreamRendererView(callId, undefined);
3094
+ ? context.setRemoteVideoStreamRendererView(callId, participantKey, remoteStreamId, undefined)
3095
+ : context.setLocalVideoStreamRendererView(callId, localStreamKey, undefined);
3072
3096
  return;
3073
3097
  }
3074
3098
  if (refreshedRenderInfo.status === 'Stopping') {
3075
3099
  _logStreamEvent(EventNames.CREATED_STREAM_STOPPING, streamLogInfo);
3076
3100
  renderer.dispose();
3077
3101
  if (streamEventType === 'createViewRemote' && participantKey) {
3078
- internalContext.setRemoteRenderInfo(callId, participantKey, streamId, refreshedRenderInfo.stream, 'NotRendered', undefined);
3079
- context.setRemoteVideoStreamRendererView(callId, participantKey, streamId, undefined);
3102
+ internalContext.setRemoteRenderInfo(callId, participantKey, remoteStreamId, refreshedRenderInfo.stream, 'NotRendered', undefined);
3103
+ context.setRemoteVideoStreamRendererView(callId, participantKey, remoteStreamId, undefined);
3080
3104
  }
3081
3105
  else if (streamEventType === 'createViewLocal') {
3082
- internalContext.setLocalRenderInfo(callId, refreshedRenderInfo.stream, 'NotRendered', undefined);
3083
- context.setLocalVideoStreamRendererView(callId, undefined);
3106
+ internalContext.setLocalRenderInfo(callId, localStreamKey, refreshedRenderInfo.stream, 'NotRendered', undefined);
3107
+ context.setLocalVideoStreamRendererView(callId, localStreamKey, undefined);
3084
3108
  }
3085
3109
  return;
3086
3110
  }
3087
3111
  // Else the stream still exists and status is not telling us to stop rendering. Complete the render process by
3088
3112
  // updating the state.
3089
3113
  if (streamEventType === 'createViewRemote' && participantKey) {
3090
- internalContext.setRemoteRenderInfo(callId, participantKey, streamId, refreshedRenderInfo.stream, 'Rendered', renderer);
3091
- context.setRemoteVideoStreamRendererView(callId, participantKey, streamId, convertFromSDKToDeclarativeVideoStreamRendererView(view));
3114
+ internalContext.setRemoteRenderInfo(callId, participantKey, remoteStreamId, refreshedRenderInfo.stream, 'Rendered', renderer);
3115
+ context.setRemoteVideoStreamRendererView(callId, participantKey, remoteStreamId, convertFromSDKToDeclarativeVideoStreamRendererView(view));
3092
3116
  _logStreamEvent(EventNames.VIEW_RENDER_SUCCEED, streamLogInfo);
3093
3117
  }
3094
3118
  else if (streamEventType === 'createViewLocal') {
3095
- internalContext.setLocalRenderInfo(callId, refreshedRenderInfo.stream, 'Rendered', renderer);
3096
- context.setLocalVideoStreamRendererView(callId, convertFromSDKToDeclarativeVideoStreamRendererView(view));
3119
+ internalContext.setLocalRenderInfo(callId, localStreamKey, refreshedRenderInfo.stream, 'Rendered', renderer);
3120
+ context.setLocalVideoStreamRendererView(callId, localStreamKey, convertFromSDKToDeclarativeVideoStreamRendererView(view));
3097
3121
  _logStreamEvent(EventNames.VIEW_RENDER_SUCCEED, streamLogInfo);
3098
3122
  }
3099
3123
  return {
@@ -3177,21 +3201,22 @@ function disposeViewVideo(context, internalContext, callId, stream, participantI
3177
3201
  streamEventType = 'disposeViewUnparented';
3178
3202
  }
3179
3203
  const streamType = stream.mediaStreamType;
3180
- const streamId = stream.id;
3204
+ const localStreamKey = stream.mediaStreamType;
3205
+ const remoteStreamId = stream.id;
3181
3206
  // we want to check to see if there is a participantId this will tell us whether its a local stream or a remote one.
3182
3207
  const participantKey = streamEventType === 'disposeViewRemote' && participantId
3183
3208
  ? typeof participantId === 'string'
3184
3209
  ? participantId
3185
3210
  : toFlatCommunicationIdentifier(participantId)
3186
3211
  : undefined;
3187
- const streamLogInfo = { callId, participantKey, streamId, streamType };
3212
+ const streamLogInfo = { callId, participantKey, streamId: remoteStreamId !== null && remoteStreamId !== void 0 ? remoteStreamId : localStreamKey, streamType };
3188
3213
  _logStreamEvent(EventNames.START_DISPOSE_STREAM, streamLogInfo);
3189
3214
  if (streamEventType === 'disposeViewRemote' && participantKey) {
3190
- context.setRemoteVideoStreamRendererView(callId, participantKey, streamId, undefined);
3215
+ context.setRemoteVideoStreamRendererView(callId, participantKey, remoteStreamId, undefined);
3191
3216
  }
3192
3217
  const renderInfo = streamEventType === 'disposeViewRemote' && participantKey
3193
- ? internalContext.getRemoteRenderInfoForParticipant(callId, participantKey, streamId)
3194
- : internalContext.getLocalRenderInfo(callId);
3218
+ ? internalContext.getRemoteRenderInfoForParticipant(callId, participantKey, remoteStreamId)
3219
+ : internalContext.getLocalRenderInfo(callId, localStreamKey);
3195
3220
  if (!renderInfo) {
3196
3221
  _logStreamEvent(EventNames.DISPOSE_INFO_NOT_FOUND, streamLogInfo);
3197
3222
  return;
@@ -3214,8 +3239,8 @@ function disposeViewVideo(context, internalContext, callId, stream, participantI
3214
3239
  if (renderInfo.status === 'Rendering') {
3215
3240
  _logStreamEvent(EventNames.STREAM_STOPPING, streamLogInfo);
3216
3241
  streamEventType === 'disposeViewRemote' && participantKey
3217
- ? internalContext.setRemoteRenderInfo(callId, participantKey, streamId, renderInfo.stream, 'Stopping', undefined)
3218
- : internalContext.setLocalRenderInfo(callId, renderInfo.stream, 'Stopping', renderInfo.renderer);
3242
+ ? internalContext.setRemoteRenderInfo(callId, participantKey, remoteStreamId, renderInfo.stream, 'Stopping', undefined)
3243
+ : internalContext.setLocalRenderInfo(callId, localStreamKey, renderInfo.stream, 'Stopping', renderInfo.renderer);
3219
3244
  return;
3220
3245
  }
3221
3246
  if (renderInfo.renderer) {
@@ -3223,11 +3248,11 @@ function disposeViewVideo(context, internalContext, callId, stream, participantI
3223
3248
  renderInfo.renderer.dispose();
3224
3249
  // Else the state must be in the "Rendered" state, so we can dispose the renderer and clean up the state.
3225
3250
  if (streamEventType === 'disposeViewRemote' && participantKey) {
3226
- internalContext.setRemoteRenderInfo(callId, participantKey, streamId, renderInfo.stream, 'NotRendered', undefined);
3251
+ internalContext.setRemoteRenderInfo(callId, participantKey, remoteStreamId, renderInfo.stream, 'NotRendered', undefined);
3227
3252
  }
3228
3253
  else if (streamEventType === 'disposeViewLocal') {
3229
- internalContext.setLocalRenderInfo(callId, renderInfo.stream, 'NotRendered', undefined);
3230
- context.setLocalVideoStreamRendererView(callId, undefined);
3254
+ internalContext.setLocalRenderInfo(callId, localStreamKey, renderInfo.stream, 'NotRendered', undefined);
3255
+ context.setLocalVideoStreamRendererView(callId, localStreamKey, undefined);
3231
3256
  }
3232
3257
  }
3233
3258
  else {
@@ -3302,9 +3327,9 @@ function disposeView(context, internalContext, callId, participantId, stream) {
3302
3327
  * Only stops videos that are tied to a Call.
3303
3328
  */
3304
3329
  function disposeAllViewsFromCall(context, internalContext, callId) {
3305
- const callStreams = internalContext.getRemoteRenderInfoForCall(callId);
3306
- if (callStreams) {
3307
- for (const [participantKey, participantStreams] of callStreams.entries()) {
3330
+ const remoteStreams = internalContext.getRemoteRenderInfoForCall(callId);
3331
+ if (remoteStreams) {
3332
+ for (const [participantKey, participantStreams] of remoteStreams.entries()) {
3308
3333
  for (const [_, remoteStreamAndRenderer] of participantStreams.entries()) {
3309
3334
  // We don't want to accept SDK stream as parameter but we also don't cache the declarative stream so we have to
3310
3335
  // convert the SDK stream to declarative stream which is not pretty so this could use some further refactoring.
@@ -3312,11 +3337,15 @@ function disposeAllViewsFromCall(context, internalContext, callId) {
3312
3337
  }
3313
3338
  }
3314
3339
  }
3315
- const localStreamAndRenderer = internalContext.getLocalRenderInfo(callId);
3316
- if (localStreamAndRenderer && localStreamAndRenderer.renderer) {
3317
- // We don't want to accept SDK stream as parameter but we also don't cache the declarative stream so we have to
3318
- // convert the SDK stream to declarative stream which is not pretty so this could use some further refactoring.
3319
- disposeView(context, internalContext, callId, undefined, convertSdkLocalStreamToDeclarativeLocalStream(localStreamAndRenderer.stream));
3340
+ const localStreams = internalContext.getLocalRenderInfosForCall(callId);
3341
+ if (localStreams) {
3342
+ for (const localStreamAndRenderer of localStreams.values()) {
3343
+ if (localStreamAndRenderer && localStreamAndRenderer.renderer) {
3344
+ // We don't want to accept SDK stream as parameter but we also don't cache the declarative stream so we have to
3345
+ // convert the SDK stream to declarative stream which is not pretty so this could use some further refactoring.
3346
+ disposeView(context, internalContext, callId, undefined, convertSdkLocalStreamToDeclarativeLocalStream(localStreamAndRenderer.stream));
3347
+ }
3348
+ }
3320
3349
  }
3321
3350
  }
3322
3351
  /**
@@ -3650,9 +3679,8 @@ class CallSubscriber {
3650
3679
  this._call.feature(communicationCalling.Features.DominantSpeakers).on('dominantSpeakersChanged', this.dominantSpeakersChanged);
3651
3680
  /* @conditional-compile-remove(total-participant-count) */
3652
3681
  this._call.on('totalParticipantCountChanged', this.totalParticipantCountChangedHandler);
3653
- // At time of writing only one LocalVideoStream is supported by SDK.
3654
- if (this._call.localVideoStreams.length > 0) {
3655
- this._internalContext.setLocalRenderInfo(this._callIdRef.callId, this._call.localVideoStreams[0], 'NotRendered', undefined);
3682
+ for (const localVideoStream of this._call.localVideoStreams) {
3683
+ this._internalContext.setLocalRenderInfo(this._callIdRef.callId, localVideoStream.mediaStreamType, localVideoStream, 'NotRendered', undefined);
3656
3684
  }
3657
3685
  if (this._call.remoteParticipants.length > 0) {
3658
3686
  this._call.remoteParticipants.forEach((participant) => {
@@ -3681,10 +3709,11 @@ class CallSubscriber {
3681
3709
  this._participantSubscribers.clear();
3682
3710
  // If we are unsubscribing that means we no longer want to display any video for this call (callEnded or callAgent
3683
3711
  // disposed) and we should not be updating it any more. So if video is rendering we stop rendering.
3684
- if (this._call.localVideoStreams && this._call.localVideoStreams[0]) {
3685
- disposeView(this._context, this._internalContext, this._callIdRef.callId, undefined, convertSdkLocalStreamToDeclarativeLocalStream(this._call.localVideoStreams[0]));
3712
+ for (const localVideoStream of this._call.localVideoStreams) {
3713
+ const mediaStreamType = localVideoStream.mediaStreamType;
3714
+ disposeView(this._context, this._internalContext, this._callIdRef.callId, undefined, convertSdkLocalStreamToDeclarativeLocalStream(localVideoStream));
3715
+ this._internalContext.deleteLocalRenderInfo(this._callIdRef.callId, mediaStreamType);
3686
3716
  }
3687
- this._internalContext.deleteLocalRenderInfo(this._callIdRef.callId);
3688
3717
  this._diagnosticsSubscriber.unsubscribe();
3689
3718
  this._recordingSubscriber.unsubscribe();
3690
3719
  this._transcriptionSubscriber.unsubscribe();
@@ -3748,49 +3777,27 @@ class CallSubscriber {
3748
3777
  };
3749
3778
  this.localVideoStreamsUpdated = (event) => {
3750
3779
  var _a, _b;
3751
- // Exclude screenshare streams from added local video streams
3752
- const addedLocalVideoStreamsExcludingScreenShare = event.added.filter((localVideoStream) => localVideoStream.mediaStreamType !== 'ScreenSharing');
3753
- // At time of writing only one LocalVideoStream is supported by SDK.
3754
- if (addedLocalVideoStreamsExcludingScreenShare.length > 0) {
3780
+ for (const localVideoStream of event.added) {
3781
+ const mediaStreamType = localVideoStream.mediaStreamType;
3755
3782
  // IMPORTANT: The internalContext should be set before context. This is done to ensure that the internal context
3756
3783
  // has the required data when component re-renders due to external state changes.
3757
- this._internalContext.setLocalRenderInfo(this._callIdRef.callId, addedLocalVideoStreamsExcludingScreenShare[0], 'NotRendered', undefined);
3758
- const currentLocalVideoStreams = this._call.localVideoStreams;
3759
- const localVideoStreams = addedLocalVideoStreamsExcludingScreenShare
3760
- .concat(currentLocalVideoStreams)
3761
- .map((stream) => convertSdkLocalStreamToDeclarativeLocalStream(stream));
3762
- this._context.setCallLocalVideoStream(this._callIdRef.callId, localVideoStreams);
3763
- /* @conditional-compile-remove(video-background-effects) */
3764
- {
3765
- // Subscribe to video effect changes
3766
- const localVideoStreamKey = event.added[0].source.id;
3767
- (_a = this._localVideoStreamVideoEffectsSubscribers.get(localVideoStreamKey)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
3768
- this._localVideoStreamVideoEffectsSubscribers.set(localVideoStreamKey, new LocalVideoStreamVideoEffectsSubscriber({
3769
- parent: this._callIdRef,
3770
- context: this._context,
3771
- localVideoStream: this._call.localVideoStreams[0],
3772
- localVideoStreamEffectsAPI: this._call.localVideoStreams[0].feature(communicationCalling.Features.VideoEffects)
3773
- }));
3774
- }
3784
+ this._internalContext.setLocalRenderInfo(this._callIdRef.callId, mediaStreamType, localVideoStream, 'NotRendered', undefined);
3785
+ // Subscribe to video effect changes
3786
+ (_a = this._localVideoStreamVideoEffectsSubscribers.get(mediaStreamType)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
3787
+ this._localVideoStreamVideoEffectsSubscribers.set(mediaStreamType, new LocalVideoStreamVideoEffectsSubscriber({
3788
+ parent: this._callIdRef,
3789
+ context: this._context,
3790
+ localVideoStream: localVideoStream,
3791
+ localVideoStreamEffectsAPI: localVideoStream.feature(communicationCalling.Features.VideoEffects)
3792
+ }));
3775
3793
  }
3776
- if (event.removed.length > 0) {
3777
- /* @conditional-compile-remove(video-background-effects) */
3778
- {
3779
- const localVideoStreamKey = event.removed[0].source.id;
3780
- (_b = this._localVideoStreamVideoEffectsSubscribers.get(localVideoStreamKey)) === null || _b === void 0 ? void 0 : _b.unsubscribe();
3781
- }
3782
- disposeView(this._context, this._internalContext, this._callIdRef.callId, undefined, convertSdkLocalStreamToDeclarativeLocalStream(event.removed[0]));
3783
- /**
3784
- * This check is to make sure that we are not deleting the local render info for the local video stream if there is one.
3785
- *
3786
- * TODO: we need to make sure the we are supporting the local screenshare stream that is now being tracked. This is a stop gap solution.
3787
- */
3788
- if (event.removed[0].mediaStreamType === 'ScreenSharing') {
3789
- return;
3790
- }
3791
- this._internalContext.deleteLocalRenderInfo(this._callIdRef.callId);
3792
- this._context.setCallLocalVideoStream(this._callIdRef.callId, []);
3794
+ for (const localVideoStream of event.removed) {
3795
+ const mediaStreamType = localVideoStream.mediaStreamType;
3796
+ (_b = this._localVideoStreamVideoEffectsSubscribers.get(mediaStreamType)) === null || _b === void 0 ? void 0 : _b.unsubscribe();
3797
+ disposeView(this._context, this._internalContext, this._callIdRef.callId, undefined, convertSdkLocalStreamToDeclarativeLocalStream(localVideoStream));
3798
+ this._internalContext.deleteLocalRenderInfo(this._callIdRef.callId, mediaStreamType);
3793
3799
  }
3800
+ this._context.setCallLocalVideoStream(this._callIdRef.callId, event.added.map(convertSdkLocalStreamToDeclarativeLocalStream), event.removed.map(convertSdkLocalStreamToDeclarativeLocalStream));
3794
3801
  };
3795
3802
  this.dominantSpeakersChanged = () => {
3796
3803
  const dominantSpeakers = this._call.feature(communicationCalling.Features.DominantSpeakers).dominantSpeakers;
@@ -4412,10 +4419,9 @@ class InternalCallContext {
4412
4419
  constructor() {
4413
4420
  // <CallId, <ParticipantKey, <StreamId, RemoteRenderInfo>>
4414
4421
  this._remoteRenderInfos = new Map();
4415
- // <CallId, LocalRenderInfo>.
4422
+ // <CallId, <MediaStreamType, LocalRenderInfo>>.
4416
4423
  this._localRenderInfos = new Map();
4417
4424
  // Used for keeping track of rendered LocalVideoStreams that are not part of a Call.
4418
- // The key is the stream ID. We assume each stream ID to only have one owning render info
4419
4425
  this._unparentedRenderInfos = new Map();
4420
4426
  this._callIdHistory = new CallIdHistory();
4421
4427
  // Used for keeping track of video effects subscribers that are not part of a Call.
@@ -4477,37 +4483,53 @@ class InternalCallContext {
4477
4483
  }
4478
4484
  participantRenderInfos.delete(streamId);
4479
4485
  }
4480
- setLocalRenderInfo(callId, stream, status, renderer) {
4481
- this._localRenderInfos.set(this._callIdHistory.latestCallId(callId), { stream, status, renderer });
4486
+ setLocalRenderInfo(callId, streamKey, stream, status, renderer) {
4487
+ let localRenderInfosForCall = this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
4488
+ if (!localRenderInfosForCall) {
4489
+ localRenderInfosForCall = new Map();
4490
+ this._localRenderInfos.set(this._callIdHistory.latestCallId(callId), localRenderInfosForCall);
4491
+ }
4492
+ localRenderInfosForCall.set(streamKey, { stream, status, renderer });
4482
4493
  }
4483
- getLocalRenderInfo(callId) {
4494
+ getLocalRenderInfosForCall(callId) {
4484
4495
  return this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
4485
4496
  }
4486
- deleteLocalRenderInfo(callId) {
4487
- this._localRenderInfos.delete(this._callIdHistory.latestCallId(callId));
4497
+ getLocalRenderInfo(callId, streamKey) {
4498
+ const localRenderInfosForCall = this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
4499
+ if (!localRenderInfosForCall) {
4500
+ return undefined;
4501
+ }
4502
+ return localRenderInfosForCall.get(streamKey);
4503
+ }
4504
+ deleteLocalRenderInfo(callId, streamKey) {
4505
+ const localRenderInfoForCall = this._localRenderInfos.get(this._callIdHistory.latestCallId(callId));
4506
+ if (!localRenderInfoForCall) {
4507
+ return;
4508
+ }
4509
+ localRenderInfoForCall.delete(streamKey);
4488
4510
  }
4489
4511
  getUnparentedRenderInfo(localVideoStream) {
4490
- return this._unparentedRenderInfos.get(localVideoStream.source.id);
4512
+ return this._unparentedRenderInfos.get(localVideoStream.mediaStreamType);
4491
4513
  }
4492
4514
  getUnparentedRenderInfos() {
4493
4515
  return [...this._unparentedRenderInfos].map(([, renderInfo]) => renderInfo.stream);
4494
4516
  }
4495
4517
  setUnparentedRenderInfo(statefulStream, stream, status, renderer) {
4496
- this._unparentedRenderInfos.set(statefulStream.source.id, { stream, status, renderer });
4518
+ this._unparentedRenderInfos.set(statefulStream.mediaStreamType, { stream, status, renderer });
4497
4519
  }
4498
4520
  deleteUnparentedRenderInfo(localVideoStream) {
4499
4521
  var _a;
4500
4522
  /* @conditional-compile-remove(video-background-effects) */
4501
- (_a = this._unparentedViewVideoEffectsSubscriber.get(localVideoStream.source.id)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
4502
- this._unparentedRenderInfos.delete(localVideoStream.source.id);
4523
+ (_a = this._unparentedViewVideoEffectsSubscriber.get(localVideoStream.mediaStreamType)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
4524
+ this._unparentedRenderInfos.delete(localVideoStream.mediaStreamType);
4503
4525
  }
4504
4526
  subscribeToUnparentedViewVideoEffects(localVideoStream, callContext) {
4505
4527
  var _a;
4506
4528
  /* @conditional-compile-remove(video-background-effects) */
4507
4529
  {
4508
4530
  // Ensure we aren't setting multiple subscriptions
4509
- (_a = this._unparentedViewVideoEffectsSubscriber.get(localVideoStream.source.id)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
4510
- this._unparentedViewVideoEffectsSubscriber.set(localVideoStream.source.id, new LocalVideoStreamVideoEffectsSubscriber({
4531
+ (_a = this._unparentedViewVideoEffectsSubscriber.get(localVideoStream.mediaStreamType)) === null || _a === void 0 ? void 0 : _a.unsubscribe();
4532
+ this._unparentedViewVideoEffectsSubscriber.set(localVideoStream.mediaStreamType, new LocalVideoStreamVideoEffectsSubscriber({
4511
4533
  parent: 'unparented',
4512
4534
  context: callContext,
4513
4535
  localVideoStream: localVideoStream,
@@ -8936,6 +8958,20 @@ const useChatMessageStyles = reactComponents.makeStyles({
8936
8958
  }, '& msft-mention': {
8937
8959
  color: reactComponents.tokens.colorStatusWarningBackground3,
8938
8960
  fontWeight: reactComponents.tokens.fontWeightSemibold
8961
+ }, '& img[src=""]': {
8962
+ display: 'block',
8963
+ position: 'relative',
8964
+ marginBottom: '5px'
8965
+ }, '& img[src=""]:after': {
8966
+ backgroundColor: reactComponents.tokens.colorNeutralBackground1Selected,
8967
+ content: `url("data:image/gif;base64,R0lGODlhAQABAAAAACw=")`,
8968
+ backgroundSize: 'center',
8969
+ position: 'absolute',
8970
+ width: '100%',
8971
+ height: '100%',
8972
+ top: '0',
8973
+ left: '0',
8974
+ display: 'block'
8939
8975
  }, '& img': {
8940
8976
  maxWidth: '100% !important',
8941
8977
  height: 'auto !important'
@@ -9438,7 +9474,7 @@ const mapBorderRadiusTokens = (effects) => {
9438
9474
  */
9439
9475
  const createV9Theme = (themeV8, baseThemeV9) => {
9440
9476
  const baseTheme = baseThemeV9 !== null && baseThemeV9 !== void 0 ? baseThemeV9 : reactComponents.webLightTheme;
9441
- return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, baseTheme), mapAliasColors(themeV8.palette, themeV8.isInverted)), mapShadowTokens(themeV8.effects)), mapBorderRadiusTokens(themeV8.effects)), { colorBrandBackground2: themeV8.palette.themeLight, colorBrandBackground2Hover: themeV8.palette.themeLight, colorBrandBackground2Pressed: themeV8.palette.themeLight, colorStatusWarningBackground3: '#D83B01', errorText: themeV8.semanticColors.errorText, colorNeutralStroke1Selected: themeV8.palette.neutralQuaternary, colorNeutralForeground2: themeV8.palette.neutralSecondary, colorBrandForegroundLink: themeV8.palette.themePrimary, colorBrandForegroundLinkHover: themeV8.palette.themeDarker,
9477
+ return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, baseTheme), mapAliasColors(themeV8.palette, themeV8.isInverted)), mapShadowTokens(themeV8.effects)), mapBorderRadiusTokens(themeV8.effects)), { colorBrandBackground2: themeV8.palette.themeLight, colorBrandBackground2Hover: themeV8.palette.themeLight, colorBrandBackground2Pressed: themeV8.palette.themeLight, colorStatusWarningBackground3: '#D83B01', errorText: themeV8.semanticColors.errorText, colorNeutralStroke1Selected: themeV8.palette.neutralQuaternary, colorNeutralForeground2: themeV8.palette.neutralSecondary, colorBrandForegroundLink: themeV8.palette.themePrimary, colorBrandForegroundLinkHover: themeV8.palette.themeDarker, colorNeutralBackground1Selected: themeV8.palette.neutralQuaternaryAlt,
9442
9478
  // Fix for an issue with black borders for iOS that are added with 'after' selector
9443
9479
  colorStrokeFocus2: 'transparent' });
9444
9480
  };
@@ -13210,12 +13246,12 @@ const videoGalleryOuterDivStyle = react.mergeStyles({ position: 'relative', widt
13210
13246
  /**
13211
13247
  * @private
13212
13248
  */
13213
- const localVideoCameraCycleButtonStyles = (theme) => {
13249
+ const localVideoCameraCycleButtonStyles = (theme, size) => {
13214
13250
  return {
13215
13251
  root: {
13216
13252
  position: 'absolute',
13217
- width: _pxToRem(32),
13218
- height: _pxToRem(32),
13253
+ width: size === 'large' ? _pxToRem(40) : _pxToRem(32),
13254
+ height: size === 'large' ? _pxToRem(40) : _pxToRem(32),
13219
13255
  right: '0rem',
13220
13256
  top: '0rem',
13221
13257
  color: '#FFFFFF',
@@ -13252,9 +13288,9 @@ const localVideoTileContainerStyles = {
13252
13288
  * @internal
13253
13289
  */
13254
13290
  const LocalVideoCameraCycleButton = (props) => {
13255
- const { cameras, selectedCamera, onSelectCamera, label, ariaDescription } = props;
13291
+ const { cameras, selectedCamera, onSelectCamera, label, ariaDescription, size } = props;
13256
13292
  const theme = react.useTheme();
13257
- return (React__default["default"].createElement(react.IconButton, { "data-ui-id": 'local-camera-switcher-button', styles: localVideoCameraCycleButtonStyles(theme), iconProps: { iconName: 'LocalCameraSwitch' }, ariaLabel: label, ariaDescription: ariaDescription, "aria-live": 'polite', onClick: () => {
13293
+ return (React__default["default"].createElement(react.IconButton, { "data-ui-id": 'local-camera-switcher-button', styles: localVideoCameraCycleButtonStyles(theme, size), iconProps: { iconName: 'LocalCameraSwitch' }, ariaLabel: label, ariaDescription: ariaDescription, "aria-live": 'polite', onClick: () => {
13258
13294
  if (cameras && cameras.length > 1 && selectedCamera !== undefined) {
13259
13295
  const index = cameras.findIndex((camera) => selectedCamera.id === camera.id);
13260
13296
  const newCamera = cameras[(index + 1) % cameras.length];
@@ -15614,8 +15650,8 @@ const VideoGallery = (props) => {
15614
15650
  : undefined;
15615
15651
  /* @conditional-compile-remove(pinned-participants) */
15616
15652
  const drawerMenuHostId = reactHooks.useId('drawerMenuHost', drawerMenuHostIdFromProp);
15617
- const localTileNotInGrid = !!((layout === 'floatingLocalVideo' || /* @conditional-compile-remove(gallery-layouts) */ layout === 'speaker') &&
15618
- remoteParticipants.length > 0);
15653
+ const localTileNotInGrid = (layout === 'floatingLocalVideo' || /* @conditional-compile-remove(gallery-layouts) */ layout === 'speaker') &&
15654
+ remoteParticipants.length > 0;
15619
15655
  const containerRef = React.useRef(null);
15620
15656
  const containerWidth = _useContainerWidth(containerRef);
15621
15657
  const containerHeight = _useContainerHeight(containerRef);
@@ -15645,6 +15681,9 @@ const VideoGallery = (props) => {
15645
15681
  /* @conditional-compile-remove(pinned-participants) */
15646
15682
  // Use pinnedParticipants from props but if it is not defined use the maintained state of pinned participants
15647
15683
  const pinnedParticipants = (_a = props.pinnedParticipants) !== null && _a !== void 0 ? _a : pinnedParticipantsState;
15684
+ const showLocalVideoTileLabel = !((localTileNotInGrid && isNarrow) ||
15685
+ /*@conditional-compile-remove(click-to-call) */ /* @conditional-compile-remove(rooms) */ localVideoTileSize ===
15686
+ '9:16') || /* @conditional-compile-remove(gallery-layouts) */ layout === 'default';
15648
15687
  /**
15649
15688
  * Utility function for memoized rendering of LocalParticipant.
15650
15689
  */
@@ -15666,9 +15705,7 @@ const VideoGallery = (props) => {
15666
15705
  return layout === 'default' ? strings.localVideoLabel : isNarrow ? '' : strings.localVideoLabel;
15667
15706
  };
15668
15707
  return (React__default["default"].createElement(react.Stack, { styles: localVideoTileContainerStyles, key: "local-video-tile-key", tabIndex: 0, "aria-label": strings.localVideoMovementLabel, role: 'dialog' },
15669
- React__default["default"].createElement(_LocalVideoTile, { userId: localParticipant.userId, onCreateLocalStreamView: onCreateLocalStreamView, onDisposeLocalStreamView: onDisposeLocalStreamView, isAvailable: (_a = localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable, isMuted: localParticipant.isMuted, renderElement: (_b = localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.videoStream) === null || _b === void 0 ? void 0 : _b.renderElement, displayName: showDisplayNameTrampoline(), initialsName: initialsName, localVideoViewOptions: localVideoViewOptions, onRenderAvatar: onRenderAvatar, showLabel: !((localTileNotInGrid && isNarrow) ||
15670
- /*@conditional-compile-remove(click-to-call) */ /* @conditional-compile-remove(rooms) */ localVideoTileSize ===
15671
- '9:16') || /* @conditional-compile-remove(gallery-layouts) */ layout === 'default', showMuteIndicator: showMuteIndicator, showCameraSwitcherInLocalPreview: showCameraSwitcherInLocalPreview, localVideoCameraCycleButtonProps: localVideoCameraCycleButtonProps, localVideoCameraSwitcherLabel: strings.localVideoCameraSwitcherLabel, localVideoSelectedDescription: strings.localVideoSelectedDescription, styles: localVideoTileStyles,
15708
+ React__default["default"].createElement(_LocalVideoTile, { userId: localParticipant.userId, onCreateLocalStreamView: onCreateLocalStreamView, onDisposeLocalStreamView: onDisposeLocalStreamView, isAvailable: (_a = localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable, isMuted: localParticipant.isMuted, renderElement: (_b = localParticipant === null || localParticipant === void 0 ? void 0 : localParticipant.videoStream) === null || _b === void 0 ? void 0 : _b.renderElement, displayName: showDisplayNameTrampoline(), initialsName: initialsName, localVideoViewOptions: localVideoViewOptions, onRenderAvatar: onRenderAvatar, showLabel: showLocalVideoTileLabel, showMuteIndicator: showMuteIndicator, showCameraSwitcherInLocalPreview: showCameraSwitcherInLocalPreview, localVideoCameraCycleButtonProps: localVideoCameraCycleButtonProps, localVideoCameraSwitcherLabel: strings.localVideoCameraSwitcherLabel, localVideoSelectedDescription: strings.localVideoSelectedDescription, styles: localVideoTileStyles,
15672
15709
  /* @conditional-compile-remove(raise-hand) */
15673
15710
  raisedHand: localParticipant.raisedHand })));
15674
15711
  }, [
@@ -15692,7 +15729,8 @@ const VideoGallery = (props) => {
15692
15729
  /*@conditional-compile-remove(click-to-call) */
15693
15730
  localVideoTileSize,
15694
15731
  /* @conditional-compile-remove(gallery-layouts) */
15695
- layout
15732
+ layout,
15733
+ showLocalVideoTileLabel
15696
15734
  ]);
15697
15735
  /* @conditional-compile-remove(pinned-participants) */
15698
15736
  const onPinParticipant = React.useCallback((userId) => {
@@ -23212,12 +23250,16 @@ const REMOVED_FROM_CALL_SUB_CODES = [5000, 5300, REMOTE_PSTN_USER_HUNG_UP];
23212
23250
  /* @conditional-compile-remove(calling-sounds) */
23213
23251
  const CALL_REJECTED_CODE$1 = 603;
23214
23252
  /* @conditional-compile-remove(rooms) */
23253
+ /** @private */
23215
23254
  const ROOM_NOT_FOUND_SUB_CODE = 5732;
23216
23255
  /* @conditional-compile-remove(rooms) */
23256
+ /** @private */
23217
23257
  const ROOM_NOT_VALID_SUB_CODE = 5829;
23218
23258
  /* @conditional-compile-remove(rooms) */
23259
+ /** @private */
23219
23260
  const NOT_INVITED_TO_ROOM_SUB_CODE = 5828;
23220
23261
  /* @conditional-compile-remove(rooms) */
23262
+ /** @private */
23221
23263
  const INVITE_TO_ROOM_REMOVED_SUB_CODE = 5317;
23222
23264
  /**
23223
23265
  * @private
@@ -29499,6 +29541,12 @@ const moreDetailsStyle = (palette, isVideoReady) => ({
29499
29541
  color: isVideoReady ? 'white' : palette.themePrimary,
29500
29542
  textAlign: 'center'
29501
29543
  });
29544
+ /**
29545
+ * @private
29546
+ */
29547
+ const localCameraSwitcherContainerStyles = {
29548
+ root: { position: 'absolute', top: '0rem', right: '0rem' }
29549
+ };
29502
29550
 
29503
29551
  // Copyright (c) Microsoft Corporation.
29504
29552
  /**
@@ -29508,9 +29556,13 @@ const LobbyTile = (props) => {
29508
29556
  var _a;
29509
29557
  const videoStream = props.localParticipantVideoStream;
29510
29558
  const isVideoReady = (_a = videoStream === null || videoStream === void 0 ? void 0 : videoStream.isAvailable) !== null && _a !== void 0 ? _a : false;
29559
+ const cameraSwitcherCameras = useSelector$1(localVideoCameraCycleButtonSelector);
29560
+ const cameraSwitcherCallback = useHandlers();
29511
29561
  const palette = useTheme().palette;
29512
29562
  const handlers = useHandlers();
29513
29563
  return (React__default["default"].createElement(ExpandedLocalVideoTile, Object.assign({ localParticipantVideoStream: props.localParticipantVideoStream, overlayContent: props.overlayProps ? (React__default["default"].createElement(react.Stack, { verticalFill: true, horizontalAlign: "center", verticalAlign: "center", className: react.mergeStyles(overlayContainerStyle), "aria-atomic": true },
29564
+ props.showLocalVideoCameraCycleButton && isVideoReady && (React__default["default"].createElement(react.Stack.Item, { styles: localCameraSwitcherContainerStyles },
29565
+ React__default["default"].createElement(LocalVideoCameraCycleButton, Object.assign({}, cameraSwitcherCallback, cameraSwitcherCameras, { size: 'large' })))),
29514
29566
  React__default["default"].createElement(react.Stack.Item, { className: react.mergeStyles(titleStyle(palette, isVideoReady)) }, props.overlayProps.overlayIcon),
29515
29567
  React__default["default"].createElement(react.Text, { className: react.mergeStyles(titleStyle(palette, isVideoReady)), "aria-live": "assertive", "data-ui-id": "lobbyScreenTitle" }, props.overlayProps.title),
29516
29568
  props.overlayProps.moreDetails && (React__default["default"].createElement(react.Text, { className: react.mergeStyles(moreDetailsStyle(palette, isVideoReady)), "aria-live": "assertive" }, props.overlayProps.moreDetails)))) : undefined }, handlers)));
@@ -29536,7 +29588,7 @@ const LobbyPage = (props) => {
29536
29588
  return (React__default["default"].createElement(CallArrangement, { complianceBannerProps: { strings }, errorBarProps: ((_d = props.options) === null || _d === void 0 ? void 0 : _d.errorBar) !== false && errorBarProps, callControlProps: {
29537
29589
  options: callControlOptions,
29538
29590
  increaseFlyoutItemSize: props.mobileView
29539
- }, mobileView: props.mobileView, modalLayerHostId: props.modalLayerHostId, onRenderGalleryContent: () => (React__default["default"].createElement(LobbyTile, Object.assign({}, lobbyProps, { overlayProps: overlayProps(strings, inLobby, Object.values(participants)) }))), dataUiId: 'lobby-page', updateSidePaneRenderer: props.updateSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader, latestErrors: props.latestErrors, onDismissError: props.onDismissError }));
29591
+ }, mobileView: props.mobileView, modalLayerHostId: props.modalLayerHostId, onRenderGalleryContent: () => (React__default["default"].createElement(LobbyTile, Object.assign({}, lobbyProps, { showLocalVideoCameraCycleButton: props.mobileView, overlayProps: overlayProps(strings, inLobby, Object.values(participants)) }))), dataUiId: 'lobby-page', updateSidePaneRenderer: props.updateSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader, latestErrors: props.latestErrors, onDismissError: props.onDismissError }));
29540
29592
  };
29541
29593
  const overlayProps = (strings, inLobby, remoteParticipants) => {
29542
29594
  /**
@@ -30082,6 +30134,32 @@ const updateLatestCapabilityChangedNotificationMap = (capabilitiesChangedInfoAnd
30082
30134
  return activeNotifications;
30083
30135
  };
30084
30136
 
30137
+ // Copyright (c) Microsoft Corporation.
30138
+ /**
30139
+ * @private
30140
+ */
30141
+ const useEndedCallConsoleErrors = (endedCall) => {
30142
+ var _a;
30143
+ /* @conditional-compile-remove(rooms) */
30144
+ React.useEffect(() => {
30145
+ var _a;
30146
+ switch ((_a = endedCall === null || endedCall === void 0 ? void 0 : endedCall.callEndReason) === null || _a === void 0 ? void 0 : _a.subCode) {
30147
+ case ROOM_NOT_FOUND_SUB_CODE:
30148
+ console.error('Call ended because the room id provided through the adapter locator could not be found');
30149
+ break;
30150
+ case ROOM_NOT_VALID_SUB_CODE:
30151
+ console.error('Call ended because this room is currently not valid.');
30152
+ break;
30153
+ case NOT_INVITED_TO_ROOM_SUB_CODE:
30154
+ console.error('Call ended because you are not invited to this room.');
30155
+ break;
30156
+ case INVITE_TO_ROOM_REMOVED_SUB_CODE:
30157
+ console.error('Call ended because your invite to this room has been removed.');
30158
+ break;
30159
+ }
30160
+ }, [(_a = endedCall === null || endedCall === void 0 ? void 0 : endedCall.callEndReason) === null || _a === void 0 ? void 0 : _a.subCode]);
30161
+ };
30162
+
30085
30163
  // Copyright (c) Microsoft Corporation.
30086
30164
  // Licensed under the MIT License.
30087
30165
  var __awaiter$7 = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
@@ -30232,6 +30310,7 @@ const MainScreen = (props) => {
30232
30310
  capabilitiesChangedNotificationBarProps: capabilitiesChangedNotificationBarProps })));
30233
30311
  break;
30234
30312
  }
30313
+ useEndedCallConsoleErrors(endedCall);
30235
30314
  /* @conditional-compile-remove(unsupported-browser) */
30236
30315
  switch (page) {
30237
30316
  case 'unsupportedEnvironment':