matrix-react-sdk
Version:
SDK for matrix.org using React
224 lines (219 loc) • 34.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.READ_AVATAR_SIZE = void 0;
exports.ReadReceiptGroup = ReadReceiptGroup;
exports.ReadReceiptPerson = ReadReceiptPerson;
exports.determineAvatarPosition = determineAvatarPosition;
exports.readReceiptTooltip = readReceiptTooltip;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _react = _interopRequireDefault(require("react"));
var _compoundWeb = require("@vector-im/compound-web");
var _ReadReceiptMarker = _interopRequireDefault(require("./ReadReceiptMarker"));
var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton"));
var _MemberAvatar = _interopRequireDefault(require("../avatars/MemberAvatar"));
var _AutoHideScrollbar = _interopRequireDefault(require("../../structures/AutoHideScrollbar"));
var _DateUtils = require("../../../DateUtils");
var _actions = require("../../../dispatcher/actions");
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _ContextMenu = _interopRequireWildcard(require("../../structures/ContextMenu"));
var _languageHandler = require("../../../languageHandler");
var _RovingTabIndex = require("../../../accessibility/RovingTabIndex");
var _FormattingUtils = require("../../../utils/FormattingUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
// #20547 Design specified that we should show the three latest read receipts
const MAX_READ_AVATARS_PLUS_N = 3;
// #21935 If we’ve got just 4, don’t show +1, just show all of them
const MAX_READ_AVATARS = MAX_READ_AVATARS_PLUS_N + 1;
const READ_AVATAR_OFFSET = 10;
const READ_AVATAR_SIZE = exports.READ_AVATAR_SIZE = 16;
function determineAvatarPosition(index, max) {
if (index < max) {
return {
hidden: false,
position: index
};
} else {
return {
hidden: true,
position: 0
};
}
}
function readReceiptTooltip(members, maxAvatars) {
return (0, _FormattingUtils.formatList)(members, maxAvatars);
}
function ReadReceiptGroup({
readReceipts,
readReceiptMap,
checkUnmounting,
suppressAnimation,
isTwelveHour
}) {
const [menuDisplayed, button, openMenu, closeMenu] = (0, _ContextMenu.useContextMenu)();
// If we are above MAX_READ_AVATARS, we’ll have to remove a few to have space for the +n count.
const hasMore = readReceipts.length > MAX_READ_AVATARS;
const maxAvatars = hasMore ? MAX_READ_AVATARS_PLUS_N : MAX_READ_AVATARS;
const tooltipMembers = readReceipts.map(it => it.roomMember?.name ?? it.userId);
const tooltipText = readReceiptTooltip(tooltipMembers, maxAvatars);
// return early if there are no read receipts
if (readReceipts.length === 0) {
// We currently must include `mx_ReadReceiptGroup_container` in
// the DOM of all events, as it is the positioned parent of the
// animated read receipts. We can't let it unmount when a receipt
// moves events, so for now we mount it for all events. Without
// it, the animation will start from the top of the timeline
// (because it lost its container).
// See also https://github.com/vector-im/element-web/issues/17561
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_EventTile_msgOption"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_ReadReceiptGroup"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_ReadReceiptGroup_button"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "mx_ReadReceiptGroup_container"
}))));
}
const avatars = readReceipts.map((receipt, index) => {
const {
hidden,
position
} = determineAvatarPosition(index, maxAvatars);
const userId = receipt.userId;
let readReceiptPosition;
if (readReceiptMap) {
readReceiptPosition = readReceiptMap[userId];
if (!readReceiptPosition) {
readReceiptPosition = {};
readReceiptMap[userId] = readReceiptPosition;
}
}
return /*#__PURE__*/_react.default.createElement(_ReadReceiptMarker.default, {
key: userId,
member: receipt.roomMember,
fallbackUserId: userId,
offset: position * READ_AVATAR_OFFSET,
hidden: hidden,
readReceiptPosition: readReceiptPosition,
checkUnmounting: checkUnmounting,
suppressAnimation: suppressAnimation,
timestamp: receipt.ts,
showTwelveHour: isTwelveHour
});
}).reverse();
let remText;
const remainder = readReceipts.length - maxAvatars;
if (remainder > 0) {
remText = /*#__PURE__*/_react.default.createElement("span", {
className: "mx_ReadReceiptGroup_remainder",
"aria-live": "off"
}, "+", remainder);
}
let contextMenu;
if (menuDisplayed && button.current) {
const buttonRect = button.current.getBoundingClientRect();
contextMenu = /*#__PURE__*/_react.default.createElement(_ContextMenu.default, (0, _extends2.default)({
menuClassName: "mx_ReadReceiptGroup_popup",
onFinished: closeMenu
}, (0, _ContextMenu.aboveLeftOf)(buttonRect)), /*#__PURE__*/_react.default.createElement(_AutoHideScrollbar.default, null, /*#__PURE__*/_react.default.createElement(SectionHeader, {
className: "mx_ReadReceiptGroup_title"
}, (0, _languageHandler._t)("timeline|read_receipt_title", {
count: readReceipts.length
})), readReceipts.map(receipt => /*#__PURE__*/_react.default.createElement(ReadReceiptPerson, (0, _extends2.default)({
key: receipt.userId
}, receipt, {
isTwelveHour: isTwelveHour,
onAfterClick: closeMenu
})))));
}
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_EventTile_msgOption"
}, /*#__PURE__*/_react.default.createElement(_compoundWeb.Tooltip, {
label: (0, _languageHandler._t)("timeline|read_receipt_title", {
count: readReceipts.length
}),
caption: tooltipText,
placement: "top-end"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_ReadReceiptGroup",
role: "group",
"aria-label": (0, _languageHandler._t)("timeline|read_receipts_label")
}, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
className: "mx_ReadReceiptGroup_button",
ref: button,
"aria-label": tooltipText,
"aria-haspopup": "true",
onClick: openMenu
}, remText, /*#__PURE__*/_react.default.createElement("span", {
className: "mx_ReadReceiptGroup_container",
style: {
width: Math.min(maxAvatars, readReceipts.length) * READ_AVATAR_OFFSET + READ_AVATAR_SIZE - READ_AVATAR_OFFSET
}
}, avatars)), contextMenu)));
}
// Export for testing
function ReadReceiptPerson({
userId,
roomMember,
ts,
isTwelveHour,
onAfterClick
}) {
return /*#__PURE__*/_react.default.createElement(_compoundWeb.Tooltip, {
description: roomMember?.rawDisplayName ?? userId,
caption: userId,
placement: "top"
}, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_ContextMenu.MenuItem, {
className: "mx_ReadReceiptGroup_person",
onClick: () => {
_dispatcher.default.dispatch({
action: _actions.Action.ViewUser,
// XXX: We should be using a real member object and not assuming what the receiver wants.
// The ViewUser action leads to the RightPanelStore, and RightPanelStoreIPanelState defines the
// member property of IRightPanelCardState as `RoomMember | User`, so we’re fine for now, but we
// should definitely clean this up later
member: roomMember ?? {
userId
},
push: false
});
onAfterClick?.();
}
}, /*#__PURE__*/_react.default.createElement(_MemberAvatar.default, {
member: roomMember,
fallbackUserId: userId,
size: "24px",
"aria-hidden": "true",
"aria-live": "off",
resizeMethod: "crop",
hideTitle: true
}), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_ReadReceiptGroup_name"
}, /*#__PURE__*/_react.default.createElement("p", null, roomMember?.name ?? userId), /*#__PURE__*/_react.default.createElement("p", {
className: "mx_ReadReceiptGroup_secondary"
}, (0, _DateUtils.formatDate)(new Date(ts), isTwelveHour))))));
}
function SectionHeader({
className,
children
}) {
const [onFocus,, ref] = (0, _RovingTabIndex.useRovingTabIndex)();
return /*#__PURE__*/_react.default.createElement("h3", {
className: className,
role: "menuitem",
onFocus: onFocus,
tabIndex: -1,
ref: ref
}, children);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9jb21wb3VuZFdlYiIsIl9SZWFkUmVjZWlwdE1hcmtlciIsIl9BY2Nlc3NpYmxlQnV0dG9uIiwiX01lbWJlckF2YXRhciIsIl9BdXRvSGlkZVNjcm9sbGJhciIsIl9EYXRlVXRpbHMiLCJfYWN0aW9ucyIsIl9kaXNwYXRjaGVyIiwiX0NvbnRleHRNZW51IiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX1JvdmluZ1RhYkluZGV4IiwiX0Zvcm1hdHRpbmdVdGlscyIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIk1BWF9SRUFEX0FWQVRBUlNfUExVU19OIiwiTUFYX1JFQURfQVZBVEFSUyIsIlJFQURfQVZBVEFSX09GRlNFVCIsIlJFQURfQVZBVEFSX1NJWkUiLCJleHBvcnRzIiwiZGV0ZXJtaW5lQXZhdGFyUG9zaXRpb24iLCJpbmRleCIsIm1heCIsImhpZGRlbiIsInBvc2l0aW9uIiwicmVhZFJlY2VpcHRUb29sdGlwIiwibWVtYmVycyIsIm1heEF2YXRhcnMiLCJmb3JtYXRMaXN0IiwiUmVhZFJlY2VpcHRHcm91cCIsInJlYWRSZWNlaXB0cyIsInJlYWRSZWNlaXB0TWFwIiwiY2hlY2tVbm1vdW50aW5nIiwic3VwcHJlc3NBbmltYXRpb24iLCJpc1R3ZWx2ZUhvdXIiLCJtZW51RGlzcGxheWVkIiwiYnV0dG9uIiwib3Blbk1lbnUiLCJjbG9zZU1lbnUiLCJ1c2VDb250ZXh0TWVudSIsImhhc01vcmUiLCJsZW5ndGgiLCJ0b29sdGlwTWVtYmVycyIsIm1hcCIsIml0Iiwicm9vbU1lbWJlciIsIm5hbWUiLCJ1c2VySWQiLCJ0b29sdGlwVGV4dCIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJhdmF0YXJzIiwicmVjZWlwdCIsInJlYWRSZWNlaXB0UG9zaXRpb24iLCJrZXkiLCJtZW1iZXIiLCJmYWxsYmFja1VzZXJJZCIsIm9mZnNldCIsInRpbWVzdGFtcCIsInRzIiwic2hvd1R3ZWx2ZUhvdXIiLCJyZXZlcnNlIiwicmVtVGV4dCIsInJlbWFpbmRlciIsImNvbnRleHRNZW51IiwiY3VycmVudCIsImJ1dHRvblJlY3QiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJfZXh0ZW5kczIiLCJtZW51Q2xhc3NOYW1lIiwib25GaW5pc2hlZCIsImFib3ZlTGVmdE9mIiwiU2VjdGlvbkhlYWRlciIsIl90IiwiY291bnQiLCJSZWFkUmVjZWlwdFBlcnNvbiIsIm9uQWZ0ZXJDbGljayIsIlRvb2x0aXAiLCJsYWJlbCIsImNhcHRpb24iLCJwbGFjZW1lbnQiLCJyb2xlIiwicmVmIiwib25DbGljayIsInN0eWxlIiwid2lkdGgiLCJNYXRoIiwibWluIiwiZGVzY3JpcHRpb24iLCJyYXdEaXNwbGF5TmFtZSIsIk1lbnVJdGVtIiwiZGlzIiwiZGlzcGF0Y2giLCJhY3Rpb24iLCJBY3Rpb24iLCJWaWV3VXNlciIsInB1c2giLCJzaXplIiwicmVzaXplTWV0aG9kIiwiaGlkZVRpdGxlIiwiZm9ybWF0RGF0ZSIsIkRhdGUiLCJjaGlsZHJlbiIsIm9uRm9jdXMiLCJ1c2VSb3ZpbmdUYWJJbmRleCIsInRhYkluZGV4Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdmlld3Mvcm9vbXMvUmVhZFJlY2VpcHRHcm91cC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7IFByb3BzV2l0aENoaWxkcmVuIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBVc2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgVG9vbHRpcCB9IGZyb20gXCJAdmVjdG9yLWltL2NvbXBvdW5kLXdlYlwiO1xuXG5pbXBvcnQgUmVhZFJlY2VpcHRNYXJrZXIsIHsgSVJlYWRSZWNlaXB0UG9zaXRpb24gfSBmcm9tIFwiLi9SZWFkUmVjZWlwdE1hcmtlclwiO1xuaW1wb3J0IHsgSVJlYWRSZWNlaXB0UHJvcHMgfSBmcm9tIFwiLi9FdmVudFRpbGVcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgTWVtYmVyQXZhdGFyIGZyb20gXCIuLi9hdmF0YXJzL01lbWJlckF2YXRhclwiO1xuaW1wb3J0IEF1dG9IaWRlU2Nyb2xsYmFyIGZyb20gXCIuLi8uLi9zdHJ1Y3R1cmVzL0F1dG9IaWRlU2Nyb2xsYmFyXCI7XG5pbXBvcnQgeyBmb3JtYXREYXRlIH0gZnJvbSBcIi4uLy4uLy4uL0RhdGVVdGlsc1wiO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSBcIi4uLy4uLy4uL2Rpc3BhdGNoZXIvYWN0aW9uc1wiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgQ29udGV4dE1lbnUsIHsgYWJvdmVMZWZ0T2YsIE1lbnVJdGVtLCB1c2VDb250ZXh0TWVudSB9IGZyb20gXCIuLi8uLi9zdHJ1Y3R1cmVzL0NvbnRleHRNZW51XCI7XG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCB7IHVzZVJvdmluZ1RhYkluZGV4IH0gZnJvbSBcIi4uLy4uLy4uL2FjY2Vzc2liaWxpdHkvUm92aW5nVGFiSW5kZXhcIjtcbmltcG9ydCB7IGZvcm1hdExpc3QgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvRm9ybWF0dGluZ1V0aWxzXCI7XG5cbi8vICMyMDU0NyBEZXNpZ24gc3BlY2lmaWVkIHRoYXQgd2Ugc2hvdWxkIHNob3cgdGhlIHRocmVlIGxhdGVzdCByZWFkIHJlY2VpcHRzXG5jb25zdCBNQVhfUkVBRF9BVkFUQVJTX1BMVVNfTiA9IDM7XG4vLyAjMjE5MzUgSWYgd2XigJl2ZSBnb3QganVzdCA0LCBkb27igJl0IHNob3cgKzEsIGp1c3Qgc2hvdyBhbGwgb2YgdGhlbVxuY29uc3QgTUFYX1JFQURfQVZBVEFSUyA9IE1BWF9SRUFEX0FWQVRBUlNfUExVU19OICsgMTtcblxuY29uc3QgUkVBRF9BVkFUQVJfT0ZGU0VUID0gMTA7XG5leHBvcnQgY29uc3QgUkVBRF9BVkFUQVJfU0laRSA9IDE2O1xuXG5pbnRlcmZhY2UgUHJvcHMge1xuICAgIHJlYWRSZWNlaXB0czogSVJlYWRSZWNlaXB0UHJvcHNbXTtcbiAgICByZWFkUmVjZWlwdE1hcDogeyBbdXNlcklkOiBzdHJpbmddOiBJUmVhZFJlY2VpcHRQb3NpdGlvbiB9O1xuICAgIGNoZWNrVW5tb3VudGluZz86ICgpID0+IGJvb2xlYW47XG4gICAgc3VwcHJlc3NBbmltYXRpb246IGJvb2xlYW47XG4gICAgaXNUd2VsdmVIb3VyPzogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIElBdmF0YXJQb3NpdGlvbiB7XG4gICAgaGlkZGVuOiBib29sZWFuO1xuICAgIHBvc2l0aW9uOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXRlcm1pbmVBdmF0YXJQb3NpdGlvbihpbmRleDogbnVtYmVyLCBtYXg6IG51bWJlcik6IElBdmF0YXJQb3NpdGlvbiB7XG4gICAgaWYgKGluZGV4IDwgbWF4KSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoaWRkZW46IGZhbHNlLFxuICAgICAgICAgICAgcG9zaXRpb246IGluZGV4LFxuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoaWRkZW46IHRydWUsXG4gICAgICAgICAgICBwb3NpdGlvbjogMCxcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkUmVjZWlwdFRvb2x0aXAobWVtYmVyczogc3RyaW5nW10sIG1heEF2YXRhcnM6IG51bWJlcik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGZvcm1hdExpc3QobWVtYmVycywgbWF4QXZhdGFycyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBSZWFkUmVjZWlwdEdyb3VwKHtcbiAgICByZWFkUmVjZWlwdHMsXG4gICAgcmVhZFJlY2VpcHRNYXAsXG4gICAgY2hlY2tVbm1vdW50aW5nLFxuICAgIHN1cHByZXNzQW5pbWF0aW9uLFxuICAgIGlzVHdlbHZlSG91cixcbn06IFByb3BzKTogSlNYLkVsZW1lbnQge1xuICAgIGNvbnN0IFttZW51RGlzcGxheWVkLCBidXR0b24sIG9wZW5NZW51LCBjbG9zZU1lbnVdID0gdXNlQ29udGV4dE1lbnUoKTtcblxuICAgIC8vIElmIHdlIGFyZSBhYm92ZSBNQVhfUkVBRF9BVkFUQVJTLCB3ZeKAmWxsIGhhdmUgdG8gcmVtb3ZlIGEgZmV3IHRvIGhhdmUgc3BhY2UgZm9yIHRoZSArbiBjb3VudC5cbiAgICBjb25zdCBoYXNNb3JlID0gcmVhZFJlY2VpcHRzLmxlbmd0aCA+IE1BWF9SRUFEX0FWQVRBUlM7XG4gICAgY29uc3QgbWF4QXZhdGFycyA9IGhhc01vcmUgPyBNQVhfUkVBRF9BVkFUQVJTX1BMVVNfTiA6IE1BWF9SRUFEX0FWQVRBUlM7XG5cbiAgICBjb25zdCB0b29sdGlwTWVtYmVyczogc3RyaW5nW10gPSByZWFkUmVjZWlwdHMubWFwKChpdCkgPT4gaXQucm9vbU1lbWJlcj8ubmFtZSA/PyBpdC51c2VySWQpO1xuICAgIGNvbnN0IHRvb2x0aXBUZXh0ID0gcmVhZFJlY2VpcHRUb29sdGlwKHRvb2x0aXBNZW1iZXJzLCBtYXhBdmF0YXJzKTtcblxuICAgIC8vIHJldHVybiBlYXJseSBpZiB0aGVyZSBhcmUgbm8gcmVhZCByZWNlaXB0c1xuICAgIGlmIChyZWFkUmVjZWlwdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIC8vIFdlIGN1cnJlbnRseSBtdXN0IGluY2x1ZGUgYG14X1JlYWRSZWNlaXB0R3JvdXBfY29udGFpbmVyYCBpblxuICAgICAgICAvLyB0aGUgRE9NIG9mIGFsbCBldmVudHMsIGFzIGl0IGlzIHRoZSBwb3NpdGlvbmVkIHBhcmVudCBvZiB0aGVcbiAgICAgICAgLy8gYW5pbWF0ZWQgcmVhZCByZWNlaXB0cy4gV2UgY2FuJ3QgbGV0IGl0IHVubW91bnQgd2hlbiBhIHJlY2VpcHRcbiAgICAgICAgLy8gbW92ZXMgZXZlbnRzLCBzbyBmb3Igbm93IHdlIG1vdW50IGl0IGZvciBhbGwgZXZlbnRzLiBXaXRob3V0XG4gICAgICAgIC8vIGl0LCB0aGUgYW5pbWF0aW9uIHdpbGwgc3RhcnQgZnJvbSB0aGUgdG9wIG9mIHRoZSB0aW1lbGluZVxuICAgICAgICAvLyAoYmVjYXVzZSBpdCBsb3N0IGl0cyBjb250YWluZXIpLlxuICAgICAgICAvLyBTZWUgYWxzbyBodHRwczovL2dpdGh1Yi5jb20vdmVjdG9yLWltL2VsZW1lbnQtd2ViL2lzc3Vlcy8xNzU2MVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9FdmVudFRpbGVfbXNnT3B0aW9uXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9SZWFkUmVjZWlwdEdyb3VwXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfUmVhZFJlY2VpcHRHcm91cF9idXR0b25cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzTmFtZT1cIm14X1JlYWRSZWNlaXB0R3JvdXBfY29udGFpbmVyXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBhdmF0YXJzID0gcmVhZFJlY2VpcHRzXG4gICAgICAgIC5tYXAoKHJlY2VpcHQsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IGhpZGRlbiwgcG9zaXRpb24gfSA9IGRldGVybWluZUF2YXRhclBvc2l0aW9uKGluZGV4LCBtYXhBdmF0YXJzKTtcblxuICAgICAgICAgICAgY29uc3QgdXNlcklkID0gcmVjZWlwdC51c2VySWQ7XG4gICAgICAgICAgICBsZXQgcmVhZFJlY2VpcHRQb3NpdGlvbjogSVJlYWRSZWNlaXB0UG9zaXRpb24gfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgIGlmIChyZWFkUmVjZWlwdE1hcCkge1xuICAgICAgICAgICAgICAgIHJlYWRSZWNlaXB0UG9zaXRpb24gPSByZWFkUmVjZWlwdE1hcFt1c2VySWRdO1xuICAgICAgICAgICAgICAgIGlmICghcmVhZFJlY2VpcHRQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICByZWFkUmVjZWlwdFBvc2l0aW9uID0ge307XG4gICAgICAgICAgICAgICAgICAgIHJlYWRSZWNlaXB0TWFwW3VzZXJJZF0gPSByZWFkUmVjZWlwdFBvc2l0aW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8UmVhZFJlY2VpcHRNYXJrZXJcbiAgICAgICAgICAgICAgICAgICAga2V5PXt1c2VySWR9XG4gICAgICAgICAgICAgICAgICAgIG1lbWJlcj17cmVjZWlwdC5yb29tTWVtYmVyfVxuICAgICAgICAgICAgICAgICAgICBmYWxsYmFja1VzZXJJZD17dXNlcklkfVxuICAgICAgICAgICAgICAgICAgICBvZmZzZXQ9e3Bvc2l0aW9uICogUkVBRF9BVkFUQVJfT0ZGU0VUfVxuICAgICAgICAgICAgICAgICAgICBoaWRkZW49e2hpZGRlbn1cbiAgICAgICAgICAgICAgICAgICAgcmVhZFJlY2VpcHRQb3NpdGlvbj17cmVhZFJlY2VpcHRQb3NpdGlvbn1cbiAgICAgICAgICAgICAgICAgICAgY2hlY2tVbm1vdW50aW5nPXtjaGVja1VubW91bnRpbmd9XG4gICAgICAgICAgICAgICAgICAgIHN1cHByZXNzQW5pbWF0aW9uPXtzdXBwcmVzc0FuaW1hdGlvbn1cbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wPXtyZWNlaXB0LnRzfVxuICAgICAgICAgICAgICAgICAgICBzaG93VHdlbHZlSG91cj17aXNUd2VsdmVIb3VyfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICApO1xuICAgICAgICB9KVxuICAgICAgICAucmV2ZXJzZSgpO1xuXG4gICAgbGV0IHJlbVRleHQ6IEpTWC5FbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IHJlbWFpbmRlciA9IHJlYWRSZWNlaXB0cy5sZW5ndGggLSBtYXhBdmF0YXJzO1xuICAgIGlmIChyZW1haW5kZXIgPiAwKSB7XG4gICAgICAgIHJlbVRleHQgPSAoXG4gICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9SZWFkUmVjZWlwdEdyb3VwX3JlbWFpbmRlclwiIGFyaWEtbGl2ZT1cIm9mZlwiPlxuICAgICAgICAgICAgICAgICt7cmVtYWluZGVyfVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICApO1xuICAgIH1cblxuICAgIGxldCBjb250ZXh0TWVudTogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgaWYgKG1lbnVEaXNwbGF5ZWQgJiYgYnV0dG9uLmN1cnJlbnQpIHtcbiAgICAgICAgY29uc3QgYnV0dG9uUmVjdCA9IGJ1dHRvbi5jdXJyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb250ZXh0TWVudSA9IChcbiAgICAgICAgICAgIDxDb250ZXh0TWVudSBtZW51Q2xhc3NOYW1lPVwibXhfUmVhZFJlY2VpcHRHcm91cF9wb3B1cFwiIG9uRmluaXNoZWQ9e2Nsb3NlTWVudX0gey4uLmFib3ZlTGVmdE9mKGJ1dHRvblJlY3QpfT5cbiAgICAgICAgICAgICAgICA8QXV0b0hpZGVTY3JvbGxiYXI+XG4gICAgICAgICAgICAgICAgICAgIDxTZWN0aW9uSGVhZGVyIGNsYXNzTmFtZT1cIm14X1JlYWRSZWNlaXB0R3JvdXBfdGl0bGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcInRpbWVsaW5lfHJlYWRfcmVjZWlwdF90aXRsZVwiLCB7IGNvdW50OiByZWFkUmVjZWlwdHMubGVuZ3RoIH0pfVxuICAgICAgICAgICAgICAgICAgICA8L1NlY3Rpb25IZWFkZXI+XG4gICAgICAgICAgICAgICAgICAgIHtyZWFkUmVjZWlwdHMubWFwKChyZWNlaXB0KSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICA8UmVhZFJlY2VpcHRQZXJzb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXk9e3JlY2VpcHQudXNlcklkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsuLi5yZWNlaXB0fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzVHdlbHZlSG91cj17aXNUd2VsdmVIb3VyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQWZ0ZXJDbGljaz17Y2xvc2VNZW51fVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgKSl9XG4gICAgICAgICAgICAgICAgPC9BdXRvSGlkZVNjcm9sbGJhcj5cbiAgICAgICAgICAgIDwvQ29udGV4dE1lbnU+XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIChcbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9FdmVudFRpbGVfbXNnT3B0aW9uXCI+XG4gICAgICAgICAgICA8VG9vbHRpcFxuICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcInRpbWVsaW5lfHJlYWRfcmVjZWlwdF90aXRsZVwiLCB7IGNvdW50OiByZWFkUmVjZWlwdHMubGVuZ3RoIH0pfVxuICAgICAgICAgICAgICAgIGNhcHRpb249e3Rvb2x0aXBUZXh0fVxuICAgICAgICAgICAgICAgIHBsYWNlbWVudD1cInRvcC1lbmRcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfUmVhZFJlY2VpcHRHcm91cFwiIHJvbGU9XCJncm91cFwiIGFyaWEtbGFiZWw9e190KFwidGltZWxpbmV8cmVhZF9yZWNlaXB0c19sYWJlbFwiKX0+XG4gICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9SZWFkUmVjZWlwdEdyb3VwX2J1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICByZWY9e2J1dHRvbn1cbiAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtbGFiZWw9e3Rvb2x0aXBUZXh0fVxuICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1oYXNwb3B1cD1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17b3Blbk1lbnV9XG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtyZW1UZXh0fVxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9SZWFkUmVjZWlwdEdyb3VwX2NvbnRhaW5lclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGU9e3tcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRoLm1pbihtYXhBdmF0YXJzLCByZWFkUmVjZWlwdHMubGVuZ3RoKSAqIFJFQURfQVZBVEFSX09GRlNFVCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRUFEX0FWQVRBUl9TSVpFIC1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJFQURfQVZBVEFSX09GRlNFVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHthdmF0YXJzfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgIHtjb250ZXh0TWVudX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvVG9vbHRpcD5cbiAgICAgICAgPC9kaXY+XG4gICAgKTtcbn1cblxuaW50ZXJmYWNlIFJlYWRSZWNlaXB0UGVyc29uUHJvcHMgZXh0ZW5kcyBJUmVhZFJlY2VpcHRQcm9wcyB7XG4gICAgaXNUd2VsdmVIb3VyPzogYm9vbGVhbjtcbiAgICBvbkFmdGVyQ2xpY2s/OiAoKSA9PiB2b2lkO1xufVxuXG4vLyBFeHBvcnQgZm9yIHRlc3RpbmdcbmV4cG9ydCBmdW5jdGlvbiBSZWFkUmVjZWlwdFBlcnNvbih7XG4gICAgdXNlcklkLFxuICAgIHJvb21NZW1iZXIsXG4gICAgdHMsXG4gICAgaXNUd2VsdmVIb3VyLFxuICAgIG9uQWZ0ZXJDbGljayxcbn06IFJlYWRSZWNlaXB0UGVyc29uUHJvcHMpOiBKU1guRWxlbWVudCB7XG4gICAgcmV0dXJuIChcbiAgICAgICAgPFRvb2x0aXAgZGVzY3JpcHRpb249e3Jvb21NZW1iZXI/LnJhd0Rpc3BsYXlOYW1lID8/IHVzZXJJZH0gY2FwdGlvbj17dXNlcklkfSBwbGFjZW1lbnQ9XCJ0b3BcIj5cbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgPE1lbnVJdGVtXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X1JlYWRSZWNlaXB0R3JvdXBfcGVyc29uXCJcbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17KCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb246IEFjdGlvbi5WaWV3VXNlcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBYWFg6IFdlIHNob3VsZCBiZSB1c2luZyBhIHJlYWwgbWVtYmVyIG9iamVjdCBhbmQgbm90IGFzc3VtaW5nIHdoYXQgdGhlIHJlY2VpdmVyIHdhbnRzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBWaWV3VXNlciBhY3Rpb24gbGVhZHMgdG8gdGhlIFJpZ2h0UGFuZWxTdG9yZSwgYW5kIFJpZ2h0UGFuZWxTdG9yZUlQYW5lbFN0YXRlIGRlZmluZXMgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVtYmVyIHByb3BlcnR5IG9mIElSaWdodFBhbmVsQ2FyZFN0YXRlIGFzIGBSb29tTWVtYmVyIHwgVXNlcmAsIHNvIHdl4oCZcmUgZmluZSBmb3Igbm93LCBidXQgd2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzaG91bGQgZGVmaW5pdGVseSBjbGVhbiB0aGlzIHVwIGxhdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVtYmVyOiByb29tTWVtYmVyID8/ICh7IHVzZXJJZCB9IGFzIFVzZXIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1c2g6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkFmdGVyQ2xpY2s/LigpO1xuICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPE1lbWJlckF2YXRhclxuICAgICAgICAgICAgICAgICAgICAgICAgbWVtYmVyPXtyb29tTWVtYmVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgZmFsbGJhY2tVc2VySWQ9e3VzZXJJZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9XCIyNHB4XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWxpdmU9XCJvZmZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzaXplTWV0aG9kPVwiY3JvcFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBoaWRlVGl0bGVcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9SZWFkUmVjZWlwdEdyb3VwX25hbWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxwPntyb29tTWVtYmVyPy5uYW1lID8/IHVzZXJJZH08L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICA8cCBjbGFzc05hbWU9XCJteF9SZWFkUmVjZWlwdEdyb3VwX3NlY29uZGFyeVwiPntmb3JtYXREYXRlKG5ldyBEYXRlKHRzKSwgaXNUd2VsdmVIb3VyKX08L3A+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvTWVudUl0ZW0+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9Ub29sdGlwPlxuICAgICk7XG59XG5cbmludGVyZmFjZSBJU2VjdGlvbkhlYWRlclByb3BzIHtcbiAgICBjbGFzc05hbWU/OiBzdHJpbmc7XG59XG5cbmZ1bmN0aW9uIFNlY3Rpb25IZWFkZXIoeyBjbGFzc05hbWUsIGNoaWxkcmVuIH06IFByb3BzV2l0aENoaWxkcmVuPElTZWN0aW9uSGVhZGVyUHJvcHM+KTogSlNYLkVsZW1lbnQge1xuICAgIGNvbnN0IFtvbkZvY3VzLCAsIHJlZl0gPSB1c2VSb3ZpbmdUYWJJbmRleDxIVE1MSGVhZGluZ0VsZW1lbnQ+KCk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8aDMgY2xhc3NOYW1lPXtjbGFzc05hbWV9IHJvbGU9XCJtZW51aXRlbVwiIG9uRm9jdXM9e29uRm9jdXN9IHRhYkluZGV4PXstMX0gcmVmPXtyZWZ9PlxuICAgICAgICAgICAge2NoaWxkcmVufVxuICAgICAgICA8L2gzPlxuICAgICk7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQVFBLElBQUFBLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFDLFlBQUEsR0FBQUQsT0FBQTtBQUVBLElBQUFFLGtCQUFBLEdBQUFILHNCQUFBLENBQUFDLE9BQUE7QUFFQSxJQUFBRyxpQkFBQSxHQUFBSixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUksYUFBQSxHQUFBTCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUssa0JBQUEsR0FBQU4sc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFNLFVBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLFFBQUEsR0FBQVAsT0FBQTtBQUNBLElBQUFRLFdBQUEsR0FBQVQsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFTLFlBQUEsR0FBQUMsdUJBQUEsQ0FBQVYsT0FBQTtBQUNBLElBQUFXLGdCQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxlQUFBLEdBQUFaLE9BQUE7QUFDQSxJQUFBYSxnQkFBQSxHQUFBYixPQUFBO0FBQTRELFNBQUFjLHlCQUFBQyxDQUFBLDZCQUFBQyxPQUFBLG1CQUFBQyxDQUFBLE9BQUFELE9BQUEsSUFBQUUsQ0FBQSxPQUFBRixPQUFBLFlBQUFGLHdCQUFBLFlBQUFBLENBQUFDLENBQUEsV0FBQUEsQ0FBQSxHQUFBRyxDQUFBLEdBQUFELENBQUEsS0FBQUYsQ0FBQTtBQUFBLFNBQUFMLHdCQUFBSyxDQUFBLEVBQUFFLENBQUEsU0FBQUEsQ0FBQSxJQUFBRixDQUFBLElBQUFBLENB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