matrix-react-sdk
Version:
SDK for matrix.org using React
269 lines (262 loc) • 50.1 kB
JavaScript
"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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