UNPKG

matrix-react-sdk

Version:
272 lines (260 loc) 45.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.RoomSearchView = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _matrix = require("matrix-js-sdk/src/matrix"); var _logger = require("matrix-js-sdk/src/logger"); var _ScrollPanel = _interopRequireDefault(require("./ScrollPanel")); var _Spinner = _interopRequireDefault(require("../views/elements/Spinner")); var _languageHandler = require("../../languageHandler"); var _EventTileFactory = require("../../events/EventTileFactory"); var _SearchResultTile = _interopRequireDefault(require("../views/rooms/SearchResultTile")); var _Searching = require("../../Searching"); var _Modal = _interopRequireDefault(require("../../Modal")); var _ErrorDialog = _interopRequireDefault(require("../views/dialogs/ErrorDialog")); var _MatrixClientContext = _interopRequireDefault(require("../../contexts/MatrixClientContext")); var _Permalinks = require("../../utils/permalinks/Permalinks"); var _RoomContext = _interopRequireDefault(require("../../contexts/RoomContext")); 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 2015-2023 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. */ const DEBUG = false; let debuglog = function (msg) {}; /* istanbul ignore next */ if (DEBUG) { // using bind means that we get to keep useful line numbers in the console debuglog = _logger.logger.log.bind(console); } // XXX: todo: merge overlapping results somehow? // XXX: why doesn't searching on name work? const RoomSearchView = exports.RoomSearchView = /*#__PURE__*/(0, _react.forwardRef)(({ term, scope, promise, abortController, resizeNotifier, className, onUpdate, inProgress }, ref) => { const client = (0, _react.useContext)(_MatrixClientContext.default); const roomContext = (0, _react.useContext)(_RoomContext.default); const [highlights, setHighlights] = (0, _react.useState)(null); const [results, setResults] = (0, _react.useState)(null); const aborted = (0, _react.useRef)(false); // A map from room ID to permalink creator const permalinkCreators = (0, _react.useRef)(new Map()).current; const innerRef = (0, _react.useRef)(); (0, _react.useEffect)(() => { return () => { permalinkCreators.forEach(pc => pc.stop()); permalinkCreators.clear(); }; }, [permalinkCreators]); const handleSearchResult = (0, _react.useCallback)(searchPromise => { onUpdate(true, null); return searchPromise.then(async results => { debuglog("search complete"); if (aborted.current) { _logger.logger.error("Discarding stale search results"); return false; } // postgres on synapse returns us precise details of the strings // which actually got matched for highlighting. // // In either case, we want to highlight the literal search term // whether it was used by the search engine or not. let highlights = results.highlights; if (!highlights.includes(term)) { highlights = highlights.concat(term); } // For overlapping highlights, // favour longer (more specific) terms first highlights = highlights.sort(function (a, b) { return b.length - a.length; }); for (const result of results.results) { for (const event of result.context.getTimeline()) { const bundledRelationship = event.getServerAggregatedRelation(_matrix.THREAD_RELATION_TYPE.name); if (!bundledRelationship || event.getThread()) continue; const room = client.getRoom(event.getRoomId()); const thread = room?.findThreadForEvent(event); if (thread) { event.setThread(thread); } else { room?.createThread(event.getId(), event, [], true); } } } setHighlights(highlights); setResults(_objectSpread({}, results)); // copy to force a refresh onUpdate(false, results); return false; }, error => { if (aborted.current) { _logger.logger.error("Discarding stale search results"); return false; } _logger.logger.error("Search failed", error); _Modal.default.createDialog(_ErrorDialog.default, { title: (0, _languageHandler._t)("error_dialog|search_failed|title"), description: error?.message ?? (0, _languageHandler._t)("error_dialog|search_failed|server_unavailable") }); onUpdate(false, null); return false; }); }, [client, term, onUpdate]); // Mount & unmount effect (0, _react.useEffect)(() => { aborted.current = false; handleSearchResult(promise); return () => { aborted.current = true; abortController?.abort(); }; }, []); // eslint-disable-line react-hooks/exhaustive-deps // show searching spinner if (results === null) { return /*#__PURE__*/_react.default.createElement("div", { className: "mx_RoomView_messagePanel mx_RoomView_messagePanelSearchSpinner", "data-testid": "messagePanelSearchSpinner" }); } const onSearchResultsFillRequest = async backwards => { if (!backwards) { return false; } if (!results.next_batch) { debuglog("no more search results"); return false; } debuglog("requesting more search results"); const searchPromise = (0, _Searching.searchPagination)(client, results); return handleSearchResult(searchPromise); }; const ret = []; if (inProgress) { ret.push( /*#__PURE__*/_react.default.createElement("li", { key: "search-spinner" }, /*#__PURE__*/_react.default.createElement(_Spinner.default, null))); } if (!results.next_batch) { if (!results?.results?.length) { ret.push( /*#__PURE__*/_react.default.createElement("li", { key: "search-top-marker" }, /*#__PURE__*/_react.default.createElement("h2", { className: "mx_RoomView_topMarker" }, (0, _languageHandler._t)("common|no_results")))); } else { ret.push( /*#__PURE__*/_react.default.createElement("li", { key: "search-top-marker" }, /*#__PURE__*/_react.default.createElement("h2", { className: "mx_RoomView_topMarker" }, (0, _languageHandler._t)("no_more_results")))); } } // once dynamic content in the search results load, make the scrollPanel check // the scroll offsets. const onHeightChanged = () => { innerRef.current?.checkScroll(); }; const onRef = e => { if (typeof ref === "function") { ref(e); } else if (!!ref) { ref.current = e; } innerRef.current = e; }; let lastRoomId; let mergedTimeline = []; let ourEventsIndexes = []; for (let i = (results?.results?.length || 0) - 1; i >= 0; i--) { const result = results.results[i]; const mxEv = result.context.getEvent(); const roomId = mxEv.getRoomId(); const room = client.getRoom(roomId); if (!room) { // if we do not have the room in js-sdk stores then hide it as we cannot easily show it // As per the spec, an all rooms search can create this condition, // it happens with Seshat but not Synapse. // It will make the result count not match the displayed count. _logger.logger.log("Hiding search result from an unknown room", roomId); continue; } if (!(0, _EventTileFactory.haveRendererForEvent)(mxEv, client, roomContext.showHiddenEvents)) { // XXX: can this ever happen? It will make the result count // not match the displayed count. continue; } if (scope === _Searching.SearchScope.All) { if (roomId !== lastRoomId) { ret.push( /*#__PURE__*/_react.default.createElement("li", { key: mxEv.getId() + "-room" }, /*#__PURE__*/_react.default.createElement("h2", null, (0, _languageHandler._t)("common|room"), ": ", room.name))); lastRoomId = roomId; } } const resultLink = "#/room/" + roomId + "/" + mxEv.getId(); // merging two successive search result if the query is present in both of them const currentTimeline = result.context.getTimeline(); const nextTimeline = i > 0 ? results.results[i - 1].context.getTimeline() : []; if (i > 0 && currentTimeline[currentTimeline.length - 1].getId() == nextTimeline[0].getId()) { // if this is the first searchResult we merge then add all values of the current searchResult if (mergedTimeline.length == 0) { for (let j = mergedTimeline.length == 0 ? 0 : 1; j < result.context.getTimeline().length; j++) { mergedTimeline.push(currentTimeline[j]); } ourEventsIndexes.push(result.context.getOurEventIndex()); } // merge the events of the next searchResult for (let j = 1; j < nextTimeline.length; j++) { mergedTimeline.push(nextTimeline[j]); } // add the index of the matching event of the next searchResult ourEventsIndexes.push(ourEventsIndexes[ourEventsIndexes.length - 1] + results.results[i - 1].context.getOurEventIndex() + 1); continue; } if (mergedTimeline.length == 0) { mergedTimeline = result.context.getTimeline(); ourEventsIndexes = []; ourEventsIndexes.push(result.context.getOurEventIndex()); } let permalinkCreator = permalinkCreators.get(roomId); if (!permalinkCreator) { permalinkCreator = new _Permalinks.RoomPermalinkCreator(room); permalinkCreator.start(); permalinkCreators.set(roomId, permalinkCreator); } ret.push( /*#__PURE__*/_react.default.createElement(_SearchResultTile.default, { key: mxEv.getId(), timeline: mergedTimeline, ourEventsIndexes: ourEventsIndexes, searchHighlights: highlights ?? [], resultLink: resultLink, permalinkCreator: permalinkCreator, onHeightChanged: onHeightChanged })); ourEventsIndexes = []; mergedTimeline = []; } return /*#__PURE__*/_react.default.createElement(_ScrollPanel.default, { ref: onRef, className: "mx_RoomView_searchResultsPanel " + className, onFillRequest: onSearchResultsFillRequest, resizeNotifier: resizeNotifier }, /*#__PURE__*/_react.default.createElement("li", { className: "mx_RoomView_scrollheader" }), ret); }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbWF0cml4IiwiX2xvZ2dlciIsIl9TY3JvbGxQYW5lbCIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfU3Bpbm5lciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfRXZlbnRUaWxlRmFjdG9yeSIsIl9TZWFyY2hSZXN1bHRUaWxlIiwiX1NlYXJjaGluZyIsIl9Nb2RhbCIsIl9FcnJvckRpYWxvZyIsIl9NYXRyaXhDbGllbnRDb250ZXh0IiwiX1Blcm1hbGlua3MiLCJfUm9vbUNvbnRleHQiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJERUJVRyIsImRlYnVnbG9nIiwibXNnIiwibG9nZ2VyIiwibG9nIiwiYmluZCIsImNvbnNvbGUiLCJSb29tU2VhcmNoVmlldyIsImV4cG9ydHMiLCJmb3J3YXJkUmVmIiwidGVybSIsInNjb3BlIiwicHJvbWlzZSIsImFib3J0Q29udHJvbGxlciIsInJlc2l6ZU5vdGlmaWVyIiwiY2xhc3NOYW1lIiwib25VcGRhdGUiLCJpblByb2dyZXNzIiwicmVmIiwiY2xpZW50IiwidXNlQ29udGV4dCIsIk1hdHJpeENsaWVudENvbnRleHQiLCJyb29tQ29udGV4dCIsIlJvb21Db250ZXh0IiwiaGlnaGxpZ2h0cyIsInNldEhpZ2hsaWdodHMiLCJ1c2VTdGF0ZSIsInJlc3VsdHMiLCJzZXRSZXN1bHRzIiwiYWJvcnRlZCIsInVzZVJlZiIsInBlcm1hbGlua0NyZWF0b3JzIiwiTWFwIiwiY3VycmVudCIsImlubmVyUmVmIiwidXNlRWZmZWN0IiwicGMiLCJzdG9wIiwiY2xlYXIiLCJoYW5kbGVTZWFyY2hSZXN1bHQiLCJ1c2VDYWxsYmFjayIsInNlYXJjaFByb21pc2UiLCJ0aGVuIiwiZXJyb3IiLCJpbmNsdWRlcyIsImNvbmNhdCIsInNvcnQiLCJiIiwicmVzdWx0IiwiZXZlbnQiLCJjb250ZXh0IiwiZ2V0VGltZWxpbmUiLCJidW5kbGVkUmVsYXRpb25zaGlwIiwiZ2V0U2VydmVyQWdncmVnYXRlZFJlbGF0aW9uIiwiVEhSRUFEX1JFTEFUSU9OX1RZUEUiLCJuYW1lIiwiZ2V0VGhyZWFkIiwicm9vbSIsImdldFJvb20iLCJnZXRSb29tSWQiLCJ0aHJlYWQiLCJmaW5kVGhyZWFkRm9yRXZlbnQiLCJzZXRUaHJlYWQiLCJjcmVhdGVUaHJlYWQiLCJnZXRJZCIsIk1vZGFsIiwiY3JlYXRlRGlhbG9nIiwiRXJyb3JEaWFsb2ciLCJ0aXRsZSIsIl90IiwiZGVzY3JpcHRpb24iLCJtZXNzYWdlIiwiYWJvcnQiLCJjcmVhdGVFbGVtZW50Iiwib25TZWFyY2hSZXN1bHRzRmlsbFJlcXVlc3QiLCJiYWNrd2FyZHMiLCJuZXh0X2JhdGNoIiwic2VhcmNoUGFnaW5hdGlvbiIsInJldCIsImtleSIsIm9uSGVpZ2h0Q2hhbmdlZCIsImNoZWNrU2Nyb2xsIiwib25SZWYiLCJsYXN0Um9vbUlkIiwibWVyZ2VkVGltZWxpbmUiLCJvdXJFdmVudHNJbmRleGVzIiwibXhFdiIsImdldEV2ZW50Iiwicm9vbUlkIiwiaGF2ZVJlbmRlcmVyRm9yRXZlbnQiLCJzaG93SGlkZGVuRXZlbnRzIiwiU2VhcmNoU2NvcGUiLCJBbGwiLCJyZXN1bHRMaW5rIiwiY3VycmVudFRpbWVsaW5lIiwibmV4dFRpbWVsaW5lIiwiaiIsImdldE91ckV2ZW50SW5kZXgiLCJwZXJtYWxpbmtDcmVhdG9yIiwiUm9vbVBlcm1hbGlua0NyZWF0b3IiLCJzdGFydCIsInRpbWVsaW5lIiwic2VhcmNoSGlnaGxpZ2h0cyIsIm9uRmlsbFJlcXVlc3QiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tcG9uZW50cy9zdHJ1Y3R1cmVzL1Jvb21TZWFyY2hWaWV3LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxNS0yMDIzIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBmb3J3YXJkUmVmLCB1c2VDYWxsYmFjaywgdXNlQ29udGV4dCwgdXNlRWZmZWN0LCB1c2VSZWYsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1xuICAgIElTZWFyY2hSZXN1bHRzLFxuICAgIElUaHJlYWRCdW5kbGVkUmVsYXRpb25zaGlwLFxuICAgIE1hdHJpeEV2ZW50LFxuICAgIFRIUkVBRF9SRUxBVElPTl9UWVBFLFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5cbmltcG9ydCBTY3JvbGxQYW5lbCBmcm9tIFwiLi9TY3JvbGxQYW5lbFwiO1xuaW1wb3J0IFNwaW5uZXIgZnJvbSBcIi4uL3ZpZXdzL2VsZW1lbnRzL1NwaW5uZXJcIjtcbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IHsgaGF2ZVJlbmRlcmVyRm9yRXZlbnQgfSBmcm9tIFwiLi4vLi4vZXZlbnRzL0V2ZW50VGlsZUZhY3RvcnlcIjtcbmltcG9ydCBTZWFyY2hSZXN1bHRUaWxlIGZyb20gXCIuLi92aWV3cy9yb29tcy9TZWFyY2hSZXN1bHRUaWxlXCI7XG5pbXBvcnQgeyBzZWFyY2hQYWdpbmF0aW9uLCBTZWFyY2hTY29wZSB9IGZyb20gXCIuLi8uLi9TZWFyY2hpbmdcIjtcbmltcG9ydCBNb2RhbCBmcm9tIFwiLi4vLi4vTW9kYWxcIjtcbmltcG9ydCBFcnJvckRpYWxvZyBmcm9tIFwiLi4vdmlld3MvZGlhbG9ncy9FcnJvckRpYWxvZ1wiO1xuaW1wb3J0IFJlc2l6ZU5vdGlmaWVyIGZyb20gXCIuLi8uLi91dGlscy9SZXNpemVOb3RpZmllclwiO1xuaW1wb3J0IE1hdHJpeENsaWVudENvbnRleHQgZnJvbSBcIi4uLy4uL2NvbnRleHRzL01hdHJpeENsaWVudENvbnRleHRcIjtcbmltcG9ydCB7IFJvb21QZXJtYWxpbmtDcmVhdG9yIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Blcm1hbGlua3MvUGVybWFsaW5rc1wiO1xuaW1wb3J0IFJvb21Db250ZXh0IGZyb20gXCIuLi8uLi9jb250ZXh0cy9Sb29tQ29udGV4dFwiO1xuXG5jb25zdCBERUJVRyA9IGZhbHNlO1xubGV0IGRlYnVnbG9nID0gZnVuY3Rpb24gKG1zZzogc3RyaW5nKTogdm9pZCB7fTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmlmIChERUJVRykge1xuICAgIC8vIHVzaW5nIGJpbmQgbWVhbnMgdGhhdCB3ZSBnZXQgdG8ga2VlcCB1c2VmdWwgbGluZSBudW1iZXJzIGluIHRoZSBjb25zb2xlXG4gICAgZGVidWdsb2cgPSBsb2dnZXIubG9nLmJpbmQoY29uc29sZSk7XG59XG5cbmludGVyZmFjZSBQcm9wcyB7XG4gICAgdGVybTogc3RyaW5nO1xuICAgIHNjb3BlOiBTZWFyY2hTY29wZTtcbiAgICBpblByb2dyZXNzOiBib29sZWFuO1xuICAgIHByb21pc2U6IFByb21pc2U8SVNlYXJjaFJlc3VsdHM+O1xuICAgIGFib3J0Q29udHJvbGxlcj86IEFib3J0Q29udHJvbGxlcjtcbiAgICByZXNpemVOb3RpZmllcjogUmVzaXplTm90aWZpZXI7XG4gICAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gICAgb25VcGRhdGUoaW5Qcm9ncmVzczogYm9vbGVhbiwgcmVzdWx0czogSVNlYXJjaFJlc3VsdHMgfCBudWxsKTogdm9pZDtcbn1cblxuLy8gWFhYOiB0b2RvOiBtZXJnZSBvdmVybGFwcGluZyByZXN1bHRzIHNvbWVob3c/XG4vLyBYWFg6IHdoeSBkb2Vzbid0IHNlYXJjaGluZyBvbiBuYW1lIHdvcms/XG5leHBvcnQgY29uc3QgUm9vbVNlYXJjaFZpZXcgPSBmb3J3YXJkUmVmPFNjcm9sbFBhbmVsLCBQcm9wcz4oXG4gICAgKHsgdGVybSwgc2NvcGUsIHByb21pc2UsIGFib3J0Q29udHJvbGxlciwgcmVzaXplTm90aWZpZXIsIGNsYXNzTmFtZSwgb25VcGRhdGUsIGluUHJvZ3Jlc3MgfTogUHJvcHMsIHJlZikgPT4ge1xuICAgICAgICBjb25zdCBjbGllbnQgPSB1c2VDb250ZXh0KE1hdHJpeENsaWVudENvbnRleHQpO1xuICAgICAgICBjb25zdCByb29tQ29udGV4dCA9IHVzZUNvbnRleHQoUm9vbUNvbnRleHQpO1xuICAgICAgICBjb25zdCBbaGlnaGxpZ2h0cywgc2V0SGlnaGxpZ2h0c10gPSB1c2VTdGF0ZTxzdHJpbmdbXSB8IG51bGw+KG51bGwpO1xuICAgICAgICBjb25zdCBbcmVzdWx0cywgc2V0UmVzdWx0c10gPSB1c2VTdGF0ZTxJU2VhcmNoUmVzdWx0cyB8IG51bGw+KG51bGwpO1xuICAgICAgICBjb25zdCBhYm9ydGVkID0gdXNlUmVmKGZhbHNlKTtcbiAgICAgICAgLy8gQSBtYXAgZnJvbSByb29tIElEIHRvIHBlcm1hbGluayBjcmVhdG9yXG4gICAgICAgIGNvbnN0IHBlcm1hbGlua0NyZWF0b3JzID0gdXNlUmVmKG5ldyBNYXA8c3RyaW5nLCBSb29tUGVybWFsaW5rQ3JlYXRvcj4oKSkuY3VycmVudDtcbiAgICAgICAgY29uc3QgaW5uZXJSZWYgPSB1c2VSZWY8U2Nyb2xsUGFuZWwgfCBudWxsPigpO1xuXG4gICAgICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHBlcm1hbGlua0NyZWF0b3JzLmZvckVhY2goKHBjKSA9PiBwYy5zdG9wKCkpO1xuICAgICAgICAgICAgICAgIHBlcm1hbGlua0NyZWF0b3JzLmNsZWFyKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCBbcGVybWFsaW5rQ3JlYXRvcnNdKTtcblxuICAgICAgICBjb25zdCBoYW5kbGVTZWFyY2hSZXN1bHQgPSB1c2VDYWxsYmFjayhcbiAgICAgICAgICAgIChzZWFyY2hQcm9taXNlOiBQcm9taXNlPElTZWFyY2hSZXN1bHRzPik6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgICAgICAgICAgICAgIG9uVXBkYXRlKHRydWUsIG51bGwpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlYXJjaFByb21pc2UudGhlbihcbiAgICAgICAgICAgICAgICAgICAgYXN5bmMgKHJlc3VsdHMpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlYnVnbG9nKFwic2VhcmNoIGNvbXBsZXRlXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFib3J0ZWQuY3VycmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkRpc2NhcmRpbmcgc3RhbGUgc2VhcmNoIHJlc3VsdHNcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwb3N0Z3JlcyBvbiBzeW5hcHNlIHJldHVybnMgdXMgcHJlY2lzZSBkZXRhaWxzIG9mIHRoZSBzdHJpbmdzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGljaCBhY3R1YWxseSBnb3QgbWF0Y2hlZCBmb3IgaGlnaGxpZ2h0aW5nLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluIGVpdGhlciBjYXNlLCB3ZSB3YW50IHRvIGhpZ2hsaWdodCB0aGUgbGl0ZXJhbCBzZWFyY2ggdGVybVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hldGhlciBpdCB3YXMgdXNlZCBieSB0aGUgc2VhcmNoIGVuZ2luZSBvciBub3QuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBoaWdobGlnaHRzID0gcmVzdWx0cy5oaWdobGlnaHRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoaWdobGlnaHRzLmluY2x1ZGVzKHRlcm0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0cyA9IGhpZ2hsaWdodHMuY29uY2F0KHRlcm0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGb3Igb3ZlcmxhcHBpbmcgaGlnaGxpZ2h0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZhdm91ciBsb25nZXIgKG1vcmUgc3BlY2lmaWMpIHRlcm1zIGZpcnN0XG4gICAgICAgICAgICAgICAgICAgICAgICBoaWdobGlnaHRzID0gaGlnaGxpZ2h0cy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGIubGVuZ3RoIC0gYS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cy5yZXN1bHRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiByZXN1bHQuY29udGV4dC5nZXRUaW1lbGluZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJ1bmRsZWRSZWxhdGlvbnNoaXAgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuZ2V0U2VydmVyQWdncmVnYXRlZFJlbGF0aW9uPElUaHJlYWRCdW5kbGVkUmVsYXRpb25zaGlwPihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUSFJFQURfUkVMQVRJT05fVFlQRS5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFidW5kbGVkUmVsYXRpb25zaGlwIHx8IGV2ZW50LmdldFRocmVhZCgpKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgcm9vbSA9IGNsaWVudC5nZXRSb29tKGV2ZW50LmdldFJvb21JZCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGhyZWFkID0gcm9vbT8uZmluZFRocmVhZEZvckV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRocmVhZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuc2V0VGhyZWFkKHRocmVhZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb29tPy5jcmVhdGVUaHJlYWQoZXZlbnQuZ2V0SWQoKSEsIGV2ZW50LCBbXSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNldEhpZ2hsaWdodHMoaGlnaGxpZ2h0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRSZXN1bHRzKHsgLi4ucmVzdWx0cyB9KTsgLy8gY29weSB0byBmb3JjZSBhIHJlZnJlc2hcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uVXBkYXRlKGZhbHNlLCByZXN1bHRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWJvcnRlZC5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiRGlzY2FyZGluZyBzdGFsZSBzZWFyY2ggcmVzdWx0c1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJTZWFyY2ggZmFpbGVkXCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhFcnJvckRpYWxvZywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiBfdChcImVycm9yX2RpYWxvZ3xzZWFyY2hfZmFpbGVkfHRpdGxlXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBlcnJvcj8ubWVzc2FnZSA/PyBfdChcImVycm9yX2RpYWxvZ3xzZWFyY2hfZmFpbGVkfHNlcnZlcl91bmF2YWlsYWJsZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgb25VcGRhdGUoZmFsc2UsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW2NsaWVudCwgdGVybSwgb25VcGRhdGVdLFxuICAgICAgICApO1xuXG4gICAgICAgIC8vIE1vdW50ICYgdW5tb3VudCBlZmZlY3RcbiAgICAgICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgICAgIGFib3J0ZWQuY3VycmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgaGFuZGxlU2VhcmNoUmVzdWx0KHByb21pc2UpO1xuICAgICAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgICAgICBhYm9ydGVkLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGFib3J0Q29udHJvbGxlcj8uYWJvcnQoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIFtdKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcblxuICAgICAgICAvLyBzaG93IHNlYXJjaGluZyBzcGlubmVyXG4gICAgICAgIGlmIChyZXN1bHRzID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfUm9vbVZpZXdfbWVzc2FnZVBhbmVsIG14X1Jvb21WaWV3X21lc3NhZ2VQYW5lbFNlYXJjaFNwaW5uZXJcIlxuICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cIm1lc3NhZ2VQYW5lbFNlYXJjaFNwaW5uZXJcIlxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgb25TZWFyY2hSZXN1bHRzRmlsbFJlcXVlc3QgPSBhc3luYyAoYmFja3dhcmRzOiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgICAgICAgICBpZiAoIWJhY2t3YXJkcykge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFyZXN1bHRzLm5leHRfYmF0Y2gpIHtcbiAgICAgICAgICAgICAgICBkZWJ1Z2xvZyhcIm5vIG1vcmUgc2VhcmNoIHJlc3VsdHNcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkZWJ1Z2xvZyhcInJlcXVlc3RpbmcgbW9yZSBzZWFyY2ggcmVzdWx0c1wiKTtcbiAgICAgICAgICAgIGNvbnN0IHNlYXJjaFByb21pc2UgPSBzZWFyY2hQYWdpbmF0aW9uKGNsaWVudCwgcmVzdWx0cyk7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlU2VhcmNoUmVzdWx0KHNlYXJjaFByb21pc2UpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHJldDogSlNYLkVsZW1lbnRbXSA9IFtdO1xuXG4gICAgICAgIGlmIChpblByb2dyZXNzKSB7XG4gICAgICAgICAgICByZXQucHVzaChcbiAgICAgICAgICAgICAgICA8bGkga2V5PVwic2VhcmNoLXNwaW5uZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgPFNwaW5uZXIgLz5cbiAgICAgICAgICAgICAgICA8L2xpPixcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlc3VsdHMubmV4dF9iYXRjaCkge1xuICAgICAgICAgICAgaWYgKCFyZXN1bHRzPy5yZXN1bHRzPy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXQucHVzaChcbiAgICAgICAgICAgICAgICAgICAgPGxpIGtleT1cInNlYXJjaC10b3AtbWFya2VyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aDIgY2xhc3NOYW1lPVwibXhfUm9vbVZpZXdfdG9wTWFya2VyXCI+e190KFwiY29tbW9ufG5vX3Jlc3VsdHNcIil9PC9oMj5cbiAgICAgICAgICAgICAgICAgICAgPC9saT4sXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0LnB1c2goXG4gICAgICAgICAgICAgICAgICAgIDxsaSBrZXk9XCJzZWFyY2gtdG9wLW1hcmtlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGgyIGNsYXNzTmFtZT1cIm14X1Jvb21WaWV3X3RvcE1hcmtlclwiPntfdChcIm5vX21vcmVfcmVzdWx0c1wiKX08L2gyPlxuICAgICAgICAgICAgICAgICAgICA8L2xpPixcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gb25jZSBkeW5hbWljIGNvbnRlbnQgaW4gdGhlIHNlYXJjaCByZXN1bHRzIGxvYWQsIG1ha2UgdGhlIHNjcm9sbFBhbmVsIGNoZWNrXG4gICAgICAgIC8vIHRoZSBzY3JvbGwgb2Zmc2V0cy5cbiAgICAgICAgY29uc3Qgb25IZWlnaHRDaGFuZ2VkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgaW5uZXJSZWYuY3VycmVudD8uY2hlY2tTY3JvbGwoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBvblJlZiA9IChlOiBTY3JvbGxQYW5lbCB8IG51bGwpOiB2b2lkID0+IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcmVmID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICByZWYoZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCEhcmVmKSB7XG4gICAgICAgICAgICAgICAgcmVmLmN1cnJlbnQgPSBlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5uZXJSZWYuY3VycmVudCA9IGU7XG4gICAgICAgIH07XG5cbiAgICAgICAgbGV0IGxhc3RSb29tSWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IG1lcmdlZFRpbWVsaW5lOiBNYXRyaXhFdmVudFtdID0gW107XG4gICAgICAgIGxldCBvdXJFdmVudHNJbmRleGVzOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAocmVzdWx0cz8ucmVzdWx0cz8ubGVuZ3RoIHx8IDApIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHJlc3VsdHMucmVzdWx0c1tpXTtcblxuICAgICAgICAgICAgY29uc3QgbXhFdiA9IHJlc3VsdC5jb250ZXh0LmdldEV2ZW50KCk7XG4gICAgICAgICAgICBjb25zdCByb29tSWQgPSBteEV2LmdldFJvb21JZCgpITtcbiAgICAgICAgICAgIGNvbnN0IHJvb20gPSBjbGllbnQuZ2V0Um9vbShyb29tSWQpO1xuICAgICAgICAgICAgaWYgKCFyb29tKSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgd2UgZG8gbm90IGhhdmUgdGhlIHJvb20gaW4ganMtc2RrIHN0b3JlcyB0aGVuIGhpZGUgaXQgYXMgd2UgY2Fubm90IGVhc2lseSBzaG93IGl0XG4gICAgICAgICAgICAgICAgLy8gQXMgcGVyIHRoZSBzcGVjLCBhbiBhbGwgcm9vbXMgc2VhcmNoIGNhbiBjcmVhdGUgdGhpcyBjb25kaXRpb24sXG4gICAgICAgICAgICAgICAgLy8gaXQgaGFwcGVucyB3aXRoIFNlc2hhdCBidXQgbm90IFN5bmFwc2UuXG4gICAgICAgICAgICAgICAgLy8gSXQgd2lsbCBtYWtlIHRoZSByZXN1bHQgY291bnQgbm90IG1hdGNoIHRoZSBkaXNwbGF5ZWQgY291bnQuXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhcIkhpZGluZyBzZWFyY2ggcmVzdWx0IGZyb20gYW4gdW5rbm93biByb29tXCIsIHJvb21JZCk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaGF2ZVJlbmRlcmVyRm9yRXZlbnQobXhFdiwgY2xpZW50LCByb29tQ29udGV4dC5zaG93SGlkZGVuRXZlbnRzKSkge1xuICAgICAgICAgICAgICAgIC8vIFhYWDogY2FuIHRoaXMgZXZlciBoYXBwZW4/IEl0IHdpbGwgbWFrZSB0aGUgcmVzdWx0IGNvdW50XG4gICAgICAgICAgICAgICAgLy8gbm90IG1hdGNoIHRoZSBkaXNwbGF5ZWQgY291bnQuXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzY29wZSA9PT0gU2VhcmNoU2NvcGUuQWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvb21JZCAhPT0gbGFzdFJvb21JZCkge1xuICAgICAgICAgICAgICAgICAgICByZXQucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBrZXk9e214RXYuZ2V0SWQoKSArIFwiLXJvb21cIn0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGgyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJjb21tb258cm9vbVwiKX06IHtyb29tLm5hbWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9oMj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+LFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBsYXN0Um9vbUlkID0gcm9vbUlkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVzdWx0TGluayA9IFwiIy9yb29tL1wiICsgcm9vbUlkICsgXCIvXCIgKyBteEV2LmdldElkKCk7XG5cbiAgICAgICAgICAgIC8vIG1lcmdpbmcgdHdvIHN1Y2Nlc3NpdmUgc2VhcmNoIHJlc3VsdCBpZiB0aGUgcXVlcnkgaXMgcHJlc2VudCBpbiBib3RoIG9mIHRoZW1cbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRUaW1lbGluZSA9IHJlc3VsdC5jb250ZXh0LmdldFRpbWVsaW5lKCk7XG4gICAgICAgICAgICBjb25zdCBuZXh0VGltZWxpbmUgPSBpID4gMCA/IHJlc3VsdHMucmVzdWx0c1tpIC0gMV0uY29udGV4dC5nZXRUaW1lbGluZSgpIDogW107XG5cbiAgICAgICAgICAgIGlmIChpID4gMCAmJiBjdXJyZW50VGltZWxpbmVbY3VycmVudFRpbWVsaW5lLmxlbmd0aCAtIDFdLmdldElkKCkgPT0gbmV4dFRpbWVsaW5lWzBdLmdldElkKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGlzIGlzIHRoZSBmaXJzdCBzZWFyY2hSZXN1bHQgd2UgbWVyZ2UgdGhlbiBhZGQgYWxsIHZhbHVlcyBvZiB0aGUgY3VycmVudCBzZWFyY2hSZXN1bHRcbiAgICAgICAgICAgICAgICBpZiAobWVyZ2VkVGltZWxpbmUubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IG1lcmdlZFRpbWVsaW5lLmxlbmd0aCA9PSAwID8gMCA6IDE7IGogPCByZXN1bHQuY29udGV4dC5nZXRUaW1lbGluZSgpLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXJnZWRUaW1lbGluZS5wdXNoKGN1cnJlbnRUaW1lbGluZVtqXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3VyRXZlbnRzSW5kZXhlcy5wdXNoKHJlc3VsdC5jb250ZXh0LmdldE91ckV2ZW50SW5kZXgoKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gbWVyZ2UgdGhlIGV2ZW50cyBvZiB0aGUgbmV4dCBzZWFyY2hSZXN1bHRcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMTsgaiA8IG5leHRUaW1lbGluZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBtZXJnZWRUaW1lbGluZS5wdXNoKG5leHRUaW1lbGluZVtqXSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gYWRkIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hpbmcgZXZlbnQgb2YgdGhlIG5leHQgc2VhcmNoUmVzdWx0XG4gICAgICAgICAgICAgICAgb3VyRXZlbnRzSW5kZXhlcy5wdXNoKFxuICAgICAgICAgICAgICAgICAgICBvdXJFdmVudHNJbmRleGVzW291ckV2ZW50c0luZGV4ZXMubGVuZ3RoIC0gMV0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5yZXN1bHRzW2kgLSAxXS5jb250ZXh0LmdldE91ckV2ZW50SW5kZXgoKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG1lcmdlZFRpbWVsaW5lLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgbWVyZ2VkVGltZWxpbmUgPSByZXN1bHQuY29udGV4dC5nZXRUaW1lbGluZSgpO1xuICAgICAgICAgICAgICAgIG91ckV2ZW50c0luZGV4ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICBvdXJFdmVudHNJbmRleGVzLnB1c2gocmVzdWx0LmNvbnRleHQuZ2V0T3VyRXZlbnRJbmRleCgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHBlcm1hbGlua0NyZWF0b3IgPSBwZXJtYWxpbmtDcmVhdG9ycy5nZXQocm9vbUlkKTtcbiAgICAgICAgICAgIGlmICghcGVybWFsaW5rQ3JlYXRvcikge1xuICAgICAgICAgICAgICAgIHBlcm1hbGlua0NyZWF0b3IgPSBuZXcgUm9vbVBlcm1hbGlua0NyZWF0b3Iocm9vbSk7XG4gICAgICAgICAgICAgICAgcGVybWFsaW5rQ3JlYXRvci5zdGFydCgpO1xuICAgICAgICAgICAgICAgIHBlcm1hbGlua0NyZWF0b3JzLnNldChyb29tSWQsIHBlcm1hbGlua0NyZWF0b3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXQucHVzaChcbiAgICAgICAgICAgICAgICA8U2VhcmNoUmVzdWx0VGlsZVxuICAgICAgICAgICAgICAgICAgICBrZXk9e214RXYuZ2V0SWQoKX1cbiAgICAgICAgICAgICAgICAgICAgdGltZWxpbmU9e21lcmdlZFRpbWVsaW5lfVxuICAgICAgICAgICAgICAgICAgICBvdXJFdmVudHNJbmRleGVzPXtvdXJFdmVudHNJbmRleGVzfVxuICAgICAgICAgICAgICAgICAgICBzZWFyY2hIaWdobGlnaHRzPXtoaWdobGlnaHRzID8/IFtdfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHRMaW5rPXtyZXN1bHRMaW5rfVxuICAgICAgICAgICAgICAgICAgICBwZXJtYWxpbmtDcmVhdG9yPXtwZXJtYWxpbmtDcmVhdG9yfVxuICAgICAgICAgICAgICAgICAgICBvbkhlaWdodENoYW5nZWQ9e29uSGVpZ2h0Q2hhbmdlZH1cbiAgICAgICAgICAgICAgICAvPixcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIG91ckV2ZW50c0luZGV4ZXMgPSBbXTtcbiAgICAgICAgICAgIG1lcmdlZFRpbWVsaW5lID0gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPFNjcm9sbFBhbmVsXG4gICAgICAgICAgICAgICAgcmVmPXtvblJlZn1cbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9e1wibXhfUm9vbVZpZXdfc2VhcmNoUmVzdWx0c1BhbmVsIFwiICsgY2xhc3NOYW1lfVxuICAgICAgICAgICAgICAgIG9uRmlsbFJlcXVlc3Q9e29uU2VhcmNoUmVzdWx0c0ZpbGxSZXF1ZXN0fVxuICAgICAgICAgICAgICAgIHJlc2l6ZU5vdGlmaWVyPXtyZXNpemVOb3RpZmllcn1cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bGkgY2xhc3NOYW1lPVwibXhfUm9vbVZpZXdfc2Nyb2xsaGVhZGVyXCIgLz5cbiAgICAgICAgICAgICAgICB7cmV0fVxuICAgICAgICAgICAgPC9TY3JvbGxQYW5lbD5cbiAgICAgICAgKTtcbiAgICB9LFxuKTtc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