matrix-react-sdk
Version:
SDK for matrix.org using React
272 lines (260 loc) • 45.9 kB
JavaScript
;
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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