communication-react-19
Version:
React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)
114 lines • 7.17 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
/**
* Create a record for when the notification was most recently dismissed for tracking dismissed notifications.
*
* @private
*/
export const useTrackedCapabilityChangedNotifications = (capabilitiesChangedAndRoleInfo) => {
const [trackedCapabilityChangedNotifications, setTrackedCapabilityChangedNotifications] = useState({});
const activeNotifications = useRef({});
useEffect(() => {
activeNotifications.current = updateLatestCapabilityChangedNotificationMap(capabilitiesChangedAndRoleInfo, activeNotifications.current);
setTrackedCapabilityChangedNotifications((prev) => updateTrackedCapabilityChangedNotificationsWithActiveNotifications(prev, Object.values(activeNotifications.current)));
}, [capabilitiesChangedAndRoleInfo]);
const onDismissCapabilityChangedNotification = useCallback((notification) => {
setTrackedCapabilityChangedNotifications((prev) => trackCapabilityChangedNotificationAsDismissed(notification.capabilityName, prev));
}, []);
const latestCapabilityChangedNotifications = useMemo(() => filterLatestCapabilityChangedNotifications(Object.values(activeNotifications.current), trackedCapabilityChangedNotifications), [trackedCapabilityChangedNotifications]);
return {
capabilitiesChangedNotifications: latestCapabilityChangedNotifications,
onDismissNotification: onDismissCapabilityChangedNotification
};
};
/**
* Take the set of active notifications, and filter to only those that are newer than previously dismissed notifications or have never been dismissed.
*
* @private
*/
export const filterLatestCapabilityChangedNotifications = (activeNotifications, trackedNotifications) => {
const filteredNotifications = activeNotifications.filter((activeNotification) => {
const trackedNotification = trackedNotifications[activeNotification.capabilityName];
return (!trackedNotification ||
!trackedNotification.lastDismissedAt ||
trackedNotification.lastDismissedAt < trackedNotification.mostRecentlyActive);
});
return filteredNotifications;
};
/**
* Maintain a record of the most recently active notification for each capability name.
*
* @private
*/
export const updateTrackedCapabilityChangedNotificationsWithActiveNotifications = (existingTrackedNotifications, activeNotifications) => {
var _a, _b;
const trackedNotifications = {};
// Only care about active notifications. If notifications are no longer active we do not track that they have been previously dismissed.
for (const activeNotification of activeNotifications) {
const existingTrackedNotification = existingTrackedNotifications[activeNotification.capabilityName];
trackedNotifications[activeNotification.capabilityName] = {
mostRecentlyActive: (_b = (_a = activeNotification.timestamp) !== null && _a !== void 0 ? _a : existingTrackedNotification === null || existingTrackedNotification === void 0 ? void 0 : existingTrackedNotification.mostRecentlyActive) !== null && _b !== void 0 ? _b : new Date(Date.now()),
lastDismissedAt: existingTrackedNotification === null || existingTrackedNotification === void 0 ? void 0 : existingTrackedNotification.lastDismissedAt
};
}
return trackedNotifications;
};
/**
* Create a record for when the notification was most recently dismissed for tracking dismissed notifications.
*
* @private
*/
export const trackCapabilityChangedNotificationAsDismissed = (capabilityName, trackedNotifications) => {
const now = new Date(Date.now());
const existingNotification = trackedNotifications[capabilityName];
return Object.assign(Object.assign({}, trackedNotifications), { [capabilityName]: Object.assign(Object.assign({}, (existingNotification || {})), { lastDismissedAt: now }) });
};
const updateLatestCapabilityChangedNotificationMap = (capabilitiesChangedInfoAndRole, activeNotifications) => {
var _a, _b;
if (!capabilitiesChangedInfoAndRole.capabilitiesChangeInfo) {
return activeNotifications;
}
for (const [capabilityKey, newCapabilityValue] of Object.entries(capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.newValue)) {
// Cast is safe because we are iterating over the enum keys on the object.entries where
// newCapabilityValue typing is correctly returned. Object.entries limitations
// always returns string for the key
const capabilityName = capabilityKey;
// If the active notification for a capability has the same `isPresent` value and the same reason as the new
// capability value from the SDK then we will not create a new notification to avoid redundancy
if (activeNotifications[capabilityName] &&
newCapabilityValue.isPresent === ((_a = activeNotifications[capabilityName]) === null || _a === void 0 ? void 0 : _a.isPresent) &&
capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason ===
((_b = activeNotifications[capabilityName]) === null || _b === void 0 ? void 0 : _b.changedReason)) {
continue;
}
// All initial values of capabilities are not present with reason 'FeatureNotSupported'. So we should not show a
// notification for them when they initially become present at the start of the call
const oldCapabilityValue = capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.oldValue[capabilityName];
if (newCapabilityValue.isPresent === true &&
(oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.isPresent) === false &&
(oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.reason) === 'FeatureNotSupported' &&
capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason === 'MeetingOptionOrOrganizerPolicyChanged') {
continue;
}
// Do not show the first time the screenshare capability is present when the user's role is resolved to mirror
// Teams behaviour
if (capabilityName === 'shareScreen' &&
activeNotifications['shareScreen'] === undefined &&
newCapabilityValue.isPresent === true &&
(oldCapabilityValue === null || oldCapabilityValue === void 0 ? void 0 : oldCapabilityValue.isPresent) === false &&
capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason === 'RoleChanged') {
continue;
}
const newCapabilityChangeNotification = {
capabilityName: capabilityName,
isPresent: newCapabilityValue.isPresent,
changedReason: capabilitiesChangedInfoAndRole.capabilitiesChangeInfo.reason,
role: capabilitiesChangedInfoAndRole.participantRole,
timestamp: new Date(Date.now())
};
activeNotifications[capabilityName] = newCapabilityChangeNotification;
}
return activeNotifications;
};
//# sourceMappingURL=TrackCapabilityChangedNotifications.js.map