UNPKG

matrix-react-sdk

Version:
339 lines (333 loc) 59.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.EMOJI_HEIGHT = exports.EMOJIS_PER_ROW = exports.CATEGORY_HEADER_HEIGHT = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _emojibaseBindings = require("@matrix-org/emojibase-bindings"); var _languageHandler = require("../../../languageHandler"); var recent = _interopRequireWildcard(require("../../../emojipicker/recent")); var _AutoHideScrollbar = _interopRequireDefault(require("../../structures/AutoHideScrollbar")); var _Header = _interopRequireDefault(require("./Header")); var _Search = _interopRequireDefault(require("./Search")); var _Preview = _interopRequireDefault(require("./Preview")); var _QuickReactions = _interopRequireDefault(require("./QuickReactions")); var _Category = _interopRequireDefault(require("./Category")); var _arrays = require("../../../utils/arrays"); var _RovingTabIndex = require("../../../accessibility/RovingTabIndex"); var _Keyboard = require("../../../Keyboard"); var _numbers = require("../../../utils/numbers"); 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; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /* Copyright 2024 New Vector Ltd. Copyright 2020 The Matrix.org Foundation C.I.C. Copyright 2019 Tulir Asokan <tulir@maunium.net> SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ const CATEGORY_HEADER_HEIGHT = exports.CATEGORY_HEADER_HEIGHT = 20; const EMOJI_HEIGHT = exports.EMOJI_HEIGHT = 35; const EMOJIS_PER_ROW = exports.EMOJIS_PER_ROW = 8; const ZERO_WIDTH_JOINER = "\u200D"; class EmojiPicker extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "recentlyUsed", void 0); (0, _defineProperty2.default)(this, "memoizedDataByCategory", void 0); (0, _defineProperty2.default)(this, "categories", void 0); (0, _defineProperty2.default)(this, "scrollRef", /*#__PURE__*/_react.default.createRef()); (0, _defineProperty2.default)(this, "onScroll", () => { const body = this.scrollRef.current?.containerRef.current; if (!body) return; this.setState({ scrollTop: body.scrollTop, viewportHeight: body.clientHeight }); this.updateVisibility(); }); (0, _defineProperty2.default)(this, "onKeyDown", (ev, state, dispatch) => { if (state.activeRef?.current && [_Keyboard.Key.ARROW_DOWN, _Keyboard.Key.ARROW_RIGHT, _Keyboard.Key.ARROW_LEFT, _Keyboard.Key.ARROW_UP].includes(ev.key)) { this.keyboardNavigation(ev, state, dispatch); } }); (0, _defineProperty2.default)(this, "updateVisibility", () => { const body = this.scrollRef.current?.containerRef.current; if (!body) return; const rect = body.getBoundingClientRect(); for (const cat of this.categories) { const elem = body.querySelector(`[data-category-id="${cat.id}"]`); if (!elem) { cat.visible = false; cat.ref.current?.classList.remove("mx_EmojiPicker_anchor_visible"); continue; } const elemRect = elem.getBoundingClientRect(); const y = elemRect.y - rect.y; const yEnd = elemRect.y + elemRect.height - rect.y; cat.visible = y < rect.height && yEnd > 0; // We update this here instead of through React to avoid re-render on scroll. if (!cat.ref.current) continue; if (cat.visible) { cat.ref.current.classList.add("mx_EmojiPicker_anchor_visible"); cat.ref.current.setAttribute("aria-selected", "true"); cat.ref.current.setAttribute("tabindex", "0"); } else { cat.ref.current.classList.remove("mx_EmojiPicker_anchor_visible"); cat.ref.current.setAttribute("aria-selected", "false"); cat.ref.current.setAttribute("tabindex", "-1"); } } }); (0, _defineProperty2.default)(this, "scrollToCategory", category => { this.scrollRef.current?.containerRef.current?.querySelector(`[data-category-id="${category}"]`)?.scrollIntoView(); }); (0, _defineProperty2.default)(this, "onChangeFilter", filter => { const lcFilter = filter.toLowerCase().trim(); // filter is case insensitive for (const cat of this.categories) { let emojis; // If the new filter string includes the old filter string, we don't have to re-filter the whole dataset. if (lcFilter.includes(this.state.filter)) { emojis = this.memoizedDataByCategory[cat.id]; } else { emojis = cat.id === "recent" ? this.recentlyUsed : _emojibaseBindings.DATA_BY_CATEGORY[cat.id]; } if (lcFilter !== "") { emojis = emojis.filter(emoji => this.emojiMatchesFilter(emoji, lcFilter)); // Copy the array to not clobber the original unfiltered sorting emojis = [...emojis].sort((a, b) => { const indexA = a.shortcodes[0].indexOf(lcFilter); const indexB = b.shortcodes[0].indexOf(lcFilter); // Prioritize emojis containing the filter in its shortcode if (indexA == -1 || indexB == -1) { return indexB - indexA; } // If both emojis start with the filter // put the shorter emoji first if (indexA == 0 && indexB == 0) { return a.shortcodes[0].length - b.shortcodes[0].length; } // Prioritize emojis starting with the filter return indexA - indexB; }); } this.memoizedDataByCategory[cat.id] = emojis; cat.enabled = emojis.length > 0; // The setState below doesn't re-render the header and we already have the refs for updateVisibility, so... if (cat.ref.current) { cat.ref.current.disabled = !cat.enabled; } } this.setState({ filter }); // Header underlines need to be updated, but updating requires knowing // where the categories are, so we wait for a tick. window.setTimeout(this.updateVisibility, 0); }); (0, _defineProperty2.default)(this, "emojiMatchesFilter", (emoji, filter) => { // If the query is an emoji containing a variation then strip it to provide more useful matches if (filter.includes(ZERO_WIDTH_JOINER)) { filter = filter.split(ZERO_WIDTH_JOINER, 2)[0]; } return emoji.label.toLowerCase().includes(filter) || (Array.isArray(emoji.emoticon) ? emoji.emoticon.some(x => x.includes(filter)) : emoji.emoticon?.includes(filter)) || emoji.shortcodes.some(x => x.toLowerCase().includes(filter)) || emoji.unicode.split(ZERO_WIDTH_JOINER).includes(filter); }); (0, _defineProperty2.default)(this, "onEnterFilter", () => { const btn = this.scrollRef.current?.containerRef.current?.querySelector('.mx_EmojiPicker_item_wrapper[tabindex="0"]'); btn?.click(); this.props.onFinished(); }); (0, _defineProperty2.default)(this, "onHoverEmoji", emoji => { this.setState({ previewEmoji: emoji }); }); (0, _defineProperty2.default)(this, "onHoverEmojiEnd", () => { this.setState({ previewEmoji: undefined }); }); (0, _defineProperty2.default)(this, "onClickEmoji", (ev, emoji) => { if (this.props.onChoose(emoji.unicode) !== false) { recent.add(emoji.unicode); } if (ev.key === _Keyboard.Key.ENTER) { this.props.onFinished(); } }); this.state = { filter: "", scrollTop: 0, viewportHeight: 280 }; // Convert recent emoji characters to emoji data, removing unknowns and duplicates this.recentlyUsed = Array.from(new Set((0, _arrays.filterBoolean)(recent.get().map(_emojibaseBindings.getEmojiFromUnicode)))); this.memoizedDataByCategory = _objectSpread({ recent: this.recentlyUsed }, _emojibaseBindings.DATA_BY_CATEGORY); this.categories = [{ id: "recent", name: (0, _languageHandler._t)("emoji|category_frequently_used"), enabled: this.recentlyUsed.length > 0, visible: this.recentlyUsed.length > 0, ref: /*#__PURE__*/_react.default.createRef() }, { id: "people", name: (0, _languageHandler._t)("emoji|category_smileys_people"), enabled: true, visible: true, ref: /*#__PURE__*/_react.default.createRef() }, { id: "nature", name: (0, _languageHandler._t)("emoji|category_animals_nature"), enabled: true, visible: false, ref: /*#__PURE__*/_react.default.createRef() }, { id: "foods", name: (0, _languageHandler._t)("emoji|category_food_drink"), enabled: true, visible: false, ref: /*#__PURE__*/_react.default.createRef() }, { id: "activity", name: (0, _languageHandler._t)("emoji|category_activities"), enabled: true, visible: false, ref: /*#__PURE__*/_react.default.createRef() }, { id: "places", name: (0, _languageHandler._t)("emoji|category_travel_places"), enabled: true, visible: false, ref: /*#__PURE__*/_react.default.createRef() }, { id: "objects", name: (0, _languageHandler._t)("emoji|category_objects"), enabled: true, visible: false, ref: /*#__PURE__*/_react.default.createRef() }, { id: "symbols", name: (0, _languageHandler._t)("emoji|category_symbols"), enabled: true, visible: false, ref: /*#__PURE__*/_react.default.createRef() }, { id: "flags", name: (0, _languageHandler._t)("emoji|category_flags"), enabled: true, visible: false, ref: /*#__PURE__*/_react.default.createRef() }]; } keyboardNavigation(ev, state, dispatch) { const node = state.activeRef?.current; const parent = node?.parentElement; if (!parent || !state.activeRef) return; const rowIndex = Array.from(parent.children).indexOf(node); const refIndex = state.refs.indexOf(state.activeRef); let focusRef; let newParent; switch (ev.key) { case _Keyboard.Key.ARROW_LEFT: focusRef = state.refs[refIndex - 1]; newParent = focusRef?.current?.parentElement ?? undefined; break; case _Keyboard.Key.ARROW_RIGHT: focusRef = state.refs[refIndex + 1]; newParent = focusRef?.current?.parentElement ?? undefined; break; case _Keyboard.Key.ARROW_UP: case _Keyboard.Key.ARROW_DOWN: { // For up/down we find the prev/next parent by inspecting the refs either side of our row const ref = ev.key === _Keyboard.Key.ARROW_UP ? state.refs[refIndex - rowIndex - 1] : state.refs[refIndex - rowIndex + EMOJIS_PER_ROW]; newParent = ref?.current?.parentElement ?? undefined; const newTarget = newParent?.children[(0, _numbers.clamp)(rowIndex, 0, newParent.children.length - 1)]; focusRef = state.refs.find(r => r.current === newTarget); break; } } if (focusRef) { dispatch({ type: _RovingTabIndex.Type.SetFocus, payload: { ref: focusRef } }); if (parent !== newParent) { focusRef.current?.scrollIntoView({ behavior: "auto", block: "center", inline: "center" }); } } ev.preventDefault(); ev.stopPropagation(); } static categoryHeightForEmojiCount(count) { if (count === 0) { return 0; } return CATEGORY_HEADER_HEIGHT + Math.ceil(count / EMOJIS_PER_ROW) * EMOJI_HEIGHT; } render() { return /*#__PURE__*/_react.default.createElement(_RovingTabIndex.RovingTabIndexProvider, { onKeyDown: this.onKeyDown }, ({ onKeyDownHandler }) => { let heightBefore = 0; return /*#__PURE__*/_react.default.createElement("section", { className: "mx_EmojiPicker", "data-testid": "mx_EmojiPicker", onKeyDown: onKeyDownHandler, "aria-label": (0, _languageHandler._t)("a11y|emoji_picker") }, /*#__PURE__*/_react.default.createElement(_Header.default, { categories: this.categories, onAnchorClick: this.scrollToCategory }), /*#__PURE__*/_react.default.createElement(_Search.default, { query: this.state.filter, onChange: this.onChangeFilter, onEnter: this.onEnterFilter, onKeyDown: onKeyDownHandler }), /*#__PURE__*/_react.default.createElement(_AutoHideScrollbar.default, { id: "mx_EmojiPicker_body", className: "mx_EmojiPicker_body", ref: this.scrollRef, onScroll: this.onScroll }, this.categories.map(category => { const emojis = this.memoizedDataByCategory[category.id]; const categoryElement = /*#__PURE__*/_react.default.createElement(_Category.default, { key: category.id, id: category.id, name: category.name, heightBefore: heightBefore, viewportHeight: this.state.viewportHeight, scrollTop: this.state.scrollTop, emojis: emojis, onClick: this.onClickEmoji, onMouseEnter: this.onHoverEmoji, onMouseLeave: this.onHoverEmojiEnd, isEmojiDisabled: this.props.isEmojiDisabled, selectedEmojis: this.props.selectedEmojis }); const height = EmojiPicker.categoryHeightForEmojiCount(emojis.length); heightBefore += height; return categoryElement; })), this.state.previewEmoji ? /*#__PURE__*/_react.default.createElement(_Preview.default, { emoji: this.state.previewEmoji }) : /*#__PURE__*/_react.default.createElement(_QuickReactions.default, { onClick: this.onClickEmoji, selectedEmojis: this.props.selectedEmojis })); }); } } var _default = exports.default = EmojiPicker; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9lbW9qaWJhc2VCaW5kaW5ncyIsIl9sYW5ndWFnZUhhbmRsZXIiLCJyZWNlbnQiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsIl9BdXRvSGlkZVNjcm9sbGJhciIsIl9IZWFkZXIiLCJfU2VhcmNoIiwiX1ByZXZpZXciLCJfUXVpY2tSZWFjdGlvbnMiLCJfQ2F0ZWdvcnkiLCJfYXJyYXlzIiwiX1JvdmluZ1RhYkluZGV4IiwiX0tleWJvYXJkIiwiX251bWJlcnMiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJDQVRFR09SWV9IRUFERVJfSEVJR0hUIiwiZXhwb3J0cyIsIkVNT0pJX0hFSUdIVCIsIkVNT0pJU19QRVJfUk9XIiwiWkVST19XSURUSF9KT0lORVIiLCJFbW9qaVBpY2tlciIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsImNyZWF0ZVJlZiIsImJvZHkiLCJzY3JvbGxSZWYiLCJjdXJyZW50IiwiY29udGFpbmVyUmVmIiwic2V0U3RhdGUiLCJzY3JvbGxUb3AiLCJ2aWV3cG9ydEhlaWdodCIsImNsaWVudEhlaWdodCIsInVwZGF0ZVZpc2liaWxpdHkiLCJldiIsInN0YXRlIiwiZGlzcGF0Y2giLCJhY3RpdmVSZWYiLCJLZXkiLCJBUlJPV19ET1dOIiwiQVJST1dfUklHSFQiLCJBUlJPV19MRUZUIiwiQVJST1dfVVAiLCJpbmNsdWRlcyIsImtleSIsImtleWJvYXJkTmF2aWdhdGlvbiIsInJlY3QiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJjYXQiLCJjYXRlZ29yaWVzIiwiZWxlbSIsInF1ZXJ5U2VsZWN0b3IiLCJpZCIsInZpc2libGUiLCJyZWYiLCJjbGFzc0xpc3QiLCJyZW1vdmUiLCJlbGVtUmVjdCIsInkiLCJ5RW5kIiwiaGVpZ2h0IiwiYWRkIiwic2V0QXR0cmlidXRlIiwiY2F0ZWdvcnkiLCJzY3JvbGxJbnRvVmlldyIsImxjRmlsdGVyIiwidG9Mb3dlckNhc2UiLCJ0cmltIiwiZW1vamlzIiwibWVtb2l6ZWREYXRhQnlDYXRlZ29yeSIsInJlY2VudGx5VXNlZCIsIkRBVEFfQllfQ0FURUdPUlkiLCJlbW9qaSIsImVtb2ppTWF0Y2hlc0ZpbHRlciIsInNvcnQiLCJiIiwiaW5kZXhBIiwic2hvcnRjb2RlcyIsImluZGV4T2YiLCJpbmRleEIiLCJlbmFibGVkIiwiZGlzYWJsZWQiLCJ3aW5kb3ciLCJzZXRUaW1lb3V0Iiwic3BsaXQiLCJsYWJlbCIsIkFycmF5IiwiaXNBcnJheSIsImVtb3RpY29uIiwic29tZSIsIngiLCJ1bmljb2RlIiwiYnRuIiwiY2xpY2siLCJvbkZpbmlzaGVkIiwicHJldmlld0Vtb2ppIiwidW5kZWZpbmVkIiwib25DaG9vc2UiLCJFTlRFUiIsImZyb20iLCJTZXQiLCJmaWx0ZXJCb29sZWFuIiwibWFwIiwiZ2V0RW1vamlGcm9tVW5pY29kZSIsIm5hbWUiLCJfdCIsIm5vZGUiLCJwYXJlbnQiLCJwYXJlbnRFbGVtZW50Iiwicm93SW5kZXgiLCJjaGlsZHJlbiIsInJlZkluZGV4IiwicmVmcyIsImZvY3VzUmVmIiwibmV3UGFyZW50IiwibmV3VGFyZ2V0IiwiY2xhbXAiLCJmaW5kIiwidHlwZSIsIlR5cGUiLCJTZXRGb2N1cyIsInBheWxvYWQiLCJiZWhhdmlvciIsImJsb2NrIiwiaW5saW5lIiwicHJldmVudERlZmF1bHQiLCJzdG9wUHJvcGFnYXRpb24iLCJjYXRlZ29yeUhlaWdodEZvckVtb2ppQ291bnQiLCJjb3VudCIsIk1hdGgiLCJjZWlsIiwicmVuZGVyIiwiY3JlYXRlRWxlbWVudCIsIlJvdmluZ1RhYkluZGV4UHJvdmlkZXIiLCJvbktleURvd24iLCJvbktleURvd25IYW5kbGVyIiwiaGVpZ2h0QmVmb3JlIiwiY2xhc3NOYW1lIiwib25BbmNob3JDbGljayIsInNjcm9sbFRvQ2F0ZWdvcnkiLCJxdWVyeSIsIm9uQ2hhbmdlIiwib25DaGFuZ2VGaWx0ZXIiLCJvbkVudGVyIiwib25FbnRlckZpbHRlciIsIm9uU2Nyb2xsIiwiY2F0ZWdvcnlFbGVtZW50Iiwib25DbGljayIsIm9uQ2xpY2tFbW9qaSIsIm9uTW91c2VFbnRlciIsIm9uSG92ZXJFbW9qaSIsIm9uTW91c2VMZWF2ZSIsIm9uSG92ZXJFbW9qaUVuZCIsImlzRW1vamlEaXNhYmxlZCIsInNlbGVjdGVkRW1vamlzIiwiX2RlZmF1bHQiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9lbW9qaXBpY2tlci9FbW9qaVBpY2tlci50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cbkNvcHlyaWdodCAyMDE5IFR1bGlyIEFzb2thbiA8dHVsaXJAbWF1bml1bS5uZXQ+XG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBEaXNwYXRjaCB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgREFUQV9CWV9DQVRFR09SWSwgZ2V0RW1vamlGcm9tVW5pY29kZSwgRW1vamkgYXMgSUVtb2ppIH0gZnJvbSBcIkBtYXRyaXgtb3JnL2Vtb2ppYmFzZS1iaW5kaW5nc1wiO1xuXG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCAqIGFzIHJlY2VudCBmcm9tIFwiLi4vLi4vLi4vZW1vamlwaWNrZXIvcmVjZW50XCI7XG5pbXBvcnQgQXV0b0hpZGVTY3JvbGxiYXIgZnJvbSBcIi4uLy4uL3N0cnVjdHVyZXMvQXV0b0hpZGVTY3JvbGxiYXJcIjtcbmltcG9ydCBIZWFkZXIgZnJvbSBcIi4vSGVhZGVyXCI7XG5pbXBvcnQgU2VhcmNoIGZyb20gXCIuL1NlYXJjaFwiO1xuaW1wb3J0IFByZXZpZXcgZnJvbSBcIi4vUHJldmlld1wiO1xuaW1wb3J0IFF1aWNrUmVhY3Rpb25zIGZyb20gXCIuL1F1aWNrUmVhY3Rpb25zXCI7XG5pbXBvcnQgQ2F0ZWdvcnksIHsgQ2F0ZWdvcnlLZXksIElDYXRlZ29yeSB9IGZyb20gXCIuL0NhdGVnb3J5XCI7XG5pbXBvcnQgeyBmaWx0ZXJCb29sZWFuIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL2FycmF5c1wiO1xuaW1wb3J0IHtcbiAgICBJQWN0aW9uIGFzIFJvdmluZ0FjdGlvbixcbiAgICBJU3RhdGUgYXMgUm92aW5nU3RhdGUsXG4gICAgUm92aW5nVGFiSW5kZXhQcm92aWRlcixcbiAgICBUeXBlLFxufSBmcm9tIFwiLi4vLi4vLi4vYWNjZXNzaWJpbGl0eS9Sb3ZpbmdUYWJJbmRleFwiO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSBcIi4uLy4uLy4uL0tleWJvYXJkXCI7XG5pbXBvcnQgeyBjbGFtcCB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9udW1iZXJzXCI7XG5pbXBvcnQgeyBCdXR0b25FdmVudCB9IGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgeyBSZWYgfSBmcm9tIFwiLi4vLi4vLi4vYWNjZXNzaWJpbGl0eS9yb3ZpbmcvdHlwZXNcIjtcblxuZXhwb3J0IGNvbnN0IENBVEVHT1JZX0hFQURFUl9IRUlHSFQgPSAyMDtcbmV4cG9ydCBjb25zdCBFTU9KSV9IRUlHSFQgPSAzNTtcbmV4cG9ydCBjb25zdCBFTU9KSVNfUEVSX1JPVyA9IDg7XG5cbmNvbnN0IFpFUk9fV0lEVEhfSk9JTkVSID0gXCJcXHUyMDBEXCI7XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIHNlbGVjdGVkRW1vamlzPzogU2V0PHN0cmluZz47XG4gICAgb25DaG9vc2UodW5pY29kZTogc3RyaW5nKTogYm9vbGVhbjtcbiAgICBvbkZpbmlzaGVkKCk6IHZvaWQ7XG4gICAgaXNFbW9qaURpc2FibGVkPzogKHVuaWNvZGU6IHN0cmluZykgPT4gYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgZmlsdGVyOiBzdHJpbmc7XG4gICAgcHJldmlld0Vtb2ppPzogSUVtb2ppO1xuICAgIHNjcm9sbFRvcDogbnVtYmVyO1xuICAgIC8vIGluaXRpYWwgZXN0aW1hdGlvbiBvZiBoZWlnaHQsIGRpYWxvZyBpcyBoYXJkY29kZWQgdG8gNDUwcHggaGVpZ2h0LlxuICAgIC8vIHNob3VsZCBiZSBlbm91Z2ggdG8gbmV2ZXIgaGF2ZSBibGFuayByb3dzIG9mIGVtb2ppcyBhc1xuICAgIC8vIDMgcm93cyBvZiBvdmVyZmxvdyBhcmUgYWxzbyByZW5kZXJlZC4gVGhlIGFjdHVhbCB2YWx1ZSBpcyB1cGRhdGVkIG9uIHNjcm9sbC5cbiAgICB2aWV3cG9ydEhlaWdodDogbnVtYmVyO1xufVxuXG5jbGFzcyBFbW9qaVBpY2tlciBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVjZW50bHlVc2VkOiBJRW1vamlbXTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1lbW9pemVkRGF0YUJ5Q2F0ZWdvcnk6IFJlY29yZDxDYXRlZ29yeUtleSwgSUVtb2ppW10+O1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY2F0ZWdvcmllczogSUNhdGVnb3J5W107XG5cbiAgICBwcml2YXRlIHNjcm9sbFJlZiA9IFJlYWN0LmNyZWF0ZVJlZjxBdXRvSGlkZVNjcm9sbGJhcjxcImRpdlwiPj4oKTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcm9wczogSVByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgZmlsdGVyOiBcIlwiLFxuICAgICAgICAgICAgc2Nyb2xsVG9wOiAwLFxuICAgICAgICAgICAgdmlld3BvcnRIZWlnaHQ6IDI4MCxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBDb252ZXJ0IHJlY2VudCBlbW9qaSBjaGFyYWN0ZXJzIHRvIGVtb2ppIGRhdGEsIHJlbW92aW5nIHVua25vd25zIGFuZCBkdXBsaWNhdGVzXG4gICAgICAgIHRoaXMucmVjZW50bHlVc2VkID0gQXJyYXkuZnJvbShuZXcgU2V0KGZpbHRlckJvb2xlYW4ocmVjZW50LmdldCgpLm1hcChnZXRFbW9qaUZyb21Vbmljb2RlKSkpKTtcbiAgICAgICAgdGhpcy5tZW1vaXplZERhdGFCeUNhdGVnb3J5ID0ge1xuICAgICAgICAgICAgcmVjZW50OiB0aGlzLnJlY2VudGx5VXNlZCxcbiAgICAgICAgICAgIC4uLkRBVEFfQllfQ0FURUdPUlksXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5jYXRlZ29yaWVzID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGlkOiBcInJlY2VudFwiLFxuICAgICAgICAgICAgICAgIG5hbWU6IF90KFwiZW1vaml8Y2F0ZWdvcnlfZnJlcXVlbnRseV91c2VkXCIpLFxuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRoaXMucmVjZW50bHlVc2VkLmxlbmd0aCA+IDAsXG4gICAgICAgICAgICAgICAgdmlzaWJsZTogdGhpcy5yZWNlbnRseVVzZWQubGVuZ3RoID4gMCxcbiAgICAgICAgICAgICAgICByZWY6IFJlYWN0LmNyZWF0ZVJlZigpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBpZDogXCJwZW9wbGVcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBfdChcImVtb2ppfGNhdGVnb3J5X3NtaWxleXNfcGVvcGxlXCIpLFxuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICByZWY6IFJlYWN0LmNyZWF0ZVJlZigpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBpZDogXCJuYXR1cmVcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBfdChcImVtb2ppfGNhdGVnb3J5X2FuaW1hbHNfbmF0dXJlXCIpLFxuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmVmOiBSZWFjdC5jcmVhdGVSZWYoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaWQ6IFwiZm9vZHNcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBfdChcImVtb2ppfGNhdGVnb3J5X2Zvb2RfZHJpbmtcIiksXG4gICAgICAgICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICByZWY6IFJlYWN0LmNyZWF0ZVJlZigpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBpZDogXCJhY3Rpdml0eVwiLFxuICAgICAgICAgICAgICAgIG5hbWU6IF90KFwiZW1vaml8Y2F0ZWdvcnlfYWN0aXZpdGllc1wiKSxcbiAgICAgICAgICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHJlZjogUmVhY3QuY3JlYXRlUmVmKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGlkOiBcInBsYWNlc1wiLFxuICAgICAgICAgICAgICAgIG5hbWU6IF90KFwiZW1vaml8Y2F0ZWdvcnlfdHJhdmVsX3BsYWNlc1wiKSxcbiAgICAgICAgICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHJlZjogUmVhY3QuY3JlYXRlUmVmKCksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGlkOiBcIm9iamVjdHNcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBfdChcImVtb2ppfGNhdGVnb3J5X29iamVjdHNcIiksXG4gICAgICAgICAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICByZWY6IFJlYWN0LmNyZWF0ZVJlZigpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBpZDogXCJzeW1ib2xzXCIsXG4gICAgICAgICAgICAgICAgbmFtZTogX3QoXCJlbW9qaXxjYXRlZ29yeV9zeW1ib2xzXCIpLFxuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmVmOiBSZWFjdC5jcmVhdGVSZWYoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaWQ6IFwiZmxhZ3NcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBfdChcImVtb2ppfGNhdGVnb3J5X2ZsYWdzXCIpLFxuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmVmOiBSZWFjdC5jcmVhdGVSZWYoKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblNjcm9sbCA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgYm9keSA9IHRoaXMuc2Nyb2xsUmVmLmN1cnJlbnQ/LmNvbnRhaW5lclJlZi5jdXJyZW50O1xuICAgICAgICBpZiAoIWJvZHkpIHJldHVybjtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzY3JvbGxUb3A6IGJvZHkuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgdmlld3BvcnRIZWlnaHQ6IGJvZHkuY2xpZW50SGVpZ2h0LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy51cGRhdGVWaXNpYmlsaXR5KCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUga2V5Ym9hcmROYXZpZ2F0aW9uKGV2OiBSZWFjdC5LZXlib2FyZEV2ZW50LCBzdGF0ZTogUm92aW5nU3RhdGUsIGRpc3BhdGNoOiBEaXNwYXRjaDxSb3ZpbmdBY3Rpb24+KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBzdGF0ZS5hY3RpdmVSZWY/LmN1cnJlbnQ7XG4gICAgICAgIGNvbnN0IHBhcmVudCA9IG5vZGU/LnBhcmVudEVsZW1lbnQ7XG4gICAgICAgIGlmICghcGFyZW50IHx8ICFzdGF0ZS5hY3RpdmVSZWYpIHJldHVybjtcbiAgICAgICAgY29uc3Qgcm93SW5kZXggPSBBcnJheS5mcm9tKHBhcmVudC5jaGlsZHJlbikuaW5kZXhPZihub2RlKTtcbiAgICAgICAgY29uc3QgcmVmSW5kZXggPSBzdGF0ZS5yZWZzLmluZGV4T2Yoc3RhdGUuYWN0aXZlUmVmKTtcblxuICAgICAgICBsZXQgZm9jdXNSZWY6IFJlZiB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IG5ld1BhcmVudDogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIHN3aXRjaCAoZXYua2V5KSB7XG4gICAgICAgICAgICBjYXNlIEtleS5BUlJPV19MRUZUOlxuICAgICAgICAgICAgICAgIGZvY3VzUmVmID0gc3RhdGUucmVmc1tyZWZJbmRleCAtIDFdO1xuICAgICAgICAgICAgICAgIG5ld1BhcmVudCA9IGZvY3VzUmVmPy5jdXJyZW50Py5wYXJlbnRFbGVtZW50ID8/IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSBLZXkuQVJST1dfUklHSFQ6XG4gICAgICAgICAgICAgICAgZm9jdXNSZWYgPSBzdGF0ZS5yZWZzW3JlZkluZGV4ICsgMV07XG4gICAgICAgICAgICAgICAgbmV3UGFyZW50ID0gZm9jdXNSZWY/LmN1cnJlbnQ/LnBhcmVudEVsZW1lbnQgPz8gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlIEtleS5BUlJPV19VUDpcbiAgICAgICAgICAgIGNhc2UgS2V5LkFSUk9XX0RPV046IHtcbiAgICAgICAgICAgICAgICAvLyBGb3IgdXAvZG93biB3ZSBmaW5kIHRoZSBwcmV2L25leHQgcGFyZW50IGJ5IGluc3BlY3RpbmcgdGhlIHJlZnMgZWl0aGVyIHNpZGUgb2Ygb3VyIHJvd1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlZiA9XG4gICAgICAgICAgICAgICAgICAgIGV2LmtleSA9PT0gS2V5LkFSUk9XX1VQXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHN0YXRlLnJlZnNbcmVmSW5kZXggLSByb3dJbmRleCAtIDFdXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHN0YXRlLnJlZnNbcmVmSW5kZXggLSByb3dJbmRleCArIEVNT0pJU19QRVJfUk9XXTtcbiAgICAgICAgICAgICAgICBuZXdQYXJlbnQgPSByZWY/LmN1cnJlbnQ/LnBhcmVudEVsZW1lbnQgPz8gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld1RhcmdldCA9IG5ld1BhcmVudD8uY2hpbGRyZW5bY2xhbXAocm93SW5kZXgsIDAsIG5ld1BhcmVudC5jaGlsZHJlbi5sZW5ndGggLSAxKV07XG4gICAgICAgICAgICAgICAgZm9jdXNSZWYgPSBzdGF0ZS5yZWZzLmZpbmQoKHIpID0+IHIuY3VycmVudCA9PT0gbmV3VGFyZ2V0KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmb2N1c1JlZikge1xuICAgICAgICAgICAgZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6IFR5cGUuU2V0Rm9jdXMsXG4gICAgICAgICAgICAgICAgcGF5bG9hZDogeyByZWY6IGZvY3VzUmVmIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKHBhcmVudCAhPT0gbmV3UGFyZW50KSB7XG4gICAgICAgICAgICAgICAgZm9jdXNSZWYuY3VycmVudD8uc2Nyb2xsSW50b1ZpZXcoe1xuICAgICAgICAgICAgICAgICAgICBiZWhhdmlvcjogXCJhdXRvXCIsXG4gICAgICAgICAgICAgICAgICAgIGJsb2NrOiBcImNlbnRlclwiLFxuICAgICAgICAgICAgICAgICAgICBpbmxpbmU6IFwiY2VudGVyXCIsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uS2V5RG93biA9IChldjogUmVhY3QuS2V5Ym9hcmRFdmVudCwgc3RhdGU6IFJvdmluZ1N0YXRlLCBkaXNwYXRjaDogRGlzcGF0Y2g8Um92aW5nQWN0aW9uPik6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBzdGF0ZS5hY3RpdmVSZWY/LmN1cnJlbnQgJiZcbiAgICAgICAgICAgIFtLZXkuQVJST1dfRE9XTiwgS2V5LkFSUk9XX1JJR0hULCBLZXkuQVJST1dfTEVGVCwgS2V5LkFSUk9XX1VQXS5pbmNsdWRlcyhldi5rZXkpXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5rZXlib2FyZE5hdmlnYXRpb24oZXYsIHN0YXRlLCBkaXNwYXRjaCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSB1cGRhdGVWaXNpYmlsaXR5ID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBib2R5ID0gdGhpcy5zY3JvbGxSZWYuY3VycmVudD8uY29udGFpbmVyUmVmLmN1cnJlbnQ7XG4gICAgICAgIGlmICghYm9keSkgcmV0dXJuO1xuICAgICAgICBjb25zdCByZWN0ID0gYm9keS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgZm9yIChjb25zdCBjYXQgb2YgdGhpcy5jYXRlZ29yaWVzKSB7XG4gICAgICAgICAgICBjb25zdCBlbGVtID0gYm9keS5xdWVyeVNlbGVjdG9yKGBbZGF0YS1jYXRlZ29yeS1pZD1cIiR7Y2F0LmlkfVwiXWApO1xuICAgICAgICAgICAgaWYgKCFlbGVtKSB7XG4gICAgICAgICAgICAgICAgY2F0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjYXQucmVmLmN1cnJlbnQ/LmNsYXNzTGlzdC5yZW1vdmUoXCJteF9FbW9qaVBpY2tlcl9hbmNob3JfdmlzaWJsZVwiKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGVsZW1SZWN0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIGNvbnN0IHkgPSBlbGVtUmVjdC55IC0gcmVjdC55O1xuICAgICAgICAgICAgY29uc3QgeUVuZCA9IGVsZW1SZWN0LnkgKyBlbGVtUmVjdC5oZWlnaHQgLSByZWN0Lnk7XG4gICAgICAgICAgICBjYXQudmlzaWJsZSA9IHkgPCByZWN0LmhlaWdodCAmJiB5RW5kID4gMDtcbiAgICAgICAgICAgIC8vIFdlIHVwZGF0ZSB0aGlzIGhlcmUgaW5zdGVhZCBvZiB0aHJvdWdoIFJlYWN0IHRvIGF2b2lkIHJlLXJlbmRlciBvbiBzY3JvbGwuXG4gICAgICAgICAgICBpZiAoIWNhdC5yZWYuY3VycmVudCkgY29udGludWU7XG4gICAgICAgICAgICBpZiAoY2F0LnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICBjYXQucmVmLmN1cnJlbnQuY2xhc3NMaXN0LmFkZChcIm14X0Vtb2ppUGlja2VyX2FuY2hvcl92aXNpYmxlXCIpO1xuICAgICAgICAgICAgICAgIGNhdC5yZWYuY3VycmVudC5zZXRBdHRyaWJ1dGUoXCJhcmlhLXNlbGVjdGVkXCIsIFwidHJ1ZVwiKTtcbiAgICAgICAgICAgICAgICBjYXQucmVmLmN1cnJlbnQuc2V0QXR0cmlidXRlKFwidGFiaW5kZXhcIiwgXCIwXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYXQucmVmLmN1cnJlbnQuY2xhc3NMaXN0LnJlbW92ZShcIm14X0Vtb2ppUGlja2VyX2FuY2hvcl92aXNpYmxlXCIpO1xuICAgICAgICAgICAgICAgIGNhdC5yZWYuY3VycmVudC5zZXRBdHRyaWJ1dGUoXCJhcmlhLXNlbGVjdGVkXCIsIFwiZmFsc2VcIik7XG4gICAgICAgICAgICAgICAgY2F0LnJlZi5jdXJyZW50LnNldEF0dHJpYnV0ZShcInRhYmluZGV4XCIsIFwiLTFcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBzY3JvbGxUb0NhdGVnb3J5ID0gKGNhdGVnb3J5OiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zY3JvbGxSZWYuY3VycmVudD8uY29udGFpbmVyUmVmLmN1cnJlbnRcbiAgICAgICAgICAgID8ucXVlcnlTZWxlY3RvcihgW2RhdGEtY2F0ZWdvcnktaWQ9XCIke2NhdGVnb3J5fVwiXWApXG4gICAgICAgICAgICA/LnNjcm9sbEludG9WaWV3KCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25DaGFuZ2VGaWx0ZXIgPSAoZmlsdGVyOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgbGNGaWx0ZXIgPSBmaWx0ZXIudG9Mb3dlckNhc2UoKS50cmltKCk7IC8vIGZpbHRlciBpcyBjYXNlIGluc2Vuc2l0aXZlXG4gICAgICAgIGZvciAoY29uc3QgY2F0IG9mIHRoaXMuY2F0ZWdvcmllcykge1xuICAgICAgICAgICAgbGV0IGVtb2ppczogSUVtb2ppW107XG4gICAgICAgICAgICAvLyBJZiB0aGUgbmV3IGZpbHRlciBzdHJpbmcgaW5jbHVkZXMgdGhlIG9sZCBmaWx0ZXIgc3RyaW5nLCB3ZSBkb24ndCBoYXZlIHRvIHJlLWZpbHRlciB0aGUgd2hvbGUgZGF0YXNldC5cbiAgICAgICAgICAgIGlmIChsY0ZpbHRlci5pbmNsdWRlcyh0aGlzLnN0YXRlLmZpbHRlcikpIHtcbiAgICAgICAgICAgICAgICBlbW9qaXMgPSB0aGlzLm1lbW9pemVkRGF0YUJ5Q2F0ZWdvcnlbY2F0LmlkXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZW1vamlzID0gY2F0LmlkID09PSBcInJlY2VudFwiID8gdGhpcy5yZWNlbnRseVVzZWQgOiBEQVRBX0JZX0NBVEVHT1JZW2NhdC5pZF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChsY0ZpbHRlciAhPT0gXCJcIikge1xuICAgICAgICAgICAgICAgIGVtb2ppcyA9IGVtb2ppcy5maWx0ZXIoKGVtb2ppKSA9PiB0aGlzLmVtb2ppTWF0Y2hlc0ZpbHRlcihlbW9qaSwgbGNGaWx0ZXIpKTtcbiAgICAgICAgICAgICAgICAvLyBDb3B5IHRoZSBhcnJheSB0byBub3QgY2xvYmJlciB0aGUgb3JpZ2luYWwgdW5maWx0ZXJlZCBzb3J0aW5nXG4gICAgICAgICAgICAgICAgZW1vamlzID0gWy4uLmVtb2ppc10uc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleEEgPSBhLnNob3J0Y29kZXNbMF0uaW5kZXhPZihsY0ZpbHRlcik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4QiA9IGIuc2hvcnRjb2Rlc1swXS5pbmRleE9mKGxjRmlsdGVyKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBQcmlvcml0aXplIGVtb2ppcyBjb250YWluaW5nIHRoZSBmaWx0ZXIgaW4gaXRzIHNob3J0Y29kZVxuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhBID09IC0xIHx8IGluZGV4QiA9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluZGV4QiAtIGluZGV4QTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGJvdGggZW1vamlzIHN0YXJ0IHdpdGggdGhlIGZpbHRlclxuICAgICAgICAgICAgICAgICAgICAvLyBwdXQgdGhlIHNob3J0ZXIgZW1vamkgZmlyc3RcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4QSA9PSAwICYmIGluZGV4QiA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5zaG9ydGNvZGVzWzBdLmxlbmd0aCAtIGIuc2hvcnRjb2Rlc1swXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBQcmlvcml0aXplIGVtb2ppcyBzdGFydGluZyB3aXRoIHRoZSBmaWx0ZXJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluZGV4QSAtIGluZGV4QjtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZW1vaXplZERhdGFCeUNhdGVnb3J5W2NhdC5pZF0gPSBlbW9qaXM7XG4gICAgICAgICAgICBjYXQuZW5hYmxlZCA9IGVtb2ppcy5sZW5ndGggPiAwO1xuICAgICAgICAgICAgLy8gVGhlIHNldFN0YXRlIGJlbG93IGRvZXNuJ3QgcmUtcmVuZGVyIHRoZSBoZWFkZXIgYW5kIHdlIGFscmVhZHkgaGF2ZSB0aGUgcmVmcyBmb3IgdXBkYXRlVmlzaWJpbGl0eSwgc28uLi5cbiAgICAgICAgICAgIGlmIChjYXQucmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICBjYXQucmVmLmN1cnJlbnQuZGlzYWJsZWQgPSAhY2F0LmVuYWJsZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGZpbHRlciB9KTtcbiAgICAgICAgLy8gSGVhZGVyIHVuZGVybGluZXMgbmVlZCB0byBiZSB1cGRhdGVkLCBidXQgdXBkYXRpbmcgcmVxdWlyZXMga25vd2luZ1xuICAgICAgICAvLyB3aGVyZSB0aGUgY2F0ZWdvcmllcyBhcmUsIHNvIHdlIHdhaXQgZm9yIGEgdGljay5cbiAgICAgICAgd2luZG93LnNldFRpbWVvdXQodGhpcy51cGRhdGVWaXNpYmlsaXR5LCAwKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBlbW9qaU1hdGNoZXNGaWx0ZXIgPSAoZW1vamk6IElFbW9qaSwgZmlsdGVyOiBzdHJpbmcpOiBib29sZWFuID0+IHtcbiAgICAgICAgLy8gSWYgdGhlIHF1ZXJ5IGlzIGFuIGVtb2ppIGNvbnRhaW5pbmcgYSB2YXJpYXRpb24gdGhlbiBzdHJpcCBpdCB0byBwcm92aWRlIG1vcmUgdXNlZnVsIG1hdGNoZXNcbiAgICAgICAgaWYgKGZpbHRlci5pbmNsdWRlcyhaRVJPX1dJRFRIX0pPSU5FUikpIHtcbiAgICAgICAgICAgIGZpbHRlciA9IGZpbHRlci5zcGxpdChaRVJPX1dJRFRIX0pPSU5FUiwgMilbMF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGVtb2ppLmxhYmVsLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoZmlsdGVyKSB8fFxuICAgICAgICAgICAgKEFycmF5LmlzQXJyYXkoZW1vamkuZW1vdGljb24pXG4gICAgICAgICAgICAgICAgPyBlbW9qaS5lbW90aWNvbi5zb21lKCh4KSA9PiB4LmluY2x1ZGVzKGZpbHRlcikpXG4gICAgICAgICAgICAgICAgOiBlbW9qaS5lbW90aWNvbj8uaW5jbHVkZXMoZmlsdGVyKSkgfHxcbiAgICAgICAgICAgIGVtb2ppLnNob3J0Y29kZXMuc29tZSgoeCkgPT4geC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKGZpbHRlcikpIHx8XG4gICAgICAgICAgICBlbW9qaS51bmljb2RlLnNwbGl0KFpFUk9fV0lEVEhfSk9JTkVSKS5pbmNsdWRlcyhmaWx0ZXIpXG4gICAgICAgICk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25FbnRlckZpbHRlciA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgYnRuID0gdGhpcy5zY3JvbGxSZWYuY3VycmVudD8uY29udGFpbmVyUmVmLmN1cnJlbnQ/LnF1ZXJ5U2VsZWN0b3I8SFRNTEJ1dHRvbkVsZW1lbnQ+KFxuICAgICAgICAgICAgJy5teF9FbW9qaVBpY2tlcl9pdGVtX3dyYXBwZXJbdGFiaW5kZXg9XCIwXCJdJyxcbiAgICAgICAgKTtcbiAgICAgICAgYnRuPy5jbGljaygpO1xuICAgICAgICB0aGlzLnByb3BzLm9uRmluaXNoZWQoKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkhvdmVyRW1vamkgPSAoZW1vamk6IElFbW9qaSk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHByZXZpZXdFbW9qaTogZW1vamksXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uSG92ZXJFbW9qaUVuZCA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBwcmV2aWV3RW1vamk6IHVuZGVmaW5lZCxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25DbGlja0Vtb2ppID0gKGV2OiBCdXR0b25FdmVudCwgZW1vamk6IElFbW9qaSk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5vbkNob29zZShlbW9qaS51bmljb2RlKSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJlY2VudC5hZGQoZW1vamkudW5pY29kZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChldiBhcyBSZWFjdC5LZXlib2FyZEV2ZW50KS5rZXkgPT09IEtleS5FTlRFUikge1xuICAgICAgICAgICAgdGhpcy5wcm9wcy5vbkZpbmlzaGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgY2F0ZWdvcnlIZWlnaHRGb3JFbW9qaUNvdW50KGNvdW50OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBpZiAoY291bnQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBDQVRFR09SWV9IRUFERVJfSEVJR0hUICsgTWF0aC5jZWlsKGNvdW50IC8gRU1PSklTX1BFUl9ST1cpICogRU1PSklfSEVJR0hUO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxSb3ZpbmdUYWJJbmRleFByb3ZpZGVyIG9uS2V5RG93bj17dGhpcy5vbktleURvd259PlxuICAgICAgICAgICAgICAgIHsoeyBvbktleURvd25IYW5kbGVyIH0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGhlaWdodEJlZm9yZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICA8c2VjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0Vtb2ppUGlja2VyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cIm14X0Vtb2ppUGlja2VyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbktleURvd249e29uS2V5RG93bkhhbmRsZXJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1sYWJlbD17X3QoXCJhMTF5fGVtb2ppX3BpY2tlclwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8SGVhZGVyIGNhdGVnb3JpZXM9e3RoaXMuY2F0ZWdvcmllc30gb25BbmNob3JDbGljaz17dGhpcy5zY3JvbGxUb0NhdGVnb3J5fSAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxTZWFyY2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVlcnk9e3RoaXMuc3RhdGUuZmlsdGVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbkNoYW5nZUZpbHRlcn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25FbnRlcj17dGhpcy5vbkVudGVyRmlsdGVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbktleURvd249e29uS2V5RG93bkhhbmRsZXJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8QXV0b0hpZGVTY3JvbGxiYXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ9XCJteF9FbW9qaVBpY2tlcl9ib2R5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfRW1vamlQaWNrZXJfYm9keVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZj17dGhpcy5zY3JvbGxSZWZ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uU2Nyb2xsPXt0aGlzLm9uU2Nyb2xsfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3RoaXMuY2F0ZWdvcmllcy5tYXAoKGNhdGVnb3J5KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbW9qaXMgPSB0aGlzLm1lbW9pemVkRGF0YUJ5Q2F0ZWdvcnlbY2F0ZWdvcnkuaWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2F0ZWdvcnlFbGVtZW50ID0gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxDYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXk9e2NhdGVnb3J5LmlkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZD17Y2F0ZWdvcnkuaWR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9e2NhdGVnb3J5Lm5hbWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodEJlZm9yZT17aGVpZ2h0QmVmb3JlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydEhlaWdodD17dGhpcy5zdGF0ZS52aWV3cG9ydEhlaWdodH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsVG9wPXt0aGlzLnN0YXRlLnNjcm9sbFRvcH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW1vamlzPXtlbW9qaXN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25DbGlja0Vtb2ppfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbk1vdXNlRW50ZXI9e3RoaXMub25Ib3ZlckVtb2ppfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbk1vdXNlTGVhdmU9e3RoaXMub25Ib3ZlckVtb2ppRW5kfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0Vtb2ppRGlzYWJsZWQ9e3RoaXMucHJvcHMuaXNFbW9qaURpc2FibGVkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZEVtb2ppcz17dGhpcy5wcm9wcy5zZWxlY3RlZEVtb2ppc31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IEVtb2ppUGlja2VyLmNhdGVnb3J5SGVpZ2h0Rm9yRW1vamlDb3VudChlbW9qaXMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodEJlZm9yZSArPSBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2F0ZWdvcnlFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L0F1dG9IaWRlU2Nyb2xsYmFyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt0aGlzLnN0YXRlLnByZXZpZXdFbW9qaSA/IChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPFByZXZpZXcgZW1vamk9e3RoaXMuc3RhdGUucHJldmlld0Vtb2ppfSAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgOiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxRdWlja1JlYWN0aW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vbkNsaWNrRW1vaml9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZEVtb2ppcz17dGhpcy5wcm9wcy5zZWxlY3RlZEVtb2ppc31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWN0aW9uPlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA8L1JvdmluZ1RhYkluZGV4UHJvdmlkZXI+XG4gICAgICAgICk7XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBFbW9qaVBpY2tlcjtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQSxJQUFBQSxNQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxrQkFBQSxHQUFBRCxPQUFBO0FBRUEsSUFBQUUsZ0JBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLE1BQUEsR0FBQUMsdUJBQUEsQ0FBQUosT0FBQTtBQUNBLElBQUFLLGtCQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTSxPQUFBLEdBQUFQLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTyxPQUFBLEdBQUFSLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUSxRQUFBLEdBQUFULHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUyxlQUFBLEdBQUFWLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBVSxTQUFBLEdBQUFYLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBVyxPQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxlQUFBLEdBQUFaLE9BQUE7QUFNQSxJQUFBYSxTQUFBLEdBQUFiLE9BQUE7QUFDQSxJQUFBYyxRQUFBLEdBQUFkLE9BQUE7QUFBK0MsU0FBQWUseUJBQUFDLENBQUEsNkJBQUFDLE9BQUEsbUJBQUFDLENB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