UNPKG

matrix-react-sdk

Version:
269 lines (262 loc) 50.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _matrix = require("matrix-js-sdk/src/matrix"); var _logger = require("matrix-js-sdk/src/logger"); var _lodash = require("lodash"); var _languageHandler = require("../../../languageHandler"); var _DateUtils = require("../../../DateUtils"); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _actions = require("../../../dispatcher/actions"); var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore")); var _UIFeature = require("../../../settings/UIFeature"); var _Modal = _interopRequireDefault(require("../../../Modal")); var _ErrorDialog = _interopRequireDefault(require("../dialogs/ErrorDialog")); var _BugReportDialog = _interopRequireDefault(require("../dialogs/BugReportDialog")); var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton")); var _RoomTile = require("../rooms/RoomTile"); var _ContextMenu = require("../../structures/ContextMenu"); var _IconizedContextMenu = _interopRequireWildcard(require("../context_menus/IconizedContextMenu")); var _JumpToDatePicker = _interopRequireDefault(require("./JumpToDatePicker")); var _SDKContext = require("../../../contexts/SDKContext"); var _TimelineSeparator = _interopRequireDefault(require("./TimelineSeparator")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /* Copyright 2024 New Vector Ltd. Copyright 2015-2021 The Matrix.org Foundation C.I.C. Copyright 2018 Michael Telatynski <7t3chguy@gmail.com> SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ /** * Timeline separator component to render within a MessagePanel bearing the date of the ts given * * Has additional jump to date functionality when labs flag is enabled */ class DateSeparator extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "settingWatcherRef", void 0); (0, _defineProperty2.default)(this, "onContextMenuOpenClick", e => { e.preventDefault(); e.stopPropagation(); const target = e.target; this.setState({ contextMenuPosition: target.getBoundingClientRect() }); }); (0, _defineProperty2.default)(this, "onContextMenuCloseClick", () => { this.closeMenu(); }); (0, _defineProperty2.default)(this, "closeMenu", () => { this.setState({ contextMenuPosition: undefined }); }); (0, _defineProperty2.default)(this, "pickDate", async inputTimestamp => { const unixTimestamp = new Date(inputTimestamp).getTime(); const roomIdForJumpRequest = this.props.roomId; try { const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); const { event_id: eventId, origin_server_ts: originServerTs } = await cli.timestampToEvent(roomIdForJumpRequest, unixTimestamp, _matrix.Direction.Forward); _logger.logger.log(`/timestamp_to_event: ` + `found ${eventId} (${originServerTs}) for timestamp=${unixTimestamp} (looking forward)`); // Only try to navigate to the room if the user is still viewing the same // room. We don't want to jump someone back to a room after a slow request // if they've already navigated away to another room. const currentRoomId = _SDKContext.SdkContextClass.instance.roomViewStore.getRoomId(); if (currentRoomId === roomIdForJumpRequest) { _dispatcher.default.dispatch({ action: _actions.Action.ViewRoom, event_id: eventId, highlighted: true, room_id: roomIdForJumpRequest, metricsTrigger: undefined // room doesn't change }); } else { _logger.logger.debug(`No longer navigating to date in room (jump to date) because the user already switched ` + `to another room: currentRoomId=${currentRoomId}, roomIdForJumpRequest=${roomIdForJumpRequest}`); } } catch (err) { _logger.logger.error(`Error occured while trying to find event in ${roomIdForJumpRequest} ` + `at timestamp=${unixTimestamp}:`, err); // Only display an error if the user is still viewing the same room. We // don't want to worry someone about an error in a room they no longer care // about after a slow request if they've already navigated away to another // room. const currentRoomId = _SDKContext.SdkContextClass.instance.roomViewStore.getRoomId(); if (currentRoomId === roomIdForJumpRequest) { let friendlyErrorMessage = "An error occured while trying to find and jump to the given date."; let submitDebugLogsContent = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null); if (err instanceof _matrix.ConnectionError) { friendlyErrorMessage = (0, _languageHandler._t)("room|error_jump_to_date_connection"); } else if (err instanceof _matrix.MatrixError) { if (err?.errcode === "M_NOT_FOUND") { friendlyErrorMessage = (0, _languageHandler._t)("room|error_jump_to_date_not_found", { dateString: (0, _DateUtils.formatFullDateNoDay)(new Date(unixTimestamp)) }); } else { friendlyErrorMessage = (0, _languageHandler._t)("room|error_jump_to_date", { statusCode: err?.httpStatus || (0, _languageHandler._t)("room|unknown_status_code_for_timeline_jump"), errorCode: err?.errcode || (0, _languageHandler._t)("common|unavailable") }); } } else if (err instanceof _matrix.HTTPError) { friendlyErrorMessage = err.message; } else { // We only give the option to submit logs for actual errors, not network problems. submitDebugLogsContent = /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("room|error_jump_to_date_send_logs_prompt", {}, { debugLogsLink: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default // This is by default a `<div>` which we // can't nest within a `<p>` here so update // this to a be a inline anchor element. , { element: "a", kind: "link", onClick: () => this.onBugReport(err instanceof Error ? err : undefined), "data-testid": "jump-to-date-error-submit-debug-logs-button" }, sub) })); } _Modal.default.createDialog(_ErrorDialog.default, { title: (0, _languageHandler._t)("room|error_jump_to_date_title"), description: /*#__PURE__*/_react.default.createElement("div", { "data-testid": "jump-to-date-error-content" }, /*#__PURE__*/_react.default.createElement("p", null, friendlyErrorMessage), submitDebugLogsContent, /*#__PURE__*/_react.default.createElement("details", null, /*#__PURE__*/_react.default.createElement("summary", null, (0, _languageHandler._t)("room|error_jump_to_date_details")), /*#__PURE__*/_react.default.createElement("p", null, String(err)))) }); } } }); (0, _defineProperty2.default)(this, "onBugReport", err => { _Modal.default.createDialog(_BugReportDialog.default, { error: err, initialText: "Error occured while using jump to date #jump-to-date" }); }); (0, _defineProperty2.default)(this, "onLastWeekClicked", () => { const date = new Date(); date.setDate(date.getDate() - 7); this.pickDate(date); this.closeMenu(); }); (0, _defineProperty2.default)(this, "onLastMonthClicked", () => { const date = new Date(); // Month numbers are 0 - 11 and `setMonth` handles the negative rollover date.setMonth(date.getMonth() - 1, 1); this.pickDate(date); this.closeMenu(); }); (0, _defineProperty2.default)(this, "onTheBeginningClicked", () => { const date = new Date(0); this.pickDate(date); this.closeMenu(); }); (0, _defineProperty2.default)(this, "onDatePicked", dateString => { this.pickDate(dateString); this.closeMenu(); }); this.state = { jumpToDateEnabled: _SettingsStore.default.getValue("feature_jump_to_date") }; // We're using a watcher so the date headers in the timeline are updated // when the lab setting is toggled. this.settingWatcherRef = _SettingsStore.default.watchSetting("feature_jump_to_date", null, (settingName, roomId, level, newValAtLevel, newVal) => { this.setState({ jumpToDateEnabled: newVal }); }); } componentWillUnmount() { if (this.settingWatcherRef) _SettingsStore.default.unwatchSetting(this.settingWatcherRef); } get relativeTimeFormat() { return new Intl.RelativeTimeFormat((0, _languageHandler.getUserLanguage)(), { style: "long", numeric: "auto" }); } getLabel() { const date = new Date(this.props.ts); const disableRelativeTimestamps = !_SettingsStore.default.getValue(_UIFeature.UIFeature.TimelineEnableRelativeDates); // During the time the archive is being viewed, a specific day might not make sense, so we return the full date if (this.props.forExport || disableRelativeTimestamps) return (0, _DateUtils.formatFullDateNoTime)(date); const today = new Date(); const yesterday = new Date(); const days = (0, _DateUtils.getDaysArray)("long"); yesterday.setDate(today.getDate() - 1); if (date.toDateString() === today.toDateString()) { return this.relativeTimeFormat.format(0, "day"); // Today } else if (date.toDateString() === yesterday.toDateString()) { return this.relativeTimeFormat.format(-1, "day"); // Yesterday } else if (today.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) { return days[date.getDay()]; // Sunday-Saturday } else { return (0, _DateUtils.formatFullDateNoTime)(date); } } renderJumpToDateMenu() { let contextMenu; if (this.state.contextMenuPosition) { const relativeTimeFormat = this.relativeTimeFormat; contextMenu = /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.default, (0, _extends2.default)({}, (0, _RoomTile.contextMenuBelow)(this.state.contextMenuPosition), { onFinished: this.onContextMenuCloseClick }), /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOptionList, { first: true }, /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, { label: (0, _lodash.capitalize)(relativeTimeFormat.format(-1, "week")), onClick: this.onLastWeekClicked, "data-testid": "jump-to-date-last-week" }), /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, { label: (0, _lodash.capitalize)(relativeTimeFormat.format(-1, "month")), onClick: this.onLastMonthClicked, "data-testid": "jump-to-date-last-month" }), /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOption, { label: (0, _languageHandler._t)("room|jump_to_date_beginning"), onClick: this.onTheBeginningClicked, "data-testid": "jump-to-date-beginning" })), /*#__PURE__*/_react.default.createElement(_IconizedContextMenu.IconizedContextMenuOptionList, null, /*#__PURE__*/_react.default.createElement(_JumpToDatePicker.default, { ts: this.props.ts, onDatePicked: this.onDatePicked }))); } return /*#__PURE__*/_react.default.createElement(_ContextMenu.ContextMenuTooltipButton, { className: "mx_DateSeparator_jumpToDateMenu mx_DateSeparator_dateContent", "data-testid": "jump-to-date-separator-button", onClick: this.onContextMenuOpenClick, isExpanded: !!this.state.contextMenuPosition, title: (0, _languageHandler._t)("room|jump_to_date") }, /*#__PURE__*/_react.default.createElement("h2", { className: "mx_DateSeparator_dateHeading", "aria-hidden": "true" }, this.getLabel()), /*#__PURE__*/_react.default.createElement("div", { className: "mx_DateSeparator_chevron" }), contextMenu); } render() { const label = this.getLabel(); let dateHeaderContent; if (this.state.jumpToDateEnabled) { dateHeaderContent = this.renderJumpToDateMenu(); } else { dateHeaderContent = /*#__PURE__*/_react.default.createElement("div", { className: "mx_DateSeparator_dateContent" }, /*#__PURE__*/_react.default.createElement("h2", { className: "mx_DateSeparator_dateHeading", "aria-hidden": "true" }, label)); } return /*#__PURE__*/_react.default.createElement(_TimelineSeparator.default, { label: label }, dateHeaderContent); } } exports.default = DateSeparator; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9tYXRyaXgiLCJfbG9nZ2VyIiwiX2xvZGFzaCIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfRGF0ZVV0aWxzIiwiX01hdHJpeENsaWVudFBlZyIsIl9kaXNwYXRjaGVyIiwiX2FjdGlvbnMiLCJfU2V0dGluZ3NTdG9yZSIsIl9VSUZlYXR1cmUiLCJfTW9kYWwiLCJfRXJyb3JEaWFsb2ciLCJfQnVnUmVwb3J0RGlhbG9nIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfUm9vbVRpbGUiLCJfQ29udGV4dE1lbnUiLCJfSWNvbml6ZWRDb250ZXh0TWVudSIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwiX0p1bXBUb0RhdGVQaWNrZXIiLCJfU0RLQ29udGV4dCIsIl9UaW1lbGluZVNlcGFyYXRvciIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIkRhdGVTZXBhcmF0b3IiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJfZGVmaW5lUHJvcGVydHkyIiwicHJldmVudERlZmF1bHQiLCJzdG9wUHJvcGFnYXRpb24iLCJ0YXJnZXQiLCJzZXRTdGF0ZSIsImNvbnRleHRNZW51UG9zaXRpb24iLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJjbG9zZU1lbnUiLCJ1bmRlZmluZWQiLCJpbnB1dFRpbWVzdGFtcCIsInVuaXhUaW1lc3RhbXAiLCJEYXRlIiwiZ2V0VGltZSIsInJvb21JZEZvckp1bXBSZXF1ZXN0Iiwicm9vbUlkIiwiY2xpIiwiTWF0cml4Q2xpZW50UGVnIiwic2FmZUdldCIsImV2ZW50X2lkIiwiZXZlbnRJZCIsIm9yaWdpbl9zZXJ2ZXJfdHMiLCJvcmlnaW5TZXJ2ZXJUcyIsInRpbWVzdGFtcFRvRXZlbnQiLCJEaXJlY3Rpb24iLCJGb3J3YXJkIiwibG9nZ2VyIiwibG9nIiwiY3VycmVudFJvb21JZCIsIlNka0NvbnRleHRDbGFzcyIsImluc3RhbmNlIiwicm9vbVZpZXdTdG9yZSIsImdldFJvb21JZCIsImRpc3BhdGNoZXIiLCJkaXNwYXRjaCIsImFjdGlvbiIsIkFjdGlvbiIsIlZpZXdSb29tIiwiaGlnaGxpZ2h0ZWQiLCJyb29tX2lkIiwibWV0cmljc1RyaWdnZXIiLCJkZWJ1ZyIsImVyciIsImVycm9yIiwiZnJpZW5kbHlFcnJvck1lc3NhZ2UiLCJzdWJtaXREZWJ1Z0xvZ3NDb250ZW50IiwiY3JlYXRlRWxlbWVudCIsIkZyYWdtZW50IiwiQ29ubmVjdGlvbkVycm9yIiwiX3QiLCJNYXRyaXhFcnJvciIsImVycmNvZGUiLCJkYXRlU3RyaW5nIiwiZm9ybWF0RnVsbERhdGVOb0RheSIsInN0YXR1c0NvZGUiLCJodHRwU3RhdHVzIiwiZXJyb3JDb2RlIiwiSFRUUEVycm9yIiwibWVzc2FnZSIsImRlYnVnTG9nc0xpbmsiLCJzdWIiLCJlbGVtZW50Iiwia2luZCIsIm9uQ2xpY2siLCJvbkJ1Z1JlcG9ydCIsIkVycm9yIiwiTW9kYWwiLCJjcmVhdGVEaWFsb2ciLCJFcnJvckRpYWxvZyIsInRpdGxlIiwiZGVzY3JpcHRpb24iLCJTdHJpbmciLCJCdWdSZXBvcnREaWFsb2ciLCJpbml0aWFsVGV4dCIsImRhdGUiLCJzZXREYXRlIiwiZ2V0RGF0ZSIsInBpY2tEYXRlIiwic2V0TW9udGgiLCJnZXRNb250aCIsInN0YXRlIiwianVtcFRvRGF0ZUVuYWJsZWQiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJzZXR0aW5nV2F0Y2hlclJlZiIsIndhdGNoU2V0dGluZyIsInNldHRpbmdOYW1lIiwibGV2ZWwiLCJuZXdWYWxBdExldmVsIiwibmV3VmFsIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJ1bndhdGNoU2V0dGluZyIsInJlbGF0aXZlVGltZUZvcm1hdCIsIkludGwiLCJSZWxhdGl2ZVRpbWVGb3JtYXQiLCJnZXRVc2VyTGFuZ3VhZ2UiLCJzdHlsZSIsIm51bWVyaWMiLCJnZXRMYWJlbCIsInRzIiwiZGlzYWJsZVJlbGF0aXZlVGltZXN0YW1wcyIsIlVJRmVhdHVyZSIsIlRpbWVsaW5lRW5hYmxlUmVsYXRpdmVEYXRlcyIsImZvckV4cG9ydCIsImZvcm1hdEZ1bGxEYXRlTm9UaW1lIiwidG9kYXkiLCJ5ZXN0ZXJkYXkiLCJkYXlzIiwiZ2V0RGF5c0FycmF5IiwidG9EYXRlU3RyaW5nIiwiZm9ybWF0IiwiZ2V0RGF5IiwicmVuZGVySnVtcFRvRGF0ZU1lbnUiLCJjb250ZXh0TWVudSIsIl9leHRlbmRzMiIsImNvbnRleHRNZW51QmVsb3ciLCJvbkZpbmlzaGVkIiwib25Db250ZXh0TWVudUNsb3NlQ2xpY2siLCJJY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdCIsImZpcnN0IiwiSWNvbml6ZWRDb250ZXh0TWVudU9wdGlvbiIsImxhYmVsIiwiY2FwaXRhbGl6ZSIsIm9uTGFzdFdlZWtDbGlja2VkIiwib25MYXN0TW9udGhDbGlja2VkIiwib25UaGVCZWdpbm5pbmdDbGlja2VkIiwib25EYXRlUGlja2VkIiwiQ29udGV4dE1lbnVUb29sdGlwQnV0dG9uIiwiY2xhc3NOYW1lIiwib25Db250ZXh0TWVudU9wZW5DbGljayIsImlzRXhwYW5kZWQiLCJyZW5kZXIiLCJkYXRlSGVhZGVyQ29udGVudCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9tZXNzYWdlcy9EYXRlU2VwYXJhdG9yLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxNS0yMDIxIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxOCBNaWNoYWVsIFRlbGF0eW5za2kgPDd0M2NoZ3V5QGdtYWlsLmNvbT5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgRGlyZWN0aW9uLCBDb25uZWN0aW9uRXJyb3IsIE1hdHJpeEVycm9yLCBIVFRQRXJyb3IgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBjYXBpdGFsaXplIH0gZnJvbSBcImxvZGFzaFwiO1xuXG5pbXBvcnQgeyBfdCwgZ2V0VXNlckxhbmd1YWdlIH0gZnJvbSBcIi4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IHsgZm9ybWF0RnVsbERhdGVOb0RheSwgZm9ybWF0RnVsbERhdGVOb1RpbWUsIGdldERheXNBcnJheSB9IGZyb20gXCIuLi8uLi8uLi9EYXRlVXRpbHNcIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBkaXNwYXRjaGVyIGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCB7IEFjdGlvbiB9IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2FjdGlvbnNcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgeyBVSUZlYXR1cmUgfSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvVUlGZWF0dXJlXCI7XG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4uLy4uLy4uL01vZGFsXCI7XG5pbXBvcnQgRXJyb3JEaWFsb2cgZnJvbSBcIi4uL2RpYWxvZ3MvRXJyb3JEaWFsb2dcIjtcbmltcG9ydCBCdWdSZXBvcnREaWFsb2cgZnJvbSBcIi4uL2RpYWxvZ3MvQnVnUmVwb3J0RGlhbG9nXCI7XG5pbXBvcnQgQWNjZXNzaWJsZUJ1dHRvbiwgeyBCdXR0b25FdmVudCB9IGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgeyBjb250ZXh0TWVudUJlbG93IH0gZnJvbSBcIi4uL3Jvb21zL1Jvb21UaWxlXCI7XG5pbXBvcnQgeyBDb250ZXh0TWVudVRvb2x0aXBCdXR0b24gfSBmcm9tIFwiLi4vLi4vc3RydWN0dXJlcy9Db250ZXh0TWVudVwiO1xuaW1wb3J0IEljb25pemVkQ29udGV4dE1lbnUsIHtcbiAgICBJY29uaXplZENvbnRleHRNZW51T3B0aW9uLFxuICAgIEljb25pemVkQ29udGV4dE1lbnVPcHRpb25MaXN0LFxufSBmcm9tIFwiLi4vY29udGV4dF9tZW51cy9JY29uaXplZENvbnRleHRNZW51XCI7XG5pbXBvcnQgSnVtcFRvRGF0ZVBpY2tlciBmcm9tIFwiLi9KdW1wVG9EYXRlUGlja2VyXCI7XG5pbXBvcnQgeyBWaWV3Um9vbVBheWxvYWQgfSBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9WaWV3Um9vbVBheWxvYWRcIjtcbmltcG9ydCB7IFNka0NvbnRleHRDbGFzcyB9IGZyb20gXCIuLi8uLi8uLi9jb250ZXh0cy9TREtDb250ZXh0XCI7XG5pbXBvcnQgVGltZWxpbmVTZXBhcmF0b3IgZnJvbSBcIi4vVGltZWxpbmVTZXBhcmF0b3JcIjtcblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgcm9vbUlkOiBzdHJpbmc7XG4gICAgdHM6IG51bWJlcjtcbiAgICBmb3JFeHBvcnQ/OiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICBjb250ZXh0TWVudVBvc2l0aW9uPzogRE9NUmVjdDtcbiAgICBqdW1wVG9EYXRlRW5hYmxlZDogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBUaW1lbGluZSBzZXBhcmF0b3IgY29tcG9uZW50IHRvIHJlbmRlciB3aXRoaW4gYSBNZXNzYWdlUGFuZWwgYmVhcmluZyB0aGUgZGF0ZSBvZiB0aGUgdHMgZ2l2ZW5cbiAqXG4gKiBIYXMgYWRkaXRpb25hbCBqdW1wIHRvIGRhdGUgZnVuY3Rpb25hbGl0eSB3aGVuIGxhYnMgZmxhZyBpcyBlbmFibGVkXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERhdGVTZXBhcmF0b3IgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwcml2YXRlIHNldHRpbmdXYXRjaGVyUmVmPzogc3RyaW5nO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAganVtcFRvRGF0ZUVuYWJsZWQ6IFNldHRpbmdzU3RvcmUuZ2V0VmFsdWUoXCJmZWF0dXJlX2p1bXBfdG9fZGF0ZVwiKSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBXZSdyZSB1c2luZyBhIHdhdGNoZXIgc28gdGhlIGRhdGUgaGVhZGVycyBpbiB0aGUgdGltZWxpbmUgYXJlIHVwZGF0ZWRcbiAgICAgICAgLy8gd2hlbiB0aGUgbGFiIHNldHRpbmcgaXMgdG9nZ2xlZC5cbiAgICAgICAgdGhpcy5zZXR0aW5nV2F0Y2hlclJlZiA9IFNldHRpbmdzU3RvcmUud2F0Y2hTZXR0aW5nKFxuICAgICAgICAgICAgXCJmZWF0dXJlX2p1bXBfdG9fZGF0ZVwiLFxuICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgIChzZXR0aW5nTmFtZSwgcm9vbUlkLCBsZXZlbCwgbmV3VmFsQXRMZXZlbCwgbmV3VmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGp1bXBUb0RhdGVFbmFibGVkOiBuZXdWYWwgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnRXaWxsVW5tb3VudCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ1dhdGNoZXJSZWYpIFNldHRpbmdzU3RvcmUudW53YXRjaFNldHRpbmcodGhpcy5zZXR0aW5nV2F0Y2hlclJlZik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkNvbnRleHRNZW51T3BlbkNsaWNrID0gKGU6IEJ1dHRvbkV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgSFRNTEJ1dHRvbkVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBjb250ZXh0TWVudVBvc2l0aW9uOiB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Db250ZXh0TWVudUNsb3NlQ2xpY2sgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuY2xvc2VNZW51KCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgY2xvc2VNZW51ID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGNvbnRleHRNZW51UG9zaXRpb246IHVuZGVmaW5lZCxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgZ2V0IHJlbGF0aXZlVGltZUZvcm1hdCgpOiBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdCB7XG4gICAgICAgIHJldHVybiBuZXcgSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXQoZ2V0VXNlckxhbmd1YWdlKCksIHsgc3R5bGU6IFwibG9uZ1wiLCBudW1lcmljOiBcImF1dG9cIiB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldExhYmVsKCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSh0aGlzLnByb3BzLnRzKTtcbiAgICAgICAgY29uc3QgZGlzYWJsZVJlbGF0aXZlVGltZXN0YW1wcyA9ICFTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFVJRmVhdHVyZS5UaW1lbGluZUVuYWJsZVJlbGF0aXZlRGF0ZXMpO1xuXG4gICAgICAgIC8vIER1cmluZyB0aGUgdGltZSB0aGUgYXJjaGl2ZSBpcyBiZWluZyB2aWV3ZWQsIGEgc3BlY2lmaWMgZGF5IG1pZ2h0IG5vdCBtYWtlIHNlbnNlLCBzbyB3ZSByZXR1cm4gdGhlIGZ1bGwgZGF0ZVxuICAgICAgICBpZiAodGhpcy5wcm9wcy5mb3JFeHBvcnQgfHwgZGlzYWJsZVJlbGF0aXZlVGltZXN0YW1wcykgcmV0dXJuIGZvcm1hdEZ1bGxEYXRlTm9UaW1lKGRhdGUpO1xuXG4gICAgICAgIGNvbnN0IHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgeWVzdGVyZGF5ID0gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgZGF5cyA9IGdldERheXNBcnJheShcImxvbmdcIik7XG4gICAgICAgIHllc3RlcmRheS5zZXREYXRlKHRvZGF5LmdldERhdGUoKSAtIDEpO1xuXG4gICAgICAgIGlmIChkYXRlLnRvRGF0ZVN0cmluZygpID09PSB0b2RheS50b0RhdGVTdHJpbmcoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVsYXRpdmVUaW1lRm9ybWF0LmZvcm1hdCgwLCBcImRheVwiKTsgLy8gVG9kYXlcbiAgICAgICAgfSBlbHNlIGlmIChkYXRlLnRvRGF0ZVN0cmluZygpID09PSB5ZXN0ZXJkYXkudG9EYXRlU3RyaW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlbGF0aXZlVGltZUZvcm1hdC5mb3JtYXQoLTEsIFwiZGF5XCIpOyAvLyBZZXN0ZXJkYXlcbiAgICAgICAgfSBlbHNlIGlmICh0b2RheS5nZXRUaW1lKCkgLSBkYXRlLmdldFRpbWUoKSA8IDYgKiAyNCAqIDYwICogNjAgKiAxMDAwKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF5c1tkYXRlLmdldERheSgpXTsgLy8gU3VuZGF5LVNhdHVyZGF5XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0RnVsbERhdGVOb1RpbWUoZGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHBpY2tEYXRlID0gYXN5bmMgKGlucHV0VGltZXN0YW1wOiBudW1iZXIgfCBzdHJpbmcgfCBEYXRlKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGNvbnN0IHVuaXhUaW1lc3RhbXAgPSBuZXcgRGF0ZShpbnB1dFRpbWVzdGFtcCkuZ2V0VGltZSgpO1xuICAgICAgICBjb25zdCByb29tSWRGb3JKdW1wUmVxdWVzdCA9IHRoaXMucHJvcHMucm9vbUlkO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICAgICAgY29uc3QgeyBldmVudF9pZDogZXZlbnRJZCwgb3JpZ2luX3NlcnZlcl90czogb3JpZ2luU2VydmVyVHMgfSA9IGF3YWl0IGNsaS50aW1lc3RhbXBUb0V2ZW50KFxuICAgICAgICAgICAgICAgIHJvb21JZEZvckp1bXBSZXF1ZXN0LFxuICAgICAgICAgICAgICAgIHVuaXhUaW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgRGlyZWN0aW9uLkZvcndhcmQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICAgICAgICBgL3RpbWVzdGFtcF90b19ldmVudDogYCArXG4gICAgICAgICAgICAgICAgICAgIGBmb3VuZCAke2V2ZW50SWR9ICgke29yaWdpblNlcnZlclRzfSkgZm9yIHRpbWVzdGFtcD0ke3VuaXhUaW1lc3RhbXB9IChsb29raW5nIGZvcndhcmQpYCxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgdHJ5IHRvIG5hdmlnYXRlIHRvIHRoZSByb29tIGlmIHRoZSB1c2VyIGlzIHN0aWxsIHZpZXdpbmcgdGhlIHNhbWVcbiAgICAgICAgICAgIC8vIHJvb20uIFdlIGRvbid0IHdhbnQgdG8ganVtcCBzb21lb25lIGJhY2sgdG8gYSByb29tIGFmdGVyIGEgc2xvdyByZXF1ZXN0XG4gICAgICAgICAgICAvLyBpZiB0aGV5J3ZlIGFscmVhZHkgbmF2aWdhdGVkIGF3YXkgdG8gYW5vdGhlciByb29tLlxuICAgICAgICAgICAgY29uc3QgY3VycmVudFJvb21JZCA9IFNka0NvbnRleHRDbGFzcy5pbnN0YW5jZS5yb29tVmlld1N0b3JlLmdldFJvb21JZCgpO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRSb29tSWQgPT09IHJvb21JZEZvckp1bXBSZXF1ZXN0KSB7XG4gICAgICAgICAgICAgICAgZGlzcGF0Y2hlci5kaXNwYXRjaDxWaWV3Um9vbVBheWxvYWQ+KHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBBY3Rpb24uVmlld1Jvb20sXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50X2lkOiBldmVudElkLFxuICAgICAgICAgICAgICAgICAgICBoaWdobGlnaHRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgcm9vbV9pZDogcm9vbUlkRm9ySnVtcFJlcXVlc3QsXG4gICAgICAgICAgICAgICAgICAgIG1ldHJpY3NUcmlnZ2VyOiB1bmRlZmluZWQsIC8vIHJvb20gZG9lc24ndCBjaGFuZ2VcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgICBgTm8gbG9uZ2VyIG5hdmlnYXRpbmcgdG8gZGF0ZSBpbiByb29tIChqdW1wIHRvIGRhdGUpIGJlY2F1c2UgdGhlIHVzZXIgYWxyZWFkeSBzd2l0Y2hlZCBgICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGB0byBhbm90aGVyIHJvb206IGN1cnJlbnRSb29tSWQ9JHtjdXJyZW50Um9vbUlkfSwgcm9vbUlkRm9ySnVtcFJlcXVlc3Q9JHtyb29tSWRGb3JKdW1wUmVxdWVzdH1gLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgIGBFcnJvciBvY2N1cmVkIHdoaWxlIHRyeWluZyB0byBmaW5kIGV2ZW50IGluICR7cm9vbUlkRm9ySnVtcFJlcXVlc3R9IGAgK1xuICAgICAgICAgICAgICAgICAgICBgYXQgdGltZXN0YW1wPSR7dW5peFRpbWVzdGFtcH06YCxcbiAgICAgICAgICAgICAgICBlcnIsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBPbmx5IGRpc3BsYXkgYW4gZXJyb3IgaWYgdGhlIHVzZXIgaXMgc3RpbGwgdmlld2luZyB0aGUgc2FtZSByb29tLiBXZVxuICAgICAgICAgICAgLy8gZG9uJ3Qgd2FudCB0byB3b3JyeSBzb21lb25lIGFib3V0IGFuIGVycm9yIGluIGEgcm9vbSB0aGV5IG5vIGxvbmdlciBjYXJlXG4gICAgICAgICAgICAvLyBhYm91dCBhZnRlciBhIHNsb3cgcmVxdWVzdCBpZiB0aGV5J3ZlIGFscmVhZHkgbmF2aWdhdGVkIGF3YXkgdG8gYW5vdGhlclxuICAgICAgICAgICAgLy8gcm9vbS5cbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRSb29tSWQgPSBTZGtDb250ZXh0Q2xhc3MuaW5zdGFuY2Uucm9vbVZpZXdTdG9yZS5nZXRSb29tSWQoKTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50Um9vbUlkID09PSByb29tSWRGb3JKdW1wUmVxdWVzdCkge1xuICAgICAgICAgICAgICAgIGxldCBmcmllbmRseUVycm9yTWVzc2FnZSA9IFwiQW4gZXJyb3Igb2NjdXJlZCB3aGlsZSB0cnlpbmcgdG8gZmluZCBhbmQganVtcCB0byB0aGUgZ2l2ZW4gZGF0ZS5cIjtcbiAgICAgICAgICAgICAgICBsZXQgc3VibWl0RGVidWdMb2dzQ29udGVudDogSlNYLkVsZW1lbnQgPSA8PjwvPjtcbiAgICAgICAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgQ29ubmVjdGlvbkVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyaWVuZGx5RXJyb3JNZXNzYWdlID0gX3QoXCJyb29tfGVycm9yX2p1bXBfdG9fZGF0ZV9jb25uZWN0aW9uXCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyIGluc3RhbmNlb2YgTWF0cml4RXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycj8uZXJyY29kZSA9PT0gXCJNX05PVF9GT1VORFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmllbmRseUVycm9yTWVzc2FnZSA9IF90KFwicm9vbXxlcnJvcl9qdW1wX3RvX2RhdGVfbm90X2ZvdW5kXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlU3RyaW5nOiBmb3JtYXRGdWxsRGF0ZU5vRGF5KG5ldyBEYXRlKHVuaXhUaW1lc3RhbXApKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJpZW5kbHlFcnJvck1lc3NhZ2UgPSBfdChcInJvb218ZXJyb3JfanVtcF90b19kYXRlXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXNDb2RlOiBlcnI/Lmh0dHBTdGF0dXMgfHwgX3QoXCJyb29tfHVua25vd25fc3RhdHVzX2NvZGVfZm9yX3RpbWVsaW5lX2p1bXBcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb2RlOiBlcnI/LmVycmNvZGUgfHwgX3QoXCJjb21tb258dW5hdmFpbGFibGVcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXJyIGluc3RhbmNlb2YgSFRUUEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyaWVuZGx5RXJyb3JNZXNzYWdlID0gZXJyLm1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2Ugb25seSBnaXZlIHRoZSBvcHRpb24gdG8gc3VibWl0IGxvZ3MgZm9yIGFjdHVhbCBlcnJvcnMsIG5vdCBuZXR3b3JrIHByb2JsZW1zLlxuICAgICAgICAgICAgICAgICAgICBzdWJtaXREZWJ1Z0xvZ3NDb250ZW50ID0gKFxuICAgICAgICAgICAgICAgICAgICAgICAgPHA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInJvb218ZXJyb3JfanVtcF90b19kYXRlX3NlbmRfbG9nc19wcm9tcHRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlYnVnTG9nc0xpbms6IChzdWIpID0+IChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIGJ5IGRlZmF1bHQgYSBgPGRpdj5gIHdoaWNoIHdlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbid0IG5lc3Qgd2l0aGluIGEgYDxwPmAgaGVyZSBzbyB1cGRhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyB0byBhIGJlIGEgaW5saW5lIGFuY2hvciBlbGVtZW50LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50PVwiYVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJsaW5rXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17KCkgPT4gdGhpcy5vbkJ1Z1JlcG9ydChlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyciA6IHVuZGVmaW5lZCl9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwianVtcC10by1kYXRlLWVycm9yLXN1Ym1pdC1kZWJ1Zy1sb2dzLWJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coRXJyb3JEaWFsb2csIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IF90KFwicm9vbXxlcnJvcl9qdW1wX3RvX2RhdGVfdGl0bGVcIiksXG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAoXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGRhdGEtdGVzdGlkPVwianVtcC10by1kYXRlLWVycm9yLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cD57ZnJpZW5kbHlFcnJvck1lc3NhZ2V9PC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtzdWJtaXREZWJ1Z0xvZ3NDb250ZW50fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkZXRhaWxzPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3VtbWFyeT57X3QoXCJyb29tfGVycm9yX2p1bXBfdG9fZGF0ZV9kZXRhaWxzXCIpfTwvc3VtbWFyeT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+e1N0cmluZyhlcnIpfTwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2RldGFpbHM+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIG9uQnVnUmVwb3J0ID0gKGVycj86IEVycm9yKTogdm9pZCA9PiB7XG4gICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhCdWdSZXBvcnREaWFsb2csIHtcbiAgICAgICAgICAgIGVycm9yOiBlcnIsXG4gICAgICAgICAgICBpbml0aWFsVGV4dDogXCJFcnJvciBvY2N1cmVkIHdoaWxlIHVzaW5nIGp1bXAgdG8gZGF0ZSAjanVtcC10by1kYXRlXCIsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uTGFzdFdlZWtDbGlja2VkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgZGF0ZS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpIC0gNyk7XG4gICAgICAgIHRoaXMucGlja0RhdGUoZGF0ZSk7XG4gICAgICAgIHRoaXMuY2xvc2VNZW51KCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25MYXN0TW9udGhDbGlja2VkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgLy8gTW9udGggbnVtYmVycyBhcmUgMCAtIDExIGFuZCBgc2V0TW9udGhgIGhhbmRsZXMgdGhlIG5lZ2F0aXZlIHJvbGxvdmVyXG4gICAgICAgIGRhdGUuc2V0TW9udGgoZGF0ZS5nZXRNb250aCgpIC0gMSwgMSk7XG4gICAgICAgIHRoaXMucGlja0RhdGUoZGF0ZSk7XG4gICAgICAgIHRoaXMuY2xvc2VNZW51KCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25UaGVCZWdpbm5pbmdDbGlja2VkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoMCk7XG4gICAgICAgIHRoaXMucGlja0RhdGUoZGF0ZSk7XG4gICAgICAgIHRoaXMuY2xvc2VNZW51KCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25EYXRlUGlja2VkID0gKGRhdGVTdHJpbmc6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnBpY2tEYXRlKGRhdGVTdHJpbmcpO1xuICAgICAgICB0aGlzLmNsb3NlTWVudSgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHJlbmRlckp1bXBUb0RhdGVNZW51KCk6IFJlYWN0LlJlYWN0RWxlbWVudCB7XG4gICAgICAgIGxldCBjb250ZXh0TWVudTogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmNvbnRleHRNZW51UG9zaXRpb24pIHtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0aXZlVGltZUZvcm1hdCA9IHRoaXMucmVsYXRpdmVUaW1lRm9ybWF0O1xuICAgICAgICAgICAgY29udGV4dE1lbnUgPSAoXG4gICAgICAgICAgICAgICAgPEljb25pemVkQ29udGV4dE1lbnVcbiAgICAgICAgICAgICAgICAgICAgey4uLmNvbnRleHRNZW51QmVsb3codGhpcy5zdGF0ZS5jb250ZXh0TWVudVBvc2l0aW9uKX1cbiAgICAgICAgICAgICAgICAgICAgb25GaW5pc2hlZD17dGhpcy5vbkNvbnRleHRNZW51Q2xvc2VDbGlja31cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdCBmaXJzdD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxJY29uaXplZENvbnRleHRNZW51T3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e2NhcGl0YWxpemUocmVsYXRpdmVUaW1lRm9ybWF0LmZvcm1hdCgtMSwgXCJ3ZWVrXCIpKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uTGFzdFdlZWtDbGlja2VkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwianVtcC10by1kYXRlLWxhc3Qtd2Vla1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPEljb25pemVkQ29udGV4dE1lbnVPcHRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbD17Y2FwaXRhbGl6ZShyZWxhdGl2ZVRpbWVGb3JtYXQuZm9ybWF0KC0xLCBcIm1vbnRoXCIpKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uTGFzdE1vbnRoQ2xpY2tlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cImp1bXAtdG8tZGF0ZS1sYXN0LW1vbnRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICA8SWNvbml6ZWRDb250ZXh0TWVudU9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcInJvb218anVtcF90b19kYXRlX2JlZ2lubmluZ1wiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uVGhlQmVnaW5uaW5nQ2xpY2tlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cImp1bXAtdG8tZGF0ZS1iZWdpbm5pbmdcIlxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9JY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdD5cblxuICAgICAgICAgICAgICAgICAgICA8SWNvbml6ZWRDb250ZXh0TWVudU9wdGlvbkxpc3Q+XG4gICAgICAgICAgICAgICAgICAgICAgICA8SnVtcFRvRGF0ZVBpY2tlciB0cz17dGhpcy5wcm9wcy50c30gb25EYXRlUGlja2VkPXt0aGlzLm9uRGF0ZVBpY2tlZH0gLz5cbiAgICAgICAgICAgICAgICAgICAgPC9JY29uaXplZENvbnRleHRNZW51T3B0aW9uTGlzdD5cbiAgICAgICAgICAgICAgICA8L0ljb25pemVkQ29udGV4dE1lbnU+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxDb250ZXh0TWVudVRvb2x0aXBCdXR0b25cbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9EYXRlU2VwYXJhdG9yX2p1bXBUb0RhdGVNZW51IG14X0RhdGVTZXBhcmF0b3JfZGF0ZUNvbnRlbnRcIlxuICAgICAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwianVtcC10by1kYXRlLXNlcGFyYXRvci1idXR0b25cIlxuICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25Db250ZXh0TWVudU9wZW5DbGlja31cbiAgICAgICAgICAgICAgICBpc0V4cGFuZGVkPXshIXRoaXMuc3RhdGUuY29udGV4dE1lbnVQb3NpdGlvbn1cbiAgICAgICAgICAgICAgICB0aXRsZT17X3QoXCJyb29tfGp1bXBfdG9fZGF0ZVwiKX1cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8aDIgY2xhc3NOYW1lPVwibXhfRGF0ZVNlcGFyYXRvcl9kYXRlSGVhZGluZ1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICB7dGhpcy5nZXRMYWJlbCgpfVxuICAgICAgICAgICAgICAgIDwvaDI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9EYXRlU2VwYXJhdG9yX2NoZXZyb25cIiAvPlxuICAgICAgICAgICAgICAgIHtjb250ZXh0TWVudX1cbiAgICAgICAgICAgIDwvQ29udGV4dE1lbnVUb29sdGlwQnV0dG9uPlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgY29uc3QgbGFiZWwgPSB0aGlzLmdldExhYmVsKCk7XG5cbiAgICAgICAgbGV0IGRhdGVIZWFkZXJDb250ZW50OiBKU1guRWxlbWVudDtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuanVtcFRvRGF0ZUVuYWJsZWQpIHtcbiAgICAgICAgICAgIGRhdGVIZWFkZXJDb250ZW50ID0gdGhpcy5yZW5kZXJKdW1wVG9EYXRlTWVudSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0ZUhlYWRlckNvbnRlbnQgPSAoXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9EYXRlU2VwYXJhdG9yX2RhdGVDb250ZW50XCI+XG4gICAgICAgICAgICAgICAgICAgIDxoMiBjbGFzc05hbWU9XCJteF9EYXRlU2VwYXJhdG9yX2RhdGVIZWFkaW5nXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7bGFiZWx9XG4gICAgICAgICAgICAgICAgICAgIDwvaDI+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDxUaW1lbGluZVNlcGFyYXRvciBsYWJlbD17bGFiZWx9PntkYXRlSGVhZGVyQ29udGVudH08L1RpbWVsaW5lU2VwYXJhdG9yPjtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7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