@azure/communication-react 1.5.1-alpha-202306200012 → 1.5.1-alpha-202306210014
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.
- package/README.md +2 -3
- package/dist/dist-cjs/communication-react/index.js +715 -712
- package/dist/dist-cjs/communication-react/index.js.map +1 -1
- package/dist/dist-esm/acs-ui-common/src/identifier.d.ts +6 -0
- package/dist/dist-esm/acs-ui-common/src/identifier.js +12 -1
- package/dist/dist-esm/acs-ui-common/src/identifier.js.map +1 -1
- package/dist/dist-esm/acs-ui-common/src/index.d.ts +1 -1
- package/dist/dist-esm/acs-ui-common/src/index.js +1 -1
- package/dist/dist-esm/acs-ui-common/src/index.js.map +1 -1
- package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
- package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/InputBoxComponent.js +6 -1
- package/dist/dist-esm/react-components/src/components/InputBoxComponent.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/mentionTagUtils.js +1 -1
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/mentionTagUtils.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/AzureCommunicationCallAdapter.js +3 -3
- package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/AzureCommunicationCallAdapter.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.d.ts +0 -9
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js +1 -14
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/ChatComposite/adapter/AzureCommunicationChatAdapter.js +2 -2
- package/dist/dist-esm/react-composites/src/composites/ChatComposite/adapter/AzureCommunicationChatAdapter.js.map +1 -1
- package/package.json +8 -8
@@ -163,11 +163,22 @@ const _toCommunicationIdentifier = (id) => {
|
|
163
163
|
}
|
164
164
|
return id;
|
165
165
|
};
|
166
|
+
/**
|
167
|
+
* Check if an object is identifier.
|
168
|
+
*
|
169
|
+
* @internal
|
170
|
+
*/
|
171
|
+
const _isValidIdentifier = (identifier) => {
|
172
|
+
return (communicationCommon.isCommunicationUserIdentifier(identifier) ||
|
173
|
+
communicationCommon.isPhoneNumberIdentifier(identifier) ||
|
174
|
+
communicationCommon.isMicrosoftTeamsUserIdentifier(identifier) ||
|
175
|
+
communicationCommon.isUnknownIdentifier(identifier));
|
176
|
+
};
|
166
177
|
|
167
178
|
// Copyright (c) Microsoft Corporation.
|
168
179
|
// Licensed under the MIT license.
|
169
180
|
// GENERATED FILE. DO NOT EDIT MANUALLY.
|
170
|
-
var telemetryVersion = '1.5.1-alpha-
|
181
|
+
var telemetryVersion = '1.5.1-alpha-202306210014';
|
171
182
|
|
172
183
|
// Copyright (c) Microsoft Corporation.
|
173
184
|
/**
|
@@ -6311,7 +6322,7 @@ const updateHTML = (props) => {
|
|
6311
6322
|
const updatedHTML = escapeHTMLChars(oldPlainText.substring(0, startIndex)) +
|
6312
6323
|
changeWithSkippedChars +
|
6313
6324
|
escapeHTMLChars(oldPlainText.substring(oldPlainTextEndIndex));
|
6314
|
-
return { updatedHTML, updatedSelectionIndex:
|
6325
|
+
return { updatedHTML, updatedSelectionIndex: undefined };
|
6315
6326
|
}
|
6316
6327
|
let result = '';
|
6317
6328
|
let lastProcessedHTMLIndex = 0;
|
@@ -7655,7 +7666,12 @@ const InputBoxComponent = (props) => {
|
|
7655
7666
|
if (props.mentionLookupOptions) {
|
7656
7667
|
return React__default['default'].createElement(TextFieldWithMention, Object.assign({}, textFieldWithMentionProps));
|
7657
7668
|
}
|
7658
|
-
return (React__default['default'].createElement(react.TextField, Object.assign({}, textFieldProps, { "data-ui-id": dataUiId, value: textValue, onChange: onChange, onKeyDown: onTextFieldKeyDown
|
7669
|
+
return (React__default['default'].createElement(react.TextField, Object.assign({}, textFieldProps, { "data-ui-id": dataUiId, value: textValue, onChange: onChange, onKeyDown: onTextFieldKeyDown, onFocus: (e) => {
|
7670
|
+
// Fix for setting the cursor to the correct position when multiline is true
|
7671
|
+
// This approach should be reviewed during migration to FluentUI v9
|
7672
|
+
e.currentTarget.value = '';
|
7673
|
+
e.currentTarget.value = textValue;
|
7674
|
+
} })));
|
7659
7675
|
};
|
7660
7676
|
return (React__default['default'].createElement(react.Stack, { className: mergedRootStyle },
|
7661
7677
|
React__default['default'].createElement("div", { className: mergedTextContainerStyle }, renderTextField())));
|
@@ -19302,22 +19318,6 @@ const convertObservableFileUploadToFileUploadsUiState = (fileUploads) => {
|
|
19302
19318
|
}, {});
|
19303
19319
|
};
|
19304
19320
|
|
19305
|
-
// Copyright (c) Microsoft Corporation.
|
19306
|
-
// Licensed under the MIT license.
|
19307
|
-
/**
|
19308
|
-
* Subset of CallCompositePages that represent an end call state.
|
19309
|
-
* @private
|
19310
|
-
*/
|
19311
|
-
const END_CALL_PAGES = [
|
19312
|
-
'accessDeniedTeamsMeeting',
|
19313
|
-
'joinCallFailedDueToNoNetwork',
|
19314
|
-
'leftCall',
|
19315
|
-
/* @conditional-compile-remove(rooms) */ 'deniedPermissionToRoom',
|
19316
|
-
'removedFromCall',
|
19317
|
-
/* @conditional-compile-remove(rooms) */ 'roomNotFound',
|
19318
|
-
/* @conditional-compile-remove(unsupported-browser) */ 'unsupportedEnvironment'
|
19319
|
-
];
|
19320
|
-
|
19321
19321
|
// Copyright (c) Microsoft Corporation.
|
19322
19322
|
// Licensed under the MIT license.
|
19323
19323
|
var __awaiter$i = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
|
@@ -19329,498 +19329,135 @@ var __awaiter$i = (window && window.__awaiter) || function (thisArg, _arguments,
|
|
19329
19329
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
19330
19330
|
});
|
19331
19331
|
};
|
19332
|
-
|
19333
|
-
|
19334
|
-
|
19335
|
-
|
19336
|
-
|
19337
|
-
|
19338
|
-
const DENIED_PERMISSION_TO_ROOM_SUB_CODE = 5828;
|
19339
|
-
/**
|
19340
|
-
* @private
|
19341
|
-
*/
|
19342
|
-
const isCameraOn = (state) => {
|
19343
|
-
if (state.call) {
|
19344
|
-
const stream = state.call.localVideoStreams.find((stream) => stream.mediaStreamType === 'Video');
|
19345
|
-
return !!stream;
|
19346
|
-
}
|
19347
|
-
else {
|
19348
|
-
if (state.devices.selectedCamera) {
|
19349
|
-
const previewOn = _isPreviewOn(state.devices);
|
19350
|
-
return previewOn;
|
19351
|
-
}
|
19352
|
-
}
|
19353
|
-
return false;
|
19332
|
+
var __asyncValues = (window && window.__asyncValues) || function (o) {
|
19333
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
19334
|
+
var m = o[Symbol.asyncIterator], i;
|
19335
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
19336
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
19337
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
19354
19338
|
};
|
19355
19339
|
/**
|
19356
|
-
*
|
19357
|
-
* For example do not show screenshare button.
|
19358
|
-
*
|
19340
|
+
* Context of Chat, which is a centralized context for all state updates
|
19359
19341
|
* @private
|
19360
19342
|
*/
|
19361
|
-
|
19362
|
-
|
19363
|
-
|
19364
|
-
|
19365
|
-
|
19366
|
-
|
19367
|
-
|
19368
|
-
|
19369
|
-
|
19370
|
-
|
19371
|
-
|
19372
|
-
|
19343
|
+
class ChatContext {
|
19344
|
+
constructor(clientState, threadId) {
|
19345
|
+
this.emitter = new EventEmitter__default['default']();
|
19346
|
+
const thread = clientState.threads[threadId];
|
19347
|
+
this.threadId = threadId;
|
19348
|
+
if (!thread) {
|
19349
|
+
throw 'Cannot find threadId, please initialize thread before use!';
|
19350
|
+
}
|
19351
|
+
this.state = {
|
19352
|
+
userId: clientState.userId,
|
19353
|
+
displayName: clientState.displayName,
|
19354
|
+
thread,
|
19355
|
+
latestErrors: clientState.latestErrors
|
19356
|
+
};
|
19373
19357
|
}
|
19374
|
-
|
19375
|
-
|
19376
|
-
var CallEndReasons;
|
19377
|
-
(function (CallEndReasons) {
|
19378
|
-
CallEndReasons[CallEndReasons["LEFT_CALL"] = 0] = "LEFT_CALL";
|
19379
|
-
CallEndReasons[CallEndReasons["ACCESS_DENIED"] = 1] = "ACCESS_DENIED";
|
19380
|
-
CallEndReasons[CallEndReasons["REMOVED_FROM_CALL"] = 2] = "REMOVED_FROM_CALL";
|
19381
|
-
CallEndReasons[CallEndReasons["ROOM_NOT_FOUND"] = 3] = "ROOM_NOT_FOUND";
|
19382
|
-
CallEndReasons[CallEndReasons["DENIED_PERMISSION_TO_ROOM"] = 4] = "DENIED_PERMISSION_TO_ROOM";
|
19383
|
-
})(CallEndReasons || (CallEndReasons = {}));
|
19384
|
-
const getCallEndReason = (call) => {
|
19385
|
-
var _a, _b, _c, _d, _e;
|
19386
|
-
const remoteParticipantsEndedArray = Array.from(Object.values(call.remoteParticipantsEnded));
|
19387
|
-
/**
|
19388
|
-
* Handle the special case in a PSTN call where removing the last user kicks the caller out of the call.
|
19389
|
-
* The code and subcode is the same as when a user is removed from a teams interop call.
|
19390
|
-
* Hence, we look at the last remote participant removed to determine if the last participant removed was a phone number.
|
19391
|
-
* If yes, the caller was kicked out of the call, but we need to show them that they left the call.
|
19392
|
-
* Note: This check will only work for 1:1 PSTN Calls. The subcode is different for 1:N PSTN calls, and we do not need to handle that case.
|
19393
|
-
*/
|
19394
|
-
if (remoteParticipantsEndedArray.length === 1 &&
|
19395
|
-
communicationCommon.isPhoneNumberIdentifier(remoteParticipantsEndedArray[0].identifier) &&
|
19396
|
-
((_a = call.callEndReason) === null || _a === void 0 ? void 0 : _a.subCode) !== REMOTE_PSTN_USER_HUNG_UP) {
|
19397
|
-
return CallEndReasons.LEFT_CALL;
|
19358
|
+
onStateChange(handler) {
|
19359
|
+
this.emitter.on('stateChanged', handler);
|
19398
19360
|
}
|
19399
|
-
|
19400
|
-
|
19361
|
+
offStateChange(handler) {
|
19362
|
+
this.emitter.off('stateChanged', handler);
|
19401
19363
|
}
|
19402
|
-
|
19403
|
-
|
19364
|
+
setState(state) {
|
19365
|
+
this.state = state;
|
19366
|
+
this.emitter.emit('stateChanged', this.state);
|
19404
19367
|
}
|
19405
|
-
|
19406
|
-
|
19407
|
-
return CallEndReasons.ROOM_NOT_FOUND;
|
19368
|
+
getState() {
|
19369
|
+
return this.state;
|
19408
19370
|
}
|
19409
|
-
|
19410
|
-
|
19411
|
-
return CallEndReasons.DENIED_PERMISSION_TO_ROOM;
|
19371
|
+
setError(error) {
|
19372
|
+
this.setState(Object.assign(Object.assign({}, this.state), { error }));
|
19412
19373
|
}
|
19413
|
-
|
19414
|
-
|
19415
|
-
|
19374
|
+
updateClientState(clientState) {
|
19375
|
+
const thread = clientState.threads[this.threadId];
|
19376
|
+
if (!thread) {
|
19377
|
+
throw 'Cannot find threadId, please make sure thread state is still in Stateful ChatClient.';
|
19378
|
+
}
|
19379
|
+
let updatedState = {
|
19380
|
+
userId: clientState.userId,
|
19381
|
+
displayName: clientState.displayName,
|
19382
|
+
thread,
|
19383
|
+
latestErrors: clientState.latestErrors
|
19384
|
+
};
|
19385
|
+
/* @conditional-compile-remove(file-sharing) */
|
19386
|
+
updatedState = Object.assign(Object.assign({}, updatedState), { fileUploads: this.state.fileUploads });
|
19387
|
+
this.setState(updatedState);
|
19416
19388
|
}
|
19417
|
-
|
19418
|
-
};
|
19389
|
+
}
|
19419
19390
|
/**
|
19420
|
-
* Get the current call composite page based on the current call composite state
|
19421
|
-
*
|
19422
|
-
* @param Call - The current call state
|
19423
|
-
* @param previousCall - The state of the most recent previous call that has ended.
|
19424
|
-
*
|
19425
|
-
* @remarks - The previousCall state is needed to determine if the call has ended.
|
19426
|
-
* When the call ends a new call object is created, and so we must lookback at the
|
19427
|
-
* previous call state to understand how the call has ended. If there is no previous
|
19428
|
-
* call we know that this is a fresh call and can display the configuration page.
|
19429
|
-
*
|
19430
19391
|
* @private
|
19431
19392
|
*/
|
19432
|
-
|
19433
|
-
|
19434
|
-
|
19435
|
-
|
19393
|
+
class AzureCommunicationChatAdapter {
|
19394
|
+
constructor(chatClient, chatThreadClient,
|
19395
|
+
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */ options) {
|
19396
|
+
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19397
|
+
this.credential = undefined;
|
19398
|
+
this.emitter = new EventEmitter__default['default']();
|
19399
|
+
this.bindAllPublicMethods();
|
19400
|
+
this.chatClient = chatClient;
|
19401
|
+
this.chatThreadClient = chatThreadClient;
|
19402
|
+
this.context = new ChatContext(chatClient.getState(), chatThreadClient.threadId);
|
19403
|
+
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19404
|
+
if (options && options.credential) {
|
19405
|
+
this.credential = options.credential;
|
19406
|
+
}
|
19407
|
+
/* @conditional-compile-remove(file-sharing) */ /* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19408
|
+
this.fileUploadAdapter = new AzureCommunicationFileUploadAdapter(this.context);
|
19409
|
+
const onStateChange = (clientState) => {
|
19410
|
+
// unsubscribe when the instance gets disposed
|
19411
|
+
if (!this) {
|
19412
|
+
chatClient.offStateChange(onStateChange);
|
19413
|
+
return;
|
19414
|
+
}
|
19415
|
+
this.context.updateClientState(clientState);
|
19416
|
+
};
|
19417
|
+
this.handlers = createDefaultChatHandlers(chatClient, chatThreadClient);
|
19418
|
+
this.chatClient.onStateChange(onStateChange);
|
19419
|
+
this.subscribeAllEvents();
|
19436
19420
|
}
|
19437
|
-
|
19438
|
-
|
19439
|
-
|
19421
|
+
bindAllPublicMethods() {
|
19422
|
+
this.onStateChange = this.onStateChange.bind(this);
|
19423
|
+
this.offStateChange = this.offStateChange.bind(this);
|
19424
|
+
this.getState = this.getState.bind(this);
|
19425
|
+
this.dispose = this.dispose.bind(this);
|
19426
|
+
this.fetchInitialData = this.fetchInitialData.bind(this);
|
19427
|
+
this.sendMessage = this.sendMessage.bind(this);
|
19428
|
+
this.sendReadReceipt = this.sendReadReceipt.bind(this);
|
19429
|
+
this.sendTypingIndicator = this.sendTypingIndicator.bind(this);
|
19430
|
+
this.updateMessage = this.updateMessage.bind(this);
|
19431
|
+
this.deleteMessage = this.deleteMessage.bind(this);
|
19432
|
+
this.removeParticipant = this.removeParticipant.bind(this);
|
19433
|
+
this.setTopic = this.setTopic.bind(this);
|
19434
|
+
this.loadPreviousChatMessages = this.loadPreviousChatMessages.bind(this);
|
19435
|
+
this.on = this.on.bind(this);
|
19436
|
+
this.off = this.off.bind(this);
|
19437
|
+
/* @conditional-compile-remove(file-sharing) */
|
19438
|
+
this.registerActiveFileUploads = this.registerActiveFileUploads.bind(this);
|
19439
|
+
/* @conditional-compile-remove(file-sharing) */
|
19440
|
+
this.registerCompletedFileUploads = this.registerCompletedFileUploads.bind(this);
|
19441
|
+
/* @conditional-compile-remove(file-sharing) */
|
19442
|
+
this.clearFileUploads = this.clearFileUploads.bind(this);
|
19443
|
+
/* @conditional-compile-remove(file-sharing) */
|
19444
|
+
this.cancelFileUpload = this.cancelFileUpload.bind(this);
|
19445
|
+
/* @conditional-compile-remove(file-sharing) */
|
19446
|
+
this.updateFileUploadProgress = this.updateFileUploadProgress.bind(this);
|
19447
|
+
/* @conditional-compile-remove(file-sharing) */
|
19448
|
+
this.updateFileUploadErrorMessage = this.updateFileUploadErrorMessage.bind(this);
|
19449
|
+
/* @conditional-compile-remove(file-sharing) */
|
19450
|
+
this.updateFileUploadMetadata = this.updateFileUploadMetadata.bind(this);
|
19451
|
+
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19452
|
+
this.downloadAttachments = this.downloadAttachments.bind(this);
|
19440
19453
|
}
|
19441
|
-
|
19442
|
-
|
19443
|
-
// If the composite completes one call and joins another, the previous calls
|
19444
|
-
// will be populated, but not relevant for determining the page.
|
19445
|
-
// `_isInLobbyOrConnecting` needs to be checked first because `_isInCall` also returns true when call is in lobby.
|
19446
|
-
if (_isInLobbyOrConnecting(call === null || call === void 0 ? void 0 : call.state)) {
|
19447
|
-
return 'lobby';
|
19448
|
-
// `LocalHold` needs to be checked before `isInCall` since it is also a state that's considered in call.
|
19449
|
-
}
|
19450
|
-
else if ((call === null || call === void 0 ? void 0 : call.state) === 'LocalHold') {
|
19451
|
-
/* @conditional-compile-remove(PSTN-calls) */ /* @conditional-compile-remove(one-to-n-calling) */
|
19452
|
-
return 'hold';
|
19453
|
-
}
|
19454
|
-
else if ((call === null || call === void 0 ? void 0 : call.state) === 'Disconnecting') {
|
19455
|
-
return 'leaving';
|
19456
|
-
}
|
19457
|
-
else if (_isInCall(call === null || call === void 0 ? void 0 : call.state)) {
|
19458
|
-
return 'call';
|
19459
|
-
}
|
19460
|
-
else {
|
19461
|
-
// When the call object has been constructed after clicking , but before 'connecting' has been
|
19462
|
-
// set on the call object, we continue to show the configuration screen.
|
19463
|
-
// The call object does not correctly reflect local device state until `call.state` moves to `connecting`.
|
19464
|
-
// Moving to the 'lobby' page too soon leads to components that depend on the `call` object to show incorrect
|
19465
|
-
// transitional state.
|
19466
|
-
return 'configuration';
|
19467
|
-
}
|
19468
|
-
}
|
19469
|
-
if (previousCall) {
|
19470
|
-
const reason = getCallEndReason(previousCall);
|
19471
|
-
/* @conditional-compile-remove(rooms) */
|
19472
|
-
switch (reason) {
|
19473
|
-
case CallEndReasons.ROOM_NOT_FOUND:
|
19474
|
-
return 'roomNotFound';
|
19475
|
-
case CallEndReasons.DENIED_PERMISSION_TO_ROOM:
|
19476
|
-
return 'deniedPermissionToRoom';
|
19477
|
-
}
|
19478
|
-
switch (reason) {
|
19479
|
-
case CallEndReasons.ACCESS_DENIED:
|
19480
|
-
return 'accessDeniedTeamsMeeting';
|
19481
|
-
case CallEndReasons.REMOVED_FROM_CALL:
|
19482
|
-
return 'removedFromCall';
|
19483
|
-
case CallEndReasons.LEFT_CALL:
|
19484
|
-
if (previousCall.diagnostics.network.latest.noNetwork) {
|
19485
|
-
return 'joinCallFailedDueToNoNetwork';
|
19486
|
-
}
|
19487
|
-
return 'leftCall';
|
19488
|
-
}
|
19489
|
-
}
|
19490
|
-
// No call state - show starting page (configuration)
|
19491
|
-
return 'configuration';
|
19492
|
-
};
|
19493
|
-
/** @private */
|
19494
|
-
const IsCallEndedPage = (
|
19495
|
-
/**
|
19496
|
-
* Explicitly listing the pages of this function intentionally.
|
19497
|
-
* This protects against adding a new composite page that should be marked as an callEndedPage.
|
19498
|
-
* EndCallPages are used to trigger onCallEnded events so this could easily be missed.
|
19499
|
-
* When you add a new composite page this will throw a compiler error. If this new page is an
|
19500
|
-
* EndCallPage ensure you update the END_CALL_PAGES. Afterwards update the `page` parameter
|
19501
|
-
* type below to allow your new page, i.e. add `| <your new page>
|
19502
|
-
*/
|
19503
|
-
page) => END_CALL_PAGES.includes(page);
|
19504
|
-
/**
|
19505
|
-
* Creates a new call control options object and sets the correct values for disabling
|
19506
|
-
* the buttons provided in the `disabledControls` array.
|
19507
|
-
* Returns a new object without changing the original object.
|
19508
|
-
* @param callControlOptions options for the call control component that need to be modified.
|
19509
|
-
* @param disabledControls An array of controls to disable.
|
19510
|
-
* @returns a copy of callControlOptions with disabledControls disabled
|
19511
|
-
* @private
|
19512
|
-
*/
|
19513
|
-
const disableCallControls = (callControlOptions, disabledControls) => {
|
19514
|
-
var _a;
|
19515
|
-
if (callControlOptions === false) {
|
19516
|
-
return false;
|
19517
|
-
}
|
19518
|
-
// Ensure we clone the prop if it is an object to ensure we do not mutate the original prop.
|
19519
|
-
let newOptions = (_a = (callControlOptions instanceof Object ? Object.assign({}, callControlOptions) : callControlOptions)) !== null && _a !== void 0 ? _a : {};
|
19520
|
-
if (newOptions === true || newOptions === undefined) {
|
19521
|
-
newOptions = disabledControls.reduce((acc, key) => {
|
19522
|
-
acc[key] = { disabled: true };
|
19523
|
-
return acc;
|
19524
|
-
}, {});
|
19525
|
-
}
|
19526
|
-
else {
|
19527
|
-
disabledControls.forEach((key) => {
|
19528
|
-
if (newOptions[key] !== false) {
|
19529
|
-
newOptions[key] = { disabled: true };
|
19530
|
-
}
|
19531
|
-
});
|
19532
|
-
}
|
19533
|
-
return newOptions;
|
19534
|
-
};
|
19535
|
-
/**
|
19536
|
-
* Check if a disabled object is provided for a button and returns if the button is disabled.
|
19537
|
-
* A button is only disabled if is explicitly set to disabled.
|
19538
|
-
*
|
19539
|
-
* @param option
|
19540
|
-
* @returns whether a button is disabled
|
19541
|
-
* @private
|
19542
|
-
*/
|
19543
|
-
const isDisabled$2 = (option) => {
|
19544
|
-
if (option === undefined || typeof option === 'boolean') {
|
19545
|
-
return false;
|
19546
|
-
}
|
19547
|
-
return option.disabled;
|
19548
|
-
};
|
19549
|
-
/* @conditional-compile-remove(call-readiness) */
|
19550
|
-
/**
|
19551
|
-
* @returns Permissions state for the camera.
|
19552
|
-
*/
|
19553
|
-
const queryCameraPermissionFromPermissionsAPI = () => __awaiter$i(void 0, void 0, void 0, function* () {
|
19554
|
-
try {
|
19555
|
-
return (yield navigator.permissions.query({ name: 'camera' })).state;
|
19556
|
-
}
|
19557
|
-
catch (e) {
|
19558
|
-
console.info('permissions API is not supported by browser', e);
|
19559
|
-
return 'unsupported';
|
19560
|
-
}
|
19561
|
-
});
|
19562
|
-
/* @conditional-compile-remove(call-readiness) */
|
19563
|
-
/**
|
19564
|
-
* @returns Permissions state for the microphone.
|
19565
|
-
*/
|
19566
|
-
const queryMicrophonePermissionFromPermissionsAPI = () => __awaiter$i(void 0, void 0, void 0, function* () {
|
19567
|
-
try {
|
19568
|
-
return (yield navigator.permissions.query({ name: 'microphone' })).state;
|
19569
|
-
}
|
19570
|
-
catch (e) {
|
19571
|
-
console.info('permissions API is not supported by browser', e);
|
19572
|
-
return 'unsupported';
|
19573
|
-
}
|
19574
|
-
});
|
19575
|
-
/* @conditional-compile-remove(call-readiness) */
|
19576
|
-
/**
|
19577
|
-
*
|
19578
|
-
* This function uses permission API to determine if device permission state is granted, prompt or denied
|
19579
|
-
* @returns whether device permission state is granted, prompt or denied
|
19580
|
-
* If permission API is not supported on this browser, permission state is set to unsupported.
|
19581
|
-
* @private
|
19582
|
-
*/
|
19583
|
-
const getDevicePermissionState = (setVideoState, setAudioState) => __awaiter$i(void 0, void 0, void 0, function* () {
|
19584
|
-
const [cameraResult, microphoneResult] = yield Promise.all([
|
19585
|
-
queryCameraPermissionFromPermissionsAPI(),
|
19586
|
-
queryMicrophonePermissionFromPermissionsAPI()
|
19587
|
-
]);
|
19588
|
-
setVideoState(cameraResult);
|
19589
|
-
setAudioState(microphoneResult);
|
19590
|
-
});
|
19591
|
-
/* @conditional-compile-remove(unsupported-browser) */
|
19592
|
-
const isUnsupportedEnvironment = (environmentInfo, unsupportedBrowserVersionOptedIn) => {
|
19593
|
-
return !!((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowser) === false ||
|
19594
|
-
((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowserVersion) === false && !unsupportedBrowserVersionOptedIn) ||
|
19595
|
-
(environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedPlatform) === false);
|
19596
|
-
};
|
19597
|
-
/**
|
19598
|
-
* Check if an object is identifier.
|
19599
|
-
*
|
19600
|
-
* @param identifier
|
19601
|
-
* @returns whether an identifier is one of identifier types (for runtime validation)
|
19602
|
-
* @private
|
19603
|
-
*/
|
19604
|
-
const isValidIdentifier = (identifier) => {
|
19605
|
-
return (communicationCommon.isCommunicationUserIdentifier(identifier) ||
|
19606
|
-
communicationCommon.isPhoneNumberIdentifier(identifier) ||
|
19607
|
-
communicationCommon.isMicrosoftTeamsUserIdentifier(identifier) ||
|
19608
|
-
communicationCommon.isUnknownIdentifier(identifier));
|
19609
|
-
};
|
19610
|
-
/**
|
19611
|
-
* Check if we are using safari browser
|
19612
|
-
* @private
|
19613
|
-
*/
|
19614
|
-
const _isSafari = (environmentInfo) => {
|
19615
|
-
/* @conditional-compile-remove(unsupported-browser) */
|
19616
|
-
return (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.environment.browser) === 'safari';
|
19617
|
-
};
|
19618
|
-
/**
|
19619
|
-
* @private
|
19620
|
-
* This is the util function to create a participant modifier for remote participantList
|
19621
|
-
* It memoize previous original participant items and only update the changed participant
|
19622
|
-
* It takes in one modifier function to generate one single participant object, it returns undefined if the object keeps unmodified
|
19623
|
-
*/
|
19624
|
-
const createParticipantModifier = (createModifiedParticipant) => {
|
19625
|
-
let previousParticipantState = undefined;
|
19626
|
-
let modifiedParticipants = {};
|
19627
|
-
const memoizedParticipants = {};
|
19628
|
-
return (state) => {
|
19629
|
-
var _a, _b, _c, _d;
|
19630
|
-
// if root state is the same, we don't need to update the participants
|
19631
|
-
if (((_a = state.call) === null || _a === void 0 ? void 0 : _a.remoteParticipants) !== previousParticipantState) {
|
19632
|
-
modifiedParticipants = {};
|
19633
|
-
const originalParticipants = (_b = state.call) === null || _b === void 0 ? void 0 : _b.remoteParticipants;
|
19634
|
-
for (const key in originalParticipants) {
|
19635
|
-
const modifiedParticipant = createModifiedParticipant(key, originalParticipants[key]);
|
19636
|
-
if (modifiedParticipant === undefined) {
|
19637
|
-
modifiedParticipants[key] = originalParticipants[key];
|
19638
|
-
continue;
|
19639
|
-
}
|
19640
|
-
// Generate the new item if original cached item has been changed
|
19641
|
-
if (((_c = memoizedParticipants[key]) === null || _c === void 0 ? void 0 : _c.originalRef) !== originalParticipants[key]) {
|
19642
|
-
memoizedParticipants[key] = {
|
19643
|
-
newParticipant: modifiedParticipant,
|
19644
|
-
originalRef: originalParticipants[key]
|
19645
|
-
};
|
19646
|
-
}
|
19647
|
-
// the modified participant is always coming from the memoized cache, whether is was refreshed
|
19648
|
-
// from the previous closure or not
|
19649
|
-
modifiedParticipants[key] = memoizedParticipants[key].newParticipant;
|
19650
|
-
}
|
19651
|
-
previousParticipantState = (_d = state.call) === null || _d === void 0 ? void 0 : _d.remoteParticipants;
|
19652
|
-
}
|
19653
|
-
return Object.assign(Object.assign({}, state), { call: state.call
|
19654
|
-
? Object.assign(Object.assign({}, state.call), { remoteParticipants: modifiedParticipants }) : undefined });
|
19655
|
-
};
|
19656
|
-
};
|
19657
|
-
/**
|
19658
|
-
* @private
|
19659
|
-
*/
|
19660
|
-
const dismissVideoEffectsError = (toDismiss) => {
|
19661
|
-
var _a;
|
19662
|
-
const now = new Date(Date.now());
|
19663
|
-
const toDismissTimestamp = (_a = toDismiss.timestamp) !== null && _a !== void 0 ? _a : now;
|
19664
|
-
// Record that this error was dismissed for the first time right now.
|
19665
|
-
return {
|
19666
|
-
dismissedAt: now > toDismissTimestamp ? now : toDismissTimestamp,
|
19667
|
-
activeSince: toDismiss.timestamp
|
19668
|
-
};
|
19669
|
-
};
|
19670
|
-
/* @conditional-compile-remove(video-background-effects) */
|
19671
|
-
/** @private */
|
19672
|
-
const getBackgroundEffectFromSelectedEffect = (selectedEffect) => (selectedEffect === null || selectedEffect === void 0 ? void 0 : selectedEffect.effectName) === 'blur'
|
19673
|
-
? new communicationCallingEffects.BackgroundBlurEffect()
|
19674
|
-
: (selectedEffect === null || selectedEffect === void 0 ? void 0 : selectedEffect.effectName) === 'replacement'
|
19675
|
-
? new communicationCallingEffects.BackgroundReplacementEffect({ backgroundImageUrl: selectedEffect.backgroundImageUrl })
|
19676
|
-
: undefined;
|
19677
|
-
/* @conditional-compile-remove(video-background-effects) */
|
19678
|
-
/**
|
19679
|
-
* @remarks this logic should mimic the onToggleCamera in the common call handlers.
|
19680
|
-
* @private
|
19681
|
-
*/
|
19682
|
-
const getSelectedCameraFromAdapterState = (state) => state.devices.selectedCamera || state.devices.cameras[0];
|
19683
|
-
|
19684
|
-
// Copyright (c) Microsoft Corporation.
|
19685
|
-
// Licensed under the MIT license.
|
19686
|
-
var __awaiter$h = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
|
19687
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
19688
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
19689
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
19690
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
19691
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
19692
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
19693
|
-
});
|
19694
|
-
};
|
19695
|
-
var __asyncValues = (window && window.__asyncValues) || function (o) {
|
19696
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
19697
|
-
var m = o[Symbol.asyncIterator], i;
|
19698
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
19699
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
19700
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
19701
|
-
};
|
19702
|
-
/**
|
19703
|
-
* Context of Chat, which is a centralized context for all state updates
|
19704
|
-
* @private
|
19705
|
-
*/
|
19706
|
-
class ChatContext {
|
19707
|
-
constructor(clientState, threadId) {
|
19708
|
-
this.emitter = new EventEmitter__default['default']();
|
19709
|
-
const thread = clientState.threads[threadId];
|
19710
|
-
this.threadId = threadId;
|
19711
|
-
if (!thread) {
|
19712
|
-
throw 'Cannot find threadId, please initialize thread before use!';
|
19713
|
-
}
|
19714
|
-
this.state = {
|
19715
|
-
userId: clientState.userId,
|
19716
|
-
displayName: clientState.displayName,
|
19717
|
-
thread,
|
19718
|
-
latestErrors: clientState.latestErrors
|
19719
|
-
};
|
19720
|
-
}
|
19721
|
-
onStateChange(handler) {
|
19722
|
-
this.emitter.on('stateChanged', handler);
|
19723
|
-
}
|
19724
|
-
offStateChange(handler) {
|
19725
|
-
this.emitter.off('stateChanged', handler);
|
19726
|
-
}
|
19727
|
-
setState(state) {
|
19728
|
-
this.state = state;
|
19729
|
-
this.emitter.emit('stateChanged', this.state);
|
19730
|
-
}
|
19731
|
-
getState() {
|
19732
|
-
return this.state;
|
19733
|
-
}
|
19734
|
-
setError(error) {
|
19735
|
-
this.setState(Object.assign(Object.assign({}, this.state), { error }));
|
19736
|
-
}
|
19737
|
-
updateClientState(clientState) {
|
19738
|
-
const thread = clientState.threads[this.threadId];
|
19739
|
-
if (!thread) {
|
19740
|
-
throw 'Cannot find threadId, please make sure thread state is still in Stateful ChatClient.';
|
19741
|
-
}
|
19742
|
-
let updatedState = {
|
19743
|
-
userId: clientState.userId,
|
19744
|
-
displayName: clientState.displayName,
|
19745
|
-
thread,
|
19746
|
-
latestErrors: clientState.latestErrors
|
19747
|
-
};
|
19748
|
-
/* @conditional-compile-remove(file-sharing) */
|
19749
|
-
updatedState = Object.assign(Object.assign({}, updatedState), { fileUploads: this.state.fileUploads });
|
19750
|
-
this.setState(updatedState);
|
19751
|
-
}
|
19752
|
-
}
|
19753
|
-
/**
|
19754
|
-
* @private
|
19755
|
-
*/
|
19756
|
-
class AzureCommunicationChatAdapter {
|
19757
|
-
constructor(chatClient, chatThreadClient,
|
19758
|
-
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */ options) {
|
19759
|
-
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19760
|
-
this.credential = undefined;
|
19761
|
-
this.emitter = new EventEmitter__default['default']();
|
19762
|
-
this.bindAllPublicMethods();
|
19763
|
-
this.chatClient = chatClient;
|
19764
|
-
this.chatThreadClient = chatThreadClient;
|
19765
|
-
this.context = new ChatContext(chatClient.getState(), chatThreadClient.threadId);
|
19766
|
-
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19767
|
-
if (options && options.credential) {
|
19768
|
-
this.credential = options.credential;
|
19769
|
-
}
|
19770
|
-
/* @conditional-compile-remove(file-sharing) */ /* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19771
|
-
this.fileUploadAdapter = new AzureCommunicationFileUploadAdapter(this.context);
|
19772
|
-
const onStateChange = (clientState) => {
|
19773
|
-
// unsubscribe when the instance gets disposed
|
19774
|
-
if (!this) {
|
19775
|
-
chatClient.offStateChange(onStateChange);
|
19776
|
-
return;
|
19777
|
-
}
|
19778
|
-
this.context.updateClientState(clientState);
|
19779
|
-
};
|
19780
|
-
this.handlers = createDefaultChatHandlers(chatClient, chatThreadClient);
|
19781
|
-
this.chatClient.onStateChange(onStateChange);
|
19782
|
-
this.subscribeAllEvents();
|
19783
|
-
}
|
19784
|
-
bindAllPublicMethods() {
|
19785
|
-
this.onStateChange = this.onStateChange.bind(this);
|
19786
|
-
this.offStateChange = this.offStateChange.bind(this);
|
19787
|
-
this.getState = this.getState.bind(this);
|
19788
|
-
this.dispose = this.dispose.bind(this);
|
19789
|
-
this.fetchInitialData = this.fetchInitialData.bind(this);
|
19790
|
-
this.sendMessage = this.sendMessage.bind(this);
|
19791
|
-
this.sendReadReceipt = this.sendReadReceipt.bind(this);
|
19792
|
-
this.sendTypingIndicator = this.sendTypingIndicator.bind(this);
|
19793
|
-
this.updateMessage = this.updateMessage.bind(this);
|
19794
|
-
this.deleteMessage = this.deleteMessage.bind(this);
|
19795
|
-
this.removeParticipant = this.removeParticipant.bind(this);
|
19796
|
-
this.setTopic = this.setTopic.bind(this);
|
19797
|
-
this.loadPreviousChatMessages = this.loadPreviousChatMessages.bind(this);
|
19798
|
-
this.on = this.on.bind(this);
|
19799
|
-
this.off = this.off.bind(this);
|
19800
|
-
/* @conditional-compile-remove(file-sharing) */
|
19801
|
-
this.registerActiveFileUploads = this.registerActiveFileUploads.bind(this);
|
19802
|
-
/* @conditional-compile-remove(file-sharing) */
|
19803
|
-
this.registerCompletedFileUploads = this.registerCompletedFileUploads.bind(this);
|
19804
|
-
/* @conditional-compile-remove(file-sharing) */
|
19805
|
-
this.clearFileUploads = this.clearFileUploads.bind(this);
|
19806
|
-
/* @conditional-compile-remove(file-sharing) */
|
19807
|
-
this.cancelFileUpload = this.cancelFileUpload.bind(this);
|
19808
|
-
/* @conditional-compile-remove(file-sharing) */
|
19809
|
-
this.updateFileUploadProgress = this.updateFileUploadProgress.bind(this);
|
19810
|
-
/* @conditional-compile-remove(file-sharing) */
|
19811
|
-
this.updateFileUploadErrorMessage = this.updateFileUploadErrorMessage.bind(this);
|
19812
|
-
/* @conditional-compile-remove(file-sharing) */
|
19813
|
-
this.updateFileUploadMetadata = this.updateFileUploadMetadata.bind(this);
|
19814
|
-
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19815
|
-
this.downloadAttachments = this.downloadAttachments.bind(this);
|
19816
|
-
}
|
19817
|
-
dispose() {
|
19818
|
-
this.unsubscribeAllEvents();
|
19454
|
+
dispose() {
|
19455
|
+
this.unsubscribeAllEvents();
|
19819
19456
|
}
|
19820
19457
|
fetchInitialData() {
|
19821
|
-
return __awaiter$
|
19458
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19822
19459
|
// If get properties fails we dont want to try to get the participants after.
|
19823
|
-
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19460
|
+
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19824
19461
|
var e_1, _a;
|
19825
19462
|
yield this.chatThreadClient.getProperties();
|
19826
19463
|
try {
|
@@ -19854,8 +19491,8 @@ class AzureCommunicationChatAdapter {
|
|
19854
19491
|
this.context.offStateChange(handler);
|
19855
19492
|
}
|
19856
19493
|
sendMessage(content, options = {}) {
|
19857
|
-
return __awaiter$
|
19858
|
-
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19494
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19495
|
+
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19859
19496
|
/* @conditional-compile-remove(file-sharing) */
|
19860
19497
|
options.metadata = Object.assign(Object.assign({}, options.metadata), convertFileUploadsUiStateToMessageMetadata(this.context.getState().fileUploads));
|
19861
19498
|
/* @conditional-compile-remove(file-sharing) */
|
@@ -19872,51 +19509,51 @@ class AzureCommunicationChatAdapter {
|
|
19872
19509
|
});
|
19873
19510
|
}
|
19874
19511
|
sendReadReceipt(chatMessageId) {
|
19875
|
-
return __awaiter$
|
19876
|
-
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19512
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19513
|
+
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19877
19514
|
yield this.handlers.onMessageSeen(chatMessageId);
|
19878
19515
|
}));
|
19879
19516
|
});
|
19880
19517
|
}
|
19881
19518
|
sendTypingIndicator() {
|
19882
|
-
return __awaiter$
|
19883
|
-
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19519
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19520
|
+
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19884
19521
|
yield this.handlers.onTyping();
|
19885
19522
|
}));
|
19886
19523
|
});
|
19887
19524
|
}
|
19888
19525
|
removeParticipant(userId) {
|
19889
|
-
return __awaiter$
|
19890
|
-
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19526
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19527
|
+
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19891
19528
|
yield this.handlers.onRemoveParticipant(userId);
|
19892
19529
|
}));
|
19893
19530
|
});
|
19894
19531
|
}
|
19895
19532
|
setTopic(topicName) {
|
19896
|
-
return __awaiter$
|
19897
|
-
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19533
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19534
|
+
yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19898
19535
|
yield this.handlers.updateThreadTopicName(topicName);
|
19899
19536
|
}));
|
19900
19537
|
});
|
19901
19538
|
}
|
19902
19539
|
loadPreviousChatMessages(messagesToLoad) {
|
19903
|
-
return __awaiter$
|
19904
|
-
return yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19540
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19541
|
+
return yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19905
19542
|
return yield this.handlers.onLoadPreviousChatMessages(messagesToLoad);
|
19906
19543
|
}));
|
19907
19544
|
});
|
19908
19545
|
}
|
19909
19546
|
updateMessage(messageId, content, metadata, options) {
|
19910
|
-
return __awaiter$
|
19911
|
-
return yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19547
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19548
|
+
return yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19912
19549
|
/* @conditional-compile-remove(file-sharing) */
|
19913
19550
|
return yield this.handlers.onUpdateMessage(messageId, content, metadata, options);
|
19914
19551
|
}));
|
19915
19552
|
});
|
19916
19553
|
}
|
19917
19554
|
deleteMessage(messageId) {
|
19918
|
-
return __awaiter$
|
19919
|
-
return yield this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19555
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19556
|
+
return yield this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19920
19557
|
return yield this.handlers.onDeleteMessage(messageId);
|
19921
19558
|
}));
|
19922
19559
|
});
|
@@ -19951,8 +19588,8 @@ class AzureCommunicationChatAdapter {
|
|
19951
19588
|
}
|
19952
19589
|
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19953
19590
|
downloadAttachments(options) {
|
19954
|
-
return __awaiter$
|
19955
|
-
return this.asyncTeeErrorToEventEmitter(() => __awaiter$
|
19591
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19592
|
+
return this.asyncTeeErrorToEventEmitter(() => __awaiter$i(this, void 0, void 0, function* () {
|
19956
19593
|
if (this.credential === undefined) {
|
19957
19594
|
const e = new Error();
|
19958
19595
|
e['target'] = 'ChatThreadClient.getMessage';
|
@@ -19972,9 +19609,9 @@ class AzureCommunicationChatAdapter {
|
|
19972
19609
|
}
|
19973
19610
|
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
19974
19611
|
downloadAuthenticatedFile(accessToken, options) {
|
19975
|
-
return __awaiter$
|
19612
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19976
19613
|
function fetchWithAuthentication(url, token) {
|
19977
|
-
return __awaiter$
|
19614
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
19978
19615
|
const headers = new Headers();
|
19979
19616
|
headers.append('Authorization', `Bearer ${token}`);
|
19980
19617
|
try {
|
@@ -20046,7 +19683,7 @@ class AzureCommunicationChatAdapter {
|
|
20046
19683
|
this.emitter.off(event, listener);
|
20047
19684
|
}
|
20048
19685
|
asyncTeeErrorToEventEmitter(f) {
|
20049
|
-
return __awaiter$
|
19686
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
20050
19687
|
try {
|
20051
19688
|
return yield f();
|
20052
19689
|
}
|
@@ -20088,8 +19725,8 @@ const convertEventType = (type) => {
|
|
20088
19725
|
*
|
20089
19726
|
* @public
|
20090
19727
|
*/
|
20091
|
-
const createAzureCommunicationChatAdapter = ({ endpoint: endpointUrl, userId, displayName, credential, threadId }) => __awaiter$
|
20092
|
-
if (!
|
19728
|
+
const createAzureCommunicationChatAdapter = ({ endpoint: endpointUrl, userId, displayName, credential, threadId }) => __awaiter$i(void 0, void 0, void 0, function* () {
|
19729
|
+
if (!_isValidIdentifier(userId)) {
|
20093
19730
|
throw new Error('Provided userId is invalid. Please provide valid identifier object.');
|
20094
19731
|
}
|
20095
19732
|
const chatClient = createStatefulChatClient({
|
@@ -20157,7 +19794,7 @@ beforeDispose) => {
|
|
20157
19794
|
if (!credential || !displayName || !endpoint || !threadId || !userId) {
|
20158
19795
|
return;
|
20159
19796
|
}
|
20160
|
-
(() => __awaiter$
|
19797
|
+
(() => __awaiter$i(void 0, void 0, void 0, function* () {
|
20161
19798
|
if (adapterRef.current) {
|
20162
19799
|
// Dispose the old adapter when a new one is created.
|
20163
19800
|
//
|
@@ -20189,7 +19826,7 @@ beforeDispose) => {
|
|
20189
19826
|
// Dispose any existing adapter when the component unmounts.
|
20190
19827
|
React.useEffect(() => {
|
20191
19828
|
return () => {
|
20192
|
-
(() => __awaiter$
|
19829
|
+
(() => __awaiter$i(void 0, void 0, void 0, function* () {
|
20193
19830
|
if (adapterRef.current) {
|
20194
19831
|
if (beforeDisposeRef.current) {
|
20195
19832
|
yield beforeDisposeRef.current(adapterRef.current);
|
@@ -20213,7 +19850,7 @@ beforeDispose) => {
|
|
20213
19850
|
function createAzureCommunicationChatAdapterFromClient(chatClient, chatThreadClient,
|
20214
19851
|
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
20215
19852
|
options) {
|
20216
|
-
return __awaiter$
|
19853
|
+
return __awaiter$i(this, void 0, void 0, function* () {
|
20217
19854
|
return new AzureCommunicationChatAdapter(chatClient, chatThreadClient,
|
20218
19855
|
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */ options);
|
20219
19856
|
});
|
@@ -20426,7 +20063,7 @@ const sendboxContainerStyles = {
|
|
20426
20063
|
|
20427
20064
|
// Copyright (c) Microsoft Corporation.
|
20428
20065
|
// Licensed under the MIT license.
|
20429
|
-
var __awaiter$
|
20066
|
+
var __awaiter$h = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
|
20430
20067
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
20431
20068
|
return new (P || (P = Promise))(function (resolve, reject) {
|
20432
20069
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
@@ -20447,7 +20084,7 @@ const AvatarPersona = (props) => {
|
|
20447
20084
|
const { userId, dataProvider, text, imageUrl, imageInitials, initialsColor, initialsTextColor, showOverflowTooltip } = props;
|
20448
20085
|
const [data, setData] = React.useState();
|
20449
20086
|
React.useEffect(() => {
|
20450
|
-
(() => __awaiter$
|
20087
|
+
(() => __awaiter$h(void 0, void 0, void 0, function* () {
|
20451
20088
|
if (dataProvider && userId) {
|
20452
20089
|
const newData = yield dataProvider(userId);
|
20453
20090
|
if (avatarDeepDifferenceCheck(data, newData)) {
|
@@ -20814,6 +20451,253 @@ const FileDownloadErrorBar = (props) => {
|
|
20814
20451
|
}
|
20815
20452
|
};
|
20816
20453
|
|
20454
|
+
// Copyright (c) Microsoft Corporation.
|
20455
|
+
// Licensed under the MIT license.
|
20456
|
+
var __awaiter$g = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
|
20457
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
20458
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
20459
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
20460
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
20461
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
20462
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
20463
|
+
});
|
20464
|
+
};
|
20465
|
+
/**
|
20466
|
+
* @private
|
20467
|
+
*/
|
20468
|
+
const ChatScreen = (props) => {
|
20469
|
+
const { onFetchAvatarPersonaData, onRenderMessage, onRenderTypingIndicator, options, styles, fileSharing, formFactor } = props;
|
20470
|
+
const defaultNumberOfChatMessagesToReload = 5;
|
20471
|
+
/* @conditional-compile-remove(file-sharing) */
|
20472
|
+
const [downloadErrorMessage, setDownloadErrorMessage] = React__default['default'].useState('');
|
20473
|
+
const adapter = useAdapter$1();
|
20474
|
+
const theme = useTheme();
|
20475
|
+
React.useEffect(() => {
|
20476
|
+
// Initial data should be always fetched by the composite(or external caller) instead of the adapter
|
20477
|
+
const fetchData = () => __awaiter$g(void 0, void 0, void 0, function* () {
|
20478
|
+
// Fetch initial data for adapter
|
20479
|
+
yield adapter.fetchInitialData();
|
20480
|
+
// Fetch initial set of messages. Without fetching messages here, if the Composite's adapter is changed the message thread does not load new messages.
|
20481
|
+
yield adapter.loadPreviousChatMessages(defaultNumberOfChatMessagesToReload);
|
20482
|
+
});
|
20483
|
+
fetchData();
|
20484
|
+
}, [adapter]);
|
20485
|
+
const messageThreadProps = usePropsFor$2(MessageThread);
|
20486
|
+
const sendBoxProps = usePropsFor$2(SendBox);
|
20487
|
+
const typingIndicatorProps = usePropsFor$2(TypingIndicator);
|
20488
|
+
const headerProps = useAdaptedSelector$1(getHeaderProps);
|
20489
|
+
const errorBarProps = usePropsFor$2(ErrorBar);
|
20490
|
+
const onRenderAvatarCallback = React.useCallback((userId, defaultOptions) => {
|
20491
|
+
return (React__default['default'].createElement(AvatarPersona, Object.assign({ userId: userId, hidePersonaDetails: true }, defaultOptions, { dataProvider: onFetchAvatarPersonaData })));
|
20492
|
+
}, [onFetchAvatarPersonaData]);
|
20493
|
+
const messageThreadStyles = Object.assign({}, messageThreadChatCompositeStyles(theme.semanticColors.bodyBackground), styles === null || styles === void 0 ? void 0 : styles.messageThread);
|
20494
|
+
const typingIndicatorStyles = Object.assign({}, styles === null || styles === void 0 ? void 0 : styles.typingIndicator);
|
20495
|
+
const sendBoxStyles = Object.assign({}, styles === null || styles === void 0 ? void 0 : styles.sendBox);
|
20496
|
+
const userId = toFlatCommunicationIdentifier(adapter.getState().userId);
|
20497
|
+
const fileUploadButtonOnChange = React.useCallback((files) => {
|
20498
|
+
if (!files) {
|
20499
|
+
return;
|
20500
|
+
}
|
20501
|
+
/* @conditional-compile-remove(file-sharing) */
|
20502
|
+
const fileUploads = adapter.registerActiveFileUploads(Array.from(files));
|
20503
|
+
/* @conditional-compile-remove(file-sharing) */
|
20504
|
+
fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.uploadHandler(userId, fileUploads);
|
20505
|
+
}, [adapter, fileSharing, userId]);
|
20506
|
+
/* @conditional-compile-remove(file-sharing) */
|
20507
|
+
const onRenderFileDownloads = React.useCallback((userId, message) => (React__default['default'].createElement(_FileDownloadCards, { userId: userId, fileMetadata: message.attachedFilesMetadata || [], downloadHandler: fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.downloadHandler, onDownloadErrorMessage: (errorMessage) => {
|
20508
|
+
setDownloadErrorMessage(errorMessage);
|
20509
|
+
} })), [fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.downloadHandler]);
|
20510
|
+
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
20511
|
+
const onRenderInlineAttachment = React.useCallback((attachment) => __awaiter$g(void 0, void 0, void 0, function* () {
|
20512
|
+
if (attachment.previewUrl) {
|
20513
|
+
const blob = yield adapter.downloadAttachments({ attachmentUrls: [attachment.previewUrl] });
|
20514
|
+
return blob;
|
20515
|
+
}
|
20516
|
+
return [{ blobUrl: '' }];
|
20517
|
+
}), [adapter]);
|
20518
|
+
const AttachFileButton = React.useCallback(() => {
|
20519
|
+
if (!(fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.uploadHandler)) {
|
20520
|
+
return null;
|
20521
|
+
}
|
20522
|
+
return (React__default['default'].createElement(FileUploadButtonWrapper, { accept: fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.accept, multiple: fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.multiple, onChange: fileUploadButtonOnChange }));
|
20523
|
+
}, [fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.accept, fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.multiple, fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.uploadHandler, fileUploadButtonOnChange]);
|
20524
|
+
return (React__default['default'].createElement(react.Stack, { className: chatContainer, grow: true },
|
20525
|
+
(options === null || options === void 0 ? void 0 : options.topic) !== false && React__default['default'].createElement(ChatHeader, Object.assign({}, headerProps)),
|
20526
|
+
React__default['default'].createElement(react.Stack, { className: chatArea, tokens: participantListContainerPadding, horizontal: true, grow: true },
|
20527
|
+
React__default['default'].createElement(react.Stack, { className: chatWrapper, grow: true },
|
20528
|
+
(options === null || options === void 0 ? void 0 : options.errorBar) !== false && React__default['default'].createElement(ErrorBar, Object.assign({}, errorBarProps)),
|
20529
|
+
/* @conditional-compile-remove(file-sharing) */
|
20530
|
+
React__default['default'].createElement(FileDownloadErrorBar, { onDismissDownloadErrorMessage: React.useCallback(() => {
|
20531
|
+
setDownloadErrorMessage('');
|
20532
|
+
}, []), fileDownloadErrorMessage: downloadErrorMessage || '' }),
|
20533
|
+
React__default['default'].createElement(MessageThread, Object.assign({}, messageThreadProps, { onRenderAvatar: onRenderAvatarCallback, onRenderMessage: onRenderMessage,
|
20534
|
+
/* @conditional-compile-remove(file-sharing) */
|
20535
|
+
onRenderFileDownloads: onRenderFileDownloads,
|
20536
|
+
/* @conditional-compile-remove(teams-inline-images-and-file-sharing) */
|
20537
|
+
onFetchAttachments: onRenderInlineAttachment, numberOfChatMessagesToReload: defaultNumberOfChatMessagesToReload, styles: messageThreadStyles })),
|
20538
|
+
React__default['default'].createElement(react.Stack, { className: react.mergeStyles(sendboxContainerStyles) },
|
20539
|
+
React__default['default'].createElement("div", { className: react.mergeStyles(typingIndicatorContainerStyles) }, onRenderTypingIndicator ? (onRenderTypingIndicator(typingIndicatorProps.typingUsers)) : (React__default['default'].createElement(TypingIndicator, Object.assign({}, typingIndicatorProps, { styles: typingIndicatorStyles })))),
|
20540
|
+
React__default['default'].createElement(react.Stack, { horizontal: formFactor === 'mobile' },
|
20541
|
+
formFactor === 'mobile' && (React__default['default'].createElement(react.Stack, { verticalAlign: "center" },
|
20542
|
+
React__default['default'].createElement(AttachFileButton, null))),
|
20543
|
+
React__default['default'].createElement(react.Stack, { grow: true },
|
20544
|
+
React__default['default'].createElement(SendBox, Object.assign({}, sendBoxProps, { autoFocus: options === null || options === void 0 ? void 0 : options.autoFocus, styles: sendBoxStyles,
|
20545
|
+
/* @conditional-compile-remove(file-sharing) */
|
20546
|
+
activeFileUploads: useSelector$2(fileUploadsSelector).files,
|
20547
|
+
/* @conditional-compile-remove(file-sharing) */
|
20548
|
+
onCancelFileUpload: adapter.cancelFileUpload }))),
|
20549
|
+
formFactor !== 'mobile' && React__default['default'].createElement(AttachFileButton, null)))),
|
20550
|
+
/* @conditional-compile-remove(chat-composite-participant-pane) */
|
20551
|
+
(options === null || options === void 0 ? void 0 : options.participantPane) === true && (React__default['default'].createElement(ChatScreenPeoplePane, { onFetchAvatarPersonaData: onFetchAvatarPersonaData, onFetchParticipantMenuItems: props.onFetchParticipantMenuItems, isMobile: formFactor === 'mobile' })))));
|
20552
|
+
};
|
20553
|
+
|
20554
|
+
// Copyright (c) Microsoft Corporation.
|
20555
|
+
/**
|
20556
|
+
* A customizable UI composite for the chat experience.
|
20557
|
+
*
|
20558
|
+
* @remarks Chat composite min width and height are respectively 17.5rem and 20rem (280px and 320px, with default rem at 16px)
|
20559
|
+
*
|
20560
|
+
* @public
|
20561
|
+
*/
|
20562
|
+
const ChatComposite = (props) => {
|
20563
|
+
const { adapter, options, onFetchAvatarPersonaData, onRenderTypingIndicator, onRenderMessage, onFetchParticipantMenuItems } = props;
|
20564
|
+
const formFactor = props['formFactor'] || 'desktop';
|
20565
|
+
/**
|
20566
|
+
* @TODO Remove this function and pass the props directly when file-sharing is promoted to stable.
|
20567
|
+
* @private
|
20568
|
+
*/
|
20569
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
20570
|
+
const fileSharingOptions = () => {
|
20571
|
+
/* @conditional-compile-remove(file-sharing) */
|
20572
|
+
return {
|
20573
|
+
fileSharing: options === null || options === void 0 ? void 0 : options.fileSharing
|
20574
|
+
};
|
20575
|
+
};
|
20576
|
+
return (React__default['default'].createElement("div", { className: chatScreenContainerStyle },
|
20577
|
+
React__default['default'].createElement(BaseProvider, Object.assign({}, props),
|
20578
|
+
React__default['default'].createElement(ChatAdapterProvider, { adapter: adapter },
|
20579
|
+
React__default['default'].createElement(ChatScreen, Object.assign({ formFactor: formFactor, options: options, onFetchAvatarPersonaData: onFetchAvatarPersonaData, onRenderTypingIndicator: onRenderTypingIndicator, onRenderMessage: onRenderMessage, onFetchParticipantMenuItems: onFetchParticipantMenuItems }, fileSharingOptions()))))));
|
20580
|
+
};
|
20581
|
+
|
20582
|
+
// Copyright (c) Microsoft Corporation.
|
20583
|
+
const CallAdapterContext = React.createContext(undefined);
|
20584
|
+
/**
|
20585
|
+
* @private
|
20586
|
+
*/
|
20587
|
+
const CallAdapterProvider = (props) => {
|
20588
|
+
const { adapter } = props;
|
20589
|
+
return React__default['default'].createElement(CallAdapterContext.Provider, { value: adapter }, props.children);
|
20590
|
+
};
|
20591
|
+
/**
|
20592
|
+
* @private
|
20593
|
+
*/
|
20594
|
+
const useAdapter = () => {
|
20595
|
+
const adapter = React.useContext(CallAdapterContext);
|
20596
|
+
if (!adapter) {
|
20597
|
+
throw 'Cannot find adapter please initialize before usage.';
|
20598
|
+
}
|
20599
|
+
return adapter;
|
20600
|
+
};
|
20601
|
+
|
20602
|
+
// Copyright (c) Microsoft Corporation.
|
20603
|
+
/**
|
20604
|
+
* @private
|
20605
|
+
*/
|
20606
|
+
const useAdaptedSelector = (selector, selectorProps) => {
|
20607
|
+
return useSelectorWithAdaptation(selector, adaptCompositeState, selectorProps);
|
20608
|
+
};
|
20609
|
+
/**
|
20610
|
+
* @private
|
20611
|
+
*/
|
20612
|
+
const useSelectorWithAdaptation = (selector, adaptState, selectorProps) => {
|
20613
|
+
var _a;
|
20614
|
+
const adapter = useAdapter();
|
20615
|
+
// Keeps track of whether the current component is mounted or not. If it has unmounted, make sure we do not modify the
|
20616
|
+
// state or it will cause React warnings in the console. https://skype.visualstudio.com/SPOOL/_workitems/edit/2453212
|
20617
|
+
const mounted = React.useRef(false);
|
20618
|
+
React.useEffect(() => {
|
20619
|
+
mounted.current = true;
|
20620
|
+
return () => {
|
20621
|
+
mounted.current = false;
|
20622
|
+
};
|
20623
|
+
});
|
20624
|
+
const callId = (_a = adapter.getState().call) === null || _a === void 0 ? void 0 : _a.id;
|
20625
|
+
const callConfigProps = React.useMemo(() => ({
|
20626
|
+
callId
|
20627
|
+
}), [callId]);
|
20628
|
+
const [props, setProps] = React.useState(selector(adaptState(adapter.getState()), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps));
|
20629
|
+
const propRef = React.useRef(props);
|
20630
|
+
propRef.current = props;
|
20631
|
+
React.useEffect(() => {
|
20632
|
+
const onStateChange = (state) => {
|
20633
|
+
if (!mounted.current) {
|
20634
|
+
return;
|
20635
|
+
}
|
20636
|
+
const newProps = selector(adaptState(state), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps);
|
20637
|
+
if (propRef.current !== newProps) {
|
20638
|
+
setProps(newProps);
|
20639
|
+
}
|
20640
|
+
};
|
20641
|
+
adapter.onStateChange(onStateChange);
|
20642
|
+
return () => {
|
20643
|
+
adapter.offStateChange(onStateChange);
|
20644
|
+
};
|
20645
|
+
}, [adaptState, adapter, selector, selectorProps, callConfigProps]);
|
20646
|
+
return props;
|
20647
|
+
};
|
20648
|
+
const memoizeState = memoizeOne__default['default']((userId, deviceManager, calls, latestErrors, displayName, alternateCallerId, environmentInfo) => ({
|
20649
|
+
userId,
|
20650
|
+
incomingCalls: {},
|
20651
|
+
incomingCallsEnded: {},
|
20652
|
+
callsEnded: {},
|
20653
|
+
deviceManager,
|
20654
|
+
callAgent: { displayName },
|
20655
|
+
calls,
|
20656
|
+
latestErrors,
|
20657
|
+
/* @conditional-compile-remove(PSTN-calls) */
|
20658
|
+
alternateCallerId,
|
20659
|
+
/* @conditional-compile-remove(unsupported-browser) */
|
20660
|
+
environmentInfo
|
20661
|
+
}));
|
20662
|
+
const memoizeCalls = memoizeOne__default['default']((call) => (call ? { [call.id]: call } : {}));
|
20663
|
+
const adaptCompositeState = (compositeState) => {
|
20664
|
+
return memoizeState(compositeState.userId, compositeState.devices, memoizeCalls(compositeState.call),
|
20665
|
+
// This is an unsafe type expansion.
|
20666
|
+
// compositeState.latestErrors can contain properties that are not valid in CallErrors.
|
20667
|
+
//
|
20668
|
+
// But there is no way to check for valid property names at runtime:
|
20669
|
+
// - The set of valid property names is built from types in the @azure/communication-calling.
|
20670
|
+
// Thus we don't have a literal array of allowed strings at runtime.
|
20671
|
+
// - Due to minification / uglification, the property names from the objects at runtime can't be used
|
20672
|
+
// to compare against permissible values inferred from the types.
|
20673
|
+
//
|
20674
|
+
// This is not a huge problem -- it simply means that our adapted selector will include some extra operations
|
20675
|
+
// that are unknown to the UI component and data binding libraries. Generic handling of the errors (e.g.,
|
20676
|
+
// just displaying them in some UI surface) will continue to work for these operations. Handling of
|
20677
|
+
// specific operations (e.g., acting on errors related to permission issues) will ignore these operations.
|
20678
|
+
compositeState.latestErrors, compositeState.displayName,
|
20679
|
+
/* @conditional-compile-remove(PSTN-calls) */
|
20680
|
+
compositeState.alternateCallerId,
|
20681
|
+
/* @conditional-compile-remove(unsupported-browser) */
|
20682
|
+
compositeState.environmentInfo);
|
20683
|
+
};
|
20684
|
+
|
20685
|
+
// Copyright (c) Microsoft Corporation.
|
20686
|
+
// Licensed under the MIT license.
|
20687
|
+
/**
|
20688
|
+
* Subset of CallCompositePages that represent an end call state.
|
20689
|
+
* @private
|
20690
|
+
*/
|
20691
|
+
const END_CALL_PAGES = [
|
20692
|
+
'accessDeniedTeamsMeeting',
|
20693
|
+
'joinCallFailedDueToNoNetwork',
|
20694
|
+
'leftCall',
|
20695
|
+
/* @conditional-compile-remove(rooms) */ 'deniedPermissionToRoom',
|
20696
|
+
'removedFromCall',
|
20697
|
+
/* @conditional-compile-remove(rooms) */ 'roomNotFound',
|
20698
|
+
/* @conditional-compile-remove(unsupported-browser) */ 'unsupportedEnvironment'
|
20699
|
+
];
|
20700
|
+
|
20817
20701
|
// Copyright (c) Microsoft Corporation.
|
20818
20702
|
// Licensed under the MIT license.
|
20819
20703
|
var __awaiter$f = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
|
@@ -20825,225 +20709,344 @@ var __awaiter$f = (window && window.__awaiter) || function (thisArg, _arguments,
|
|
20825
20709
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
20826
20710
|
});
|
20827
20711
|
};
|
20712
|
+
const ACCESS_DENIED_TEAMS_MEETING_SUB_CODE = 5854;
|
20713
|
+
const REMOTE_PSTN_USER_HUNG_UP = 560000;
|
20714
|
+
const REMOVED_FROM_CALL_SUB_CODES = [5000, 5300, REMOTE_PSTN_USER_HUNG_UP];
|
20715
|
+
/* @conditional-compile-remove(rooms) */
|
20716
|
+
const ROOM_NOT_FOUND_SUB_CODE = 5751;
|
20717
|
+
/* @conditional-compile-remove(rooms) */
|
20718
|
+
const DENIED_PERMISSION_TO_ROOM_SUB_CODE = 5828;
|
20828
20719
|
/**
|
20829
20720
|
* @private
|
20830
20721
|
*/
|
20831
|
-
const
|
20832
|
-
|
20833
|
-
|
20834
|
-
|
20835
|
-
|
20836
|
-
|
20837
|
-
|
20838
|
-
|
20839
|
-
|
20840
|
-
const fetchData = () => __awaiter$f(void 0, void 0, void 0, function* () {
|
20841
|
-
// Fetch initial data for adapter
|
20842
|
-
yield adapter.fetchInitialData();
|
20843
|
-
// Fetch initial set of messages. Without fetching messages here, if the Composite's adapter is changed the message thread does not load new messages.
|
20844
|
-
yield adapter.loadPreviousChatMessages(defaultNumberOfChatMessagesToReload);
|
20845
|
-
});
|
20846
|
-
fetchData();
|
20847
|
-
}, [adapter]);
|
20848
|
-
const messageThreadProps = usePropsFor$2(MessageThread);
|
20849
|
-
const sendBoxProps = usePropsFor$2(SendBox);
|
20850
|
-
const typingIndicatorProps = usePropsFor$2(TypingIndicator);
|
20851
|
-
const headerProps = useAdaptedSelector$1(getHeaderProps);
|
20852
|
-
const errorBarProps = usePropsFor$2(ErrorBar);
|
20853
|
-
const onRenderAvatarCallback = React.useCallback((userId, defaultOptions) => {
|
20854
|
-
return (React__default['default'].createElement(AvatarPersona, Object.assign({ userId: userId, hidePersonaDetails: true }, defaultOptions, { dataProvider: onFetchAvatarPersonaData })));
|
20855
|
-
}, [onFetchAvatarPersonaData]);
|
20856
|
-
const messageThreadStyles = Object.assign({}, messageThreadChatCompositeStyles(theme.semanticColors.bodyBackground), styles === null || styles === void 0 ? void 0 : styles.messageThread);
|
20857
|
-
const typingIndicatorStyles = Object.assign({}, styles === null || styles === void 0 ? void 0 : styles.typingIndicator);
|
20858
|
-
const sendBoxStyles = Object.assign({}, styles === null || styles === void 0 ? void 0 : styles.sendBox);
|
20859
|
-
const userId = toFlatCommunicationIdentifier(adapter.getState().userId);
|
20860
|
-
const fileUploadButtonOnChange = React.useCallback((files) => {
|
20861
|
-
if (!files) {
|
20862
|
-
return;
|
20722
|
+
const isCameraOn = (state) => {
|
20723
|
+
if (state.call) {
|
20724
|
+
const stream = state.call.localVideoStreams.find((stream) => stream.mediaStreamType === 'Video');
|
20725
|
+
return !!stream;
|
20726
|
+
}
|
20727
|
+
else {
|
20728
|
+
if (state.devices.selectedCamera) {
|
20729
|
+
const previewOn = _isPreviewOn(state.devices);
|
20730
|
+
return previewOn;
|
20863
20731
|
}
|
20864
|
-
|
20865
|
-
|
20866
|
-
|
20867
|
-
|
20868
|
-
|
20869
|
-
|
20870
|
-
|
20871
|
-
|
20872
|
-
|
20873
|
-
|
20874
|
-
|
20875
|
-
|
20876
|
-
|
20877
|
-
|
20732
|
+
}
|
20733
|
+
return false;
|
20734
|
+
};
|
20735
|
+
/**
|
20736
|
+
* Reduce the set of call controls visible on mobile.
|
20737
|
+
* For example do not show screenshare button.
|
20738
|
+
*
|
20739
|
+
* @private
|
20740
|
+
*/
|
20741
|
+
const reduceCallControlsForMobile = (callControlOptions) => {
|
20742
|
+
if (callControlOptions === false) {
|
20743
|
+
return false;
|
20744
|
+
}
|
20745
|
+
// Ensure call controls a valid object.
|
20746
|
+
const reduceCallControlOptions = callControlOptions === true ? {} : callControlOptions || {};
|
20747
|
+
// Set to compressed mode when composite is optimized for mobile
|
20748
|
+
reduceCallControlOptions.displayType = 'compact';
|
20749
|
+
// Do not show screen share button when composite is optimized for mobile unless the developer
|
20750
|
+
// has explicitly opted in.
|
20751
|
+
if (reduceCallControlOptions.screenShareButton !== true) {
|
20752
|
+
reduceCallControlOptions.screenShareButton = false;
|
20753
|
+
}
|
20754
|
+
return reduceCallControlOptions;
|
20755
|
+
};
|
20756
|
+
var CallEndReasons;
|
20757
|
+
(function (CallEndReasons) {
|
20758
|
+
CallEndReasons[CallEndReasons["LEFT_CALL"] = 0] = "LEFT_CALL";
|
20759
|
+
CallEndReasons[CallEndReasons["ACCESS_DENIED"] = 1] = "ACCESS_DENIED";
|
20760
|
+
CallEndReasons[CallEndReasons["REMOVED_FROM_CALL"] = 2] = "REMOVED_FROM_CALL";
|
20761
|
+
CallEndReasons[CallEndReasons["ROOM_NOT_FOUND"] = 3] = "ROOM_NOT_FOUND";
|
20762
|
+
CallEndReasons[CallEndReasons["DENIED_PERMISSION_TO_ROOM"] = 4] = "DENIED_PERMISSION_TO_ROOM";
|
20763
|
+
})(CallEndReasons || (CallEndReasons = {}));
|
20764
|
+
const getCallEndReason = (call) => {
|
20765
|
+
var _a, _b, _c, _d, _e;
|
20766
|
+
const remoteParticipantsEndedArray = Array.from(Object.values(call.remoteParticipantsEnded));
|
20767
|
+
/**
|
20768
|
+
* Handle the special case in a PSTN call where removing the last user kicks the caller out of the call.
|
20769
|
+
* The code and subcode is the same as when a user is removed from a teams interop call.
|
20770
|
+
* Hence, we look at the last remote participant removed to determine if the last participant removed was a phone number.
|
20771
|
+
* If yes, the caller was kicked out of the call, but we need to show them that they left the call.
|
20772
|
+
* Note: This check will only work for 1:1 PSTN Calls. The subcode is different for 1:N PSTN calls, and we do not need to handle that case.
|
20773
|
+
*/
|
20774
|
+
if (remoteParticipantsEndedArray.length === 1 &&
|
20775
|
+
communicationCommon.isPhoneNumberIdentifier(remoteParticipantsEndedArray[0].identifier) &&
|
20776
|
+
((_a = call.callEndReason) === null || _a === void 0 ? void 0 : _a.subCode) !== REMOTE_PSTN_USER_HUNG_UP) {
|
20777
|
+
return CallEndReasons.LEFT_CALL;
|
20778
|
+
}
|
20779
|
+
if (((_b = call.callEndReason) === null || _b === void 0 ? void 0 : _b.subCode) && call.callEndReason.subCode === ACCESS_DENIED_TEAMS_MEETING_SUB_CODE) {
|
20780
|
+
return CallEndReasons.ACCESS_DENIED;
|
20781
|
+
}
|
20782
|
+
if (((_c = call.callEndReason) === null || _c === void 0 ? void 0 : _c.subCode) && REMOVED_FROM_CALL_SUB_CODES.includes(call.callEndReason.subCode)) {
|
20783
|
+
return CallEndReasons.REMOVED_FROM_CALL;
|
20784
|
+
}
|
20785
|
+
/* @conditional-compile-remove(rooms) */
|
20786
|
+
if (((_d = call.callEndReason) === null || _d === void 0 ? void 0 : _d.subCode) && call.callEndReason.subCode === ROOM_NOT_FOUND_SUB_CODE) {
|
20787
|
+
return CallEndReasons.ROOM_NOT_FOUND;
|
20788
|
+
}
|
20789
|
+
/* @conditional-compile-remove(rooms) */
|
20790
|
+
if (((_e = call.callEndReason) === null || _e === void 0 ? void 0 : _e.subCode) && call.callEndReason.subCode === DENIED_PERMISSION_TO_ROOM_SUB_CODE) {
|
20791
|
+
return CallEndReasons.DENIED_PERMISSION_TO_ROOM;
|
20792
|
+
}
|
20793
|
+
if (call.callEndReason) {
|
20794
|
+
// No error codes match, assume the user simply left the call regularly
|
20795
|
+
return CallEndReasons.LEFT_CALL;
|
20796
|
+
}
|
20797
|
+
throw new Error('No matching call end reason');
|
20798
|
+
};
|
20799
|
+
/**
|
20800
|
+
* Get the current call composite page based on the current call composite state
|
20801
|
+
*
|
20802
|
+
* @param Call - The current call state
|
20803
|
+
* @param previousCall - The state of the most recent previous call that has ended.
|
20804
|
+
*
|
20805
|
+
* @remarks - The previousCall state is needed to determine if the call has ended.
|
20806
|
+
* When the call ends a new call object is created, and so we must lookback at the
|
20807
|
+
* previous call state to understand how the call has ended. If there is no previous
|
20808
|
+
* call we know that this is a fresh call and can display the configuration page.
|
20809
|
+
*
|
20810
|
+
* @private
|
20811
|
+
*/
|
20812
|
+
const getCallCompositePage = (call, previousCall, unsupportedBrowserInfo, transferCall) => {
|
20813
|
+
/* @conditional-compile-remove(unsupported-browser) */
|
20814
|
+
if (isUnsupportedEnvironment(unsupportedBrowserInfo.environmentInfo, unsupportedBrowserInfo.unsupportedBrowserVersionOptedIn)) {
|
20815
|
+
return 'unsupportedEnvironment';
|
20816
|
+
}
|
20817
|
+
/* @conditional-compile-remove(call-transfer) */
|
20818
|
+
if (transferCall !== undefined) {
|
20819
|
+
return 'transferring';
|
20820
|
+
}
|
20821
|
+
if (call) {
|
20822
|
+
// Must check for ongoing call *before* looking at any previous calls.
|
20823
|
+
// If the composite completes one call and joins another, the previous calls
|
20824
|
+
// will be populated, but not relevant for determining the page.
|
20825
|
+
// `_isInLobbyOrConnecting` needs to be checked first because `_isInCall` also returns true when call is in lobby.
|
20826
|
+
if (_isInLobbyOrConnecting(call === null || call === void 0 ? void 0 : call.state)) {
|
20827
|
+
return 'lobby';
|
20828
|
+
// `LocalHold` needs to be checked before `isInCall` since it is also a state that's considered in call.
|
20878
20829
|
}
|
20879
|
-
|
20880
|
-
|
20881
|
-
|
20882
|
-
if (!(fileSharing === null || fileSharing === void 0 ? void 0 : fileSharing.uploadHandler)) {
|
20883
|
-
return null;
|
20830
|
+
else if ((call === null || call === void 0 ? void 0 : call.state) === 'LocalHold') {
|
20831
|
+
/* @conditional-compile-remove(PSTN-calls) */ /* @conditional-compile-remove(one-to-n-calling) */
|
20832
|
+
return 'hold';
|
20884
20833
|
}
|
20885
|
-
|
20886
|
-
|
20887
|
-
|
20888
|
-
(
|
20889
|
-
|
20890
|
-
|
20891
|
-
|
20892
|
-
|
20893
|
-
|
20894
|
-
|
20895
|
-
|
20896
|
-
|
20897
|
-
|
20898
|
-
|
20899
|
-
|
20900
|
-
|
20901
|
-
|
20902
|
-
|
20903
|
-
|
20904
|
-
|
20905
|
-
|
20906
|
-
|
20907
|
-
|
20908
|
-
|
20909
|
-
|
20910
|
-
|
20911
|
-
|
20912
|
-
|
20913
|
-
|
20914
|
-
|
20834
|
+
else if ((call === null || call === void 0 ? void 0 : call.state) === 'Disconnecting') {
|
20835
|
+
return 'leaving';
|
20836
|
+
}
|
20837
|
+
else if (_isInCall(call === null || call === void 0 ? void 0 : call.state)) {
|
20838
|
+
return 'call';
|
20839
|
+
}
|
20840
|
+
else {
|
20841
|
+
// When the call object has been constructed after clicking , but before 'connecting' has been
|
20842
|
+
// set on the call object, we continue to show the configuration screen.
|
20843
|
+
// The call object does not correctly reflect local device state until `call.state` moves to `connecting`.
|
20844
|
+
// Moving to the 'lobby' page too soon leads to components that depend on the `call` object to show incorrect
|
20845
|
+
// transitional state.
|
20846
|
+
return 'configuration';
|
20847
|
+
}
|
20848
|
+
}
|
20849
|
+
if (previousCall) {
|
20850
|
+
const reason = getCallEndReason(previousCall);
|
20851
|
+
/* @conditional-compile-remove(rooms) */
|
20852
|
+
switch (reason) {
|
20853
|
+
case CallEndReasons.ROOM_NOT_FOUND:
|
20854
|
+
return 'roomNotFound';
|
20855
|
+
case CallEndReasons.DENIED_PERMISSION_TO_ROOM:
|
20856
|
+
return 'deniedPermissionToRoom';
|
20857
|
+
}
|
20858
|
+
switch (reason) {
|
20859
|
+
case CallEndReasons.ACCESS_DENIED:
|
20860
|
+
return 'accessDeniedTeamsMeeting';
|
20861
|
+
case CallEndReasons.REMOVED_FROM_CALL:
|
20862
|
+
return 'removedFromCall';
|
20863
|
+
case CallEndReasons.LEFT_CALL:
|
20864
|
+
if (previousCall.diagnostics.network.latest.noNetwork) {
|
20865
|
+
return 'joinCallFailedDueToNoNetwork';
|
20866
|
+
}
|
20867
|
+
return 'leftCall';
|
20868
|
+
}
|
20869
|
+
}
|
20870
|
+
// No call state - show starting page (configuration)
|
20871
|
+
return 'configuration';
|
20872
|
+
};
|
20873
|
+
/** @private */
|
20874
|
+
const IsCallEndedPage = (
|
20875
|
+
/**
|
20876
|
+
* Explicitly listing the pages of this function intentionally.
|
20877
|
+
* This protects against adding a new composite page that should be marked as an callEndedPage.
|
20878
|
+
* EndCallPages are used to trigger onCallEnded events so this could easily be missed.
|
20879
|
+
* When you add a new composite page this will throw a compiler error. If this new page is an
|
20880
|
+
* EndCallPage ensure you update the END_CALL_PAGES. Afterwards update the `page` parameter
|
20881
|
+
* type below to allow your new page, i.e. add `| <your new page>
|
20882
|
+
*/
|
20883
|
+
page) => END_CALL_PAGES.includes(page);
|
20884
|
+
/**
|
20885
|
+
* Creates a new call control options object and sets the correct values for disabling
|
20886
|
+
* the buttons provided in the `disabledControls` array.
|
20887
|
+
* Returns a new object without changing the original object.
|
20888
|
+
* @param callControlOptions options for the call control component that need to be modified.
|
20889
|
+
* @param disabledControls An array of controls to disable.
|
20890
|
+
* @returns a copy of callControlOptions with disabledControls disabled
|
20891
|
+
* @private
|
20892
|
+
*/
|
20893
|
+
const disableCallControls = (callControlOptions, disabledControls) => {
|
20894
|
+
var _a;
|
20895
|
+
if (callControlOptions === false) {
|
20896
|
+
return false;
|
20897
|
+
}
|
20898
|
+
// Ensure we clone the prop if it is an object to ensure we do not mutate the original prop.
|
20899
|
+
let newOptions = (_a = (callControlOptions instanceof Object ? Object.assign({}, callControlOptions) : callControlOptions)) !== null && _a !== void 0 ? _a : {};
|
20900
|
+
if (newOptions === true || newOptions === undefined) {
|
20901
|
+
newOptions = disabledControls.reduce((acc, key) => {
|
20902
|
+
acc[key] = { disabled: true };
|
20903
|
+
return acc;
|
20904
|
+
}, {});
|
20905
|
+
}
|
20906
|
+
else {
|
20907
|
+
disabledControls.forEach((key) => {
|
20908
|
+
if (newOptions[key] !== false) {
|
20909
|
+
newOptions[key] = { disabled: true };
|
20910
|
+
}
|
20911
|
+
});
|
20912
|
+
}
|
20913
|
+
return newOptions;
|
20915
20914
|
};
|
20916
|
-
|
20917
|
-
// Copyright (c) Microsoft Corporation.
|
20918
20915
|
/**
|
20919
|
-
*
|
20920
|
-
*
|
20921
|
-
* @remarks Chat composite min width and height are respectively 17.5rem and 20rem (280px and 320px, with default rem at 16px)
|
20916
|
+
* Check if a disabled object is provided for a button and returns if the button is disabled.
|
20917
|
+
* A button is only disabled if is explicitly set to disabled.
|
20922
20918
|
*
|
20923
|
-
* @
|
20919
|
+
* @param option
|
20920
|
+
* @returns whether a button is disabled
|
20921
|
+
* @private
|
20924
20922
|
*/
|
20925
|
-
const
|
20926
|
-
|
20927
|
-
|
20928
|
-
|
20929
|
-
|
20930
|
-
* @private
|
20931
|
-
*/
|
20932
|
-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
20933
|
-
const fileSharingOptions = () => {
|
20934
|
-
/* @conditional-compile-remove(file-sharing) */
|
20935
|
-
return {
|
20936
|
-
fileSharing: options === null || options === void 0 ? void 0 : options.fileSharing
|
20937
|
-
};
|
20938
|
-
};
|
20939
|
-
return (React__default['default'].createElement("div", { className: chatScreenContainerStyle },
|
20940
|
-
React__default['default'].createElement(BaseProvider, Object.assign({}, props),
|
20941
|
-
React__default['default'].createElement(ChatAdapterProvider, { adapter: adapter },
|
20942
|
-
React__default['default'].createElement(ChatScreen, Object.assign({ formFactor: formFactor, options: options, onFetchAvatarPersonaData: onFetchAvatarPersonaData, onRenderTypingIndicator: onRenderTypingIndicator, onRenderMessage: onRenderMessage, onFetchParticipantMenuItems: onFetchParticipantMenuItems }, fileSharingOptions()))))));
|
20923
|
+
const isDisabled$2 = (option) => {
|
20924
|
+
if (option === undefined || typeof option === 'boolean') {
|
20925
|
+
return false;
|
20926
|
+
}
|
20927
|
+
return option.disabled;
|
20943
20928
|
};
|
20944
|
-
|
20945
|
-
|
20946
|
-
|
20929
|
+
/* @conditional-compile-remove(call-readiness) */
|
20930
|
+
/**
|
20931
|
+
* @returns Permissions state for the camera.
|
20932
|
+
*/
|
20933
|
+
const queryCameraPermissionFromPermissionsAPI = () => __awaiter$f(void 0, void 0, void 0, function* () {
|
20934
|
+
try {
|
20935
|
+
return (yield navigator.permissions.query({ name: 'camera' })).state;
|
20936
|
+
}
|
20937
|
+
catch (e) {
|
20938
|
+
console.info('permissions API is not supported by browser', e);
|
20939
|
+
return 'unsupported';
|
20940
|
+
}
|
20941
|
+
});
|
20942
|
+
/* @conditional-compile-remove(call-readiness) */
|
20943
|
+
/**
|
20944
|
+
* @returns Permissions state for the microphone.
|
20945
|
+
*/
|
20946
|
+
const queryMicrophonePermissionFromPermissionsAPI = () => __awaiter$f(void 0, void 0, void 0, function* () {
|
20947
|
+
try {
|
20948
|
+
return (yield navigator.permissions.query({ name: 'microphone' })).state;
|
20949
|
+
}
|
20950
|
+
catch (e) {
|
20951
|
+
console.info('permissions API is not supported by browser', e);
|
20952
|
+
return 'unsupported';
|
20953
|
+
}
|
20954
|
+
});
|
20955
|
+
/* @conditional-compile-remove(call-readiness) */
|
20947
20956
|
/**
|
20957
|
+
*
|
20958
|
+
* This function uses permission API to determine if device permission state is granted, prompt or denied
|
20959
|
+
* @returns whether device permission state is granted, prompt or denied
|
20960
|
+
* If permission API is not supported on this browser, permission state is set to unsupported.
|
20948
20961
|
* @private
|
20949
20962
|
*/
|
20950
|
-
const
|
20951
|
-
const
|
20952
|
-
|
20963
|
+
const getDevicePermissionState = (setVideoState, setAudioState) => __awaiter$f(void 0, void 0, void 0, function* () {
|
20964
|
+
const [cameraResult, microphoneResult] = yield Promise.all([
|
20965
|
+
queryCameraPermissionFromPermissionsAPI(),
|
20966
|
+
queryMicrophonePermissionFromPermissionsAPI()
|
20967
|
+
]);
|
20968
|
+
setVideoState(cameraResult);
|
20969
|
+
setAudioState(microphoneResult);
|
20970
|
+
});
|
20971
|
+
/* @conditional-compile-remove(unsupported-browser) */
|
20972
|
+
const isUnsupportedEnvironment = (environmentInfo, unsupportedBrowserVersionOptedIn) => {
|
20973
|
+
return !!((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowser) === false ||
|
20974
|
+
((environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedBrowserVersion) === false && !unsupportedBrowserVersionOptedIn) ||
|
20975
|
+
(environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.isSupportedPlatform) === false);
|
20953
20976
|
};
|
20954
20977
|
/**
|
20978
|
+
* Check if we are using safari browser
|
20955
20979
|
* @private
|
20956
20980
|
*/
|
20957
|
-
const
|
20958
|
-
|
20959
|
-
|
20960
|
-
throw 'Cannot find adapter please initialize before usage.';
|
20961
|
-
}
|
20962
|
-
return adapter;
|
20981
|
+
const _isSafari = (environmentInfo) => {
|
20982
|
+
/* @conditional-compile-remove(unsupported-browser) */
|
20983
|
+
return (environmentInfo === null || environmentInfo === void 0 ? void 0 : environmentInfo.environment.browser) === 'safari';
|
20963
20984
|
};
|
20964
|
-
|
20965
|
-
// Copyright (c) Microsoft Corporation.
|
20966
20985
|
/**
|
20967
20986
|
* @private
|
20987
|
+
* This is the util function to create a participant modifier for remote participantList
|
20988
|
+
* It memoize previous original participant items and only update the changed participant
|
20989
|
+
* It takes in one modifier function to generate one single participant object, it returns undefined if the object keeps unmodified
|
20968
20990
|
*/
|
20969
|
-
const
|
20970
|
-
|
20991
|
+
const createParticipantModifier = (createModifiedParticipant) => {
|
20992
|
+
let previousParticipantState = undefined;
|
20993
|
+
let modifiedParticipants = {};
|
20994
|
+
const memoizedParticipants = {};
|
20995
|
+
return (state) => {
|
20996
|
+
var _a, _b, _c, _d;
|
20997
|
+
// if root state is the same, we don't need to update the participants
|
20998
|
+
if (((_a = state.call) === null || _a === void 0 ? void 0 : _a.remoteParticipants) !== previousParticipantState) {
|
20999
|
+
modifiedParticipants = {};
|
21000
|
+
const originalParticipants = (_b = state.call) === null || _b === void 0 ? void 0 : _b.remoteParticipants;
|
21001
|
+
for (const key in originalParticipants) {
|
21002
|
+
const modifiedParticipant = createModifiedParticipant(key, originalParticipants[key]);
|
21003
|
+
if (modifiedParticipant === undefined) {
|
21004
|
+
modifiedParticipants[key] = originalParticipants[key];
|
21005
|
+
continue;
|
21006
|
+
}
|
21007
|
+
// Generate the new item if original cached item has been changed
|
21008
|
+
if (((_c = memoizedParticipants[key]) === null || _c === void 0 ? void 0 : _c.originalRef) !== originalParticipants[key]) {
|
21009
|
+
memoizedParticipants[key] = {
|
21010
|
+
newParticipant: modifiedParticipant,
|
21011
|
+
originalRef: originalParticipants[key]
|
21012
|
+
};
|
21013
|
+
}
|
21014
|
+
// the modified participant is always coming from the memoized cache, whether is was refreshed
|
21015
|
+
// from the previous closure or not
|
21016
|
+
modifiedParticipants[key] = memoizedParticipants[key].newParticipant;
|
21017
|
+
}
|
21018
|
+
previousParticipantState = (_d = state.call) === null || _d === void 0 ? void 0 : _d.remoteParticipants;
|
21019
|
+
}
|
21020
|
+
return Object.assign(Object.assign({}, state), { call: state.call
|
21021
|
+
? Object.assign(Object.assign({}, state.call), { remoteParticipants: modifiedParticipants }) : undefined });
|
21022
|
+
};
|
20971
21023
|
};
|
20972
21024
|
/**
|
20973
21025
|
* @private
|
20974
21026
|
*/
|
20975
|
-
const
|
21027
|
+
const dismissVideoEffectsError = (toDismiss) => {
|
20976
21028
|
var _a;
|
20977
|
-
const
|
20978
|
-
|
20979
|
-
//
|
20980
|
-
|
20981
|
-
|
20982
|
-
|
20983
|
-
|
20984
|
-
mounted.current = false;
|
20985
|
-
};
|
20986
|
-
});
|
20987
|
-
const callId = (_a = adapter.getState().call) === null || _a === void 0 ? void 0 : _a.id;
|
20988
|
-
const callConfigProps = React.useMemo(() => ({
|
20989
|
-
callId
|
20990
|
-
}), [callId]);
|
20991
|
-
const [props, setProps] = React.useState(selector(adaptState(adapter.getState()), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps));
|
20992
|
-
const propRef = React.useRef(props);
|
20993
|
-
propRef.current = props;
|
20994
|
-
React.useEffect(() => {
|
20995
|
-
const onStateChange = (state) => {
|
20996
|
-
if (!mounted.current) {
|
20997
|
-
return;
|
20998
|
-
}
|
20999
|
-
const newProps = selector(adaptState(state), selectorProps !== null && selectorProps !== void 0 ? selectorProps : callConfigProps);
|
21000
|
-
if (propRef.current !== newProps) {
|
21001
|
-
setProps(newProps);
|
21002
|
-
}
|
21003
|
-
};
|
21004
|
-
adapter.onStateChange(onStateChange);
|
21005
|
-
return () => {
|
21006
|
-
adapter.offStateChange(onStateChange);
|
21007
|
-
};
|
21008
|
-
}, [adaptState, adapter, selector, selectorProps, callConfigProps]);
|
21009
|
-
return props;
|
21010
|
-
};
|
21011
|
-
const memoizeState = memoizeOne__default['default']((userId, deviceManager, calls, latestErrors, displayName, alternateCallerId, environmentInfo) => ({
|
21012
|
-
userId,
|
21013
|
-
incomingCalls: {},
|
21014
|
-
incomingCallsEnded: {},
|
21015
|
-
callsEnded: {},
|
21016
|
-
deviceManager,
|
21017
|
-
callAgent: { displayName },
|
21018
|
-
calls,
|
21019
|
-
latestErrors,
|
21020
|
-
/* @conditional-compile-remove(PSTN-calls) */
|
21021
|
-
alternateCallerId,
|
21022
|
-
/* @conditional-compile-remove(unsupported-browser) */
|
21023
|
-
environmentInfo
|
21024
|
-
}));
|
21025
|
-
const memoizeCalls = memoizeOne__default['default']((call) => (call ? { [call.id]: call } : {}));
|
21026
|
-
const adaptCompositeState = (compositeState) => {
|
21027
|
-
return memoizeState(compositeState.userId, compositeState.devices, memoizeCalls(compositeState.call),
|
21028
|
-
// This is an unsafe type expansion.
|
21029
|
-
// compositeState.latestErrors can contain properties that are not valid in CallErrors.
|
21030
|
-
//
|
21031
|
-
// But there is no way to check for valid property names at runtime:
|
21032
|
-
// - The set of valid property names is built from types in the @azure/communication-calling.
|
21033
|
-
// Thus we don't have a literal array of allowed strings at runtime.
|
21034
|
-
// - Due to minification / uglification, the property names from the objects at runtime can't be used
|
21035
|
-
// to compare against permissible values inferred from the types.
|
21036
|
-
//
|
21037
|
-
// This is not a huge problem -- it simply means that our adapted selector will include some extra operations
|
21038
|
-
// that are unknown to the UI component and data binding libraries. Generic handling of the errors (e.g.,
|
21039
|
-
// just displaying them in some UI surface) will continue to work for these operations. Handling of
|
21040
|
-
// specific operations (e.g., acting on errors related to permission issues) will ignore these operations.
|
21041
|
-
compositeState.latestErrors, compositeState.displayName,
|
21042
|
-
/* @conditional-compile-remove(PSTN-calls) */
|
21043
|
-
compositeState.alternateCallerId,
|
21044
|
-
/* @conditional-compile-remove(unsupported-browser) */
|
21045
|
-
compositeState.environmentInfo);
|
21029
|
+
const now = new Date(Date.now());
|
21030
|
+
const toDismissTimestamp = (_a = toDismiss.timestamp) !== null && _a !== void 0 ? _a : now;
|
21031
|
+
// Record that this error was dismissed for the first time right now.
|
21032
|
+
return {
|
21033
|
+
dismissedAt: now > toDismissTimestamp ? now : toDismissTimestamp,
|
21034
|
+
activeSince: toDismiss.timestamp
|
21035
|
+
};
|
21046
21036
|
};
|
21037
|
+
/* @conditional-compile-remove(video-background-effects) */
|
21038
|
+
/** @private */
|
21039
|
+
const getBackgroundEffectFromSelectedEffect = (selectedEffect) => (selectedEffect === null || selectedEffect === void 0 ? void 0 : selectedEffect.effectName) === 'blur'
|
21040
|
+
? new communicationCallingEffects.BackgroundBlurEffect()
|
21041
|
+
: (selectedEffect === null || selectedEffect === void 0 ? void 0 : selectedEffect.effectName) === 'replacement'
|
21042
|
+
? new communicationCallingEffects.BackgroundReplacementEffect({ backgroundImageUrl: selectedEffect.backgroundImageUrl })
|
21043
|
+
: undefined;
|
21044
|
+
/* @conditional-compile-remove(video-background-effects) */
|
21045
|
+
/**
|
21046
|
+
* @remarks this logic should mimic the onToggleCamera in the common call handlers.
|
21047
|
+
* @private
|
21048
|
+
*/
|
21049
|
+
const getSelectedCameraFromAdapterState = (state) => state.devices.selectedCamera || state.devices.cameras[0];
|
21047
21050
|
|
21048
21051
|
// Copyright (c) Microsoft Corporation.
|
21049
21052
|
// Licensed under the MIT license.
|
@@ -27614,7 +27617,7 @@ class AzureCommunicationCallAdapter {
|
|
27614
27617
|
const createAzureCommunicationCallAdapter = ({ userId, displayName, credential, locator,
|
27615
27618
|
/* @conditional-compile-remove(PSTN-calls) */ alternateCallerId,
|
27616
27619
|
/* @conditional-compile-remove(video-background-effects) */ options }) => __awaiter$3(void 0, void 0, void 0, function* () {
|
27617
|
-
if (!
|
27620
|
+
if (!_isValidIdentifier(userId)) {
|
27618
27621
|
throw new Error('Invalid identifier. Please provide valid identifier object.');
|
27619
27622
|
}
|
27620
27623
|
const callClient = createStatefulCallClient({
|