UNPKG

matrix-react-sdk

Version:
452 lines (387 loc) 55.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); 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 = _interopRequireWildcard(require("react")); var _languageHandler = require("../../../languageHandler"); var _AccessibleTooltipButton = _interopRequireDefault(require("./AccessibleTooltipButton")); var _Keyboard = require("../../../Keyboard"); var _reactFocusLock = _interopRequireDefault(require("react-focus-lock")); var _MemberAvatar = _interopRequireDefault(require("../avatars/MemberAvatar")); var _ContextMenuTooltipButton = require("../../../accessibility/context_menu/ContextMenuTooltipButton"); var _MessageContextMenu = _interopRequireDefault(require("../context_menus/MessageContextMenu")); var _ContextMenu = require("../../structures/ContextMenu"); var _MessageTimestamp = _interopRequireDefault(require("../messages/MessageTimestamp")); var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore")); var _DateUtils = require("../../../DateUtils"); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _replaceableComponent = require("../../../utils/replaceableComponent"); var _Mouse = require("../../../utils/Mouse"); var _dec, _class, _temp; // Max scale to keep gaps around the image const MAX_SCALE = 0.95; // This is used for the buttons const ZOOM_STEP = 0.10; // This is used for mouse wheel events const ZOOM_COEFFICIENT = 0.0025; // If we have moved only this much we can zoom const ZOOM_DISTANCE = 10; let ImageView = (_dec = (0, _replaceableComponent.replaceableComponent)("views.elements.ImageView"), _dec(_class = (_temp = class ImageView extends _react.default.Component /*:: <IProps, IState>*/ { constructor(props) { super(props); (0, _defineProperty2.default)(this, "contextMenuButton", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "focusLock", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "imageWrapper", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "image", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "initX", 0); (0, _defineProperty2.default)(this, "initY", 0); (0, _defineProperty2.default)(this, "lastX", 0); (0, _defineProperty2.default)(this, "lastY", 0); (0, _defineProperty2.default)(this, "previousX", 0); (0, _defineProperty2.default)(this, "previousY", 0); (0, _defineProperty2.default)(this, "calculateZoom", () => { const image = this.image.current; const imageWrapper = this.imageWrapper.current; const zoomX = imageWrapper.clientWidth / image.naturalWidth; const zoomY = imageWrapper.clientHeight / image.naturalHeight; // If the image is smaller in both dimensions set its the zoom to 1 to // display it in its original size if (zoomX >= 1 && zoomY >= 1) { this.setState({ zoom: 1, minZoom: 1, maxZoom: 1 }); return; } // We set minZoom to the min of the zoomX and zoomY to avoid overflow in // any direction. We also multiply by MAX_SCALE to get a gap around the // image by default const minZoom = Math.min(zoomX, zoomY) * MAX_SCALE; if (this.state.zoom <= this.state.minZoom) this.setState({ zoom: minZoom }); this.setState({ minZoom: minZoom, maxZoom: 1 }); }); (0, _defineProperty2.default)(this, "onWheel", (ev /*: WheelEvent*/ ) => { ev.stopPropagation(); ev.preventDefault(); const { deltaY } = (0, _Mouse.normalizeWheelEvent)(ev); this.zoom(-(deltaY * ZOOM_COEFFICIENT)); }); (0, _defineProperty2.default)(this, "onZoomInClick", () => { this.zoom(ZOOM_STEP); }); (0, _defineProperty2.default)(this, "onZoomOutClick", () => { this.zoom(-ZOOM_STEP); }); (0, _defineProperty2.default)(this, "onKeyDown", (ev /*: KeyboardEvent*/ ) => { if (ev.key === _Keyboard.Key.ESCAPE) { ev.stopPropagation(); ev.preventDefault(); this.props.onFinished(); } }); (0, _defineProperty2.default)(this, "onRotateCounterClockwiseClick", () => { const cur = this.state.rotation; const rotationDegrees = cur - 90; this.setState({ rotation: rotationDegrees }); }); (0, _defineProperty2.default)(this, "onRotateClockwiseClick", () => { const cur = this.state.rotation; const rotationDegrees = cur + 90; this.setState({ rotation: rotationDegrees }); }); (0, _defineProperty2.default)(this, "onDownloadClick", () => { const a = document.createElement("a"); a.href = this.props.src; a.download = this.props.name; a.target = "_blank"; a.rel = "noreferrer noopener"; a.click(); }); (0, _defineProperty2.default)(this, "onOpenContextMenu", () => { this.setState({ contextMenuDisplayed: true }); }); (0, _defineProperty2.default)(this, "onCloseContextMenu", () => { this.setState({ contextMenuDisplayed: false }); }); (0, _defineProperty2.default)(this, "onPermalinkClicked", (ev /*: React.MouseEvent*/ ) => { // This allows the permalink to be opened in a new tab/window or copied as // matrix.to, but also for it to enable routing within Element when clicked. ev.preventDefault(); _dispatcher.default.dispatch({ action: 'view_room', event_id: this.props.mxEvent.getId(), highlighted: true, room_id: this.props.mxEvent.getRoomId() }); this.props.onFinished(); }); (0, _defineProperty2.default)(this, "onStartMoving", (ev /*: React.MouseEvent*/ ) => { ev.stopPropagation(); ev.preventDefault(); // Don't do anything if we pressed any // other button than the left one if (ev.button !== 0) return; // Zoom in if we are completely zoomed out if (this.state.zoom === this.state.minZoom) { this.setState({ zoom: this.state.maxZoom }); return; } this.setState({ moving: true }); this.previousX = this.state.translationX; this.previousY = this.state.translationY; this.initX = ev.pageX - this.lastX; this.initY = ev.pageY - this.lastY; }); (0, _defineProperty2.default)(this, "onMoving", (ev /*: React.MouseEvent*/ ) => { ev.stopPropagation(); ev.preventDefault(); if (!this.state.moving) return; this.lastX = ev.pageX - this.initX; this.lastY = ev.pageY - this.initY; this.setState({ translationX: this.lastX, translationY: this.lastY }); }); (0, _defineProperty2.default)(this, "onEndMoving", () => { // Zoom out if we haven't moved much if (this.state.moving === true && Math.abs(this.state.translationX - this.previousX) < ZOOM_DISTANCE && Math.abs(this.state.translationY - this.previousY) < ZOOM_DISTANCE) { this.setState({ zoom: this.state.minZoom, translationX: 0, translationY: 0 }); } this.setState({ moving: false }); }); this.state = { zoom: 0, minZoom: MAX_SCALE, maxZoom: MAX_SCALE, rotation: 0, translationX: 0, translationY: 0, moving: false, contextMenuDisplayed: false }; } // XXX: Refs to functional components componentDidMount() { // We have to use addEventListener() because the listener // needs to be passive in order to work with Chromium this.focusLock.current.addEventListener('wheel', this.onWheel, { passive: false }); // We want to recalculate zoom whenever the window's size changes window.addEventListener("resize", this.calculateZoom); // After the image loads for the first time we want to calculate the zoom this.image.current.addEventListener("load", this.calculateZoom); } componentWillUnmount() { this.focusLock.current.removeEventListener('wheel', this.onWheel); window.removeEventListener("resize", this.calculateZoom); this.image.current.removeEventListener("load", this.calculateZoom); } zoom(delta /*: number*/ ) { const newZoom = this.state.zoom + delta; if (newZoom <= this.state.minZoom) { this.setState({ zoom: this.state.minZoom, translationX: 0, translationY: 0 }); return; } if (newZoom >= this.state.maxZoom) { this.setState({ zoom: this.state.maxZoom }); return; } this.setState({ zoom: newZoom }); } renderContextMenu() { let contextMenu = null; if (this.state.contextMenuDisplayed) { contextMenu = /*#__PURE__*/_react.default.createElement(_ContextMenu.ContextMenu, (0, _extends2.default)({}, (0, _ContextMenu.aboveLeftOf)(this.contextMenuButton.current.getBoundingClientRect()), { onFinished: this.onCloseContextMenu }), /*#__PURE__*/_react.default.createElement(_MessageContextMenu.default, { mxEvent: this.props.mxEvent, permalinkCreator: this.props.permalinkCreator, onFinished: this.onCloseContextMenu, onCloseDialog: this.props.onFinished })); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, contextMenu); } render() { const showEventMeta = !!this.props.mxEvent; const zoomingDisabled = this.state.maxZoom === this.state.minZoom; let cursor; if (this.state.moving) { cursor = "grabbing"; } else if (zoomingDisabled) { cursor = "default"; } else if (this.state.zoom === this.state.minZoom) { cursor = "zoom-in"; } else { cursor = "zoom-out"; } const rotationDegrees = this.state.rotation + "deg"; const zoom = this.state.zoom; const translatePixelsX = this.state.translationX + "px"; const translatePixelsY = this.state.translationY + "px"; // The order of the values is important! // First, we translate and only then we rotate, otherwise // we would apply the translation to an already rotated // image causing it translate in the wrong direction. const style = { cursor: cursor, transition: this.state.moving ? null : "transform 200ms ease 0s", transform: `translateX(${translatePixelsX}) translateY(${translatePixelsY}) scale(${zoom}) rotate(${rotationDegrees})` }; let info; if (showEventMeta) { const mxEvent = this.props.mxEvent; const showTwelveHour = _SettingsStore.default.getValue("showTwelveHourTimestamps"); let permalink = "#"; if (this.props.permalinkCreator) { permalink = this.props.permalinkCreator.forEvent(this.props.mxEvent.getId()); } const senderName = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); const sender = /*#__PURE__*/_react.default.createElement("div", { className: "mx_ImageView_info_sender" }, senderName); const messageTimestamp = /*#__PURE__*/_react.default.createElement("a", { href: permalink, onClick: this.onPermalinkClicked, "aria-label": (0, _DateUtils.formatFullDate)(new Date(this.props.mxEvent.getTs()), showTwelveHour, false) }, /*#__PURE__*/_react.default.createElement(_MessageTimestamp.default, { showFullDate: true, showTwelveHour: showTwelveHour, ts: mxEvent.getTs(), showSeconds: false })); const avatar = /*#__PURE__*/_react.default.createElement(_MemberAvatar.default, { member: mxEvent.sender, width: 32, height: 32, viewUserOnClick: true }); info = /*#__PURE__*/_react.default.createElement("div", { className: "mx_ImageView_info_wrapper" }, avatar, /*#__PURE__*/_react.default.createElement("div", { className: "mx_ImageView_info" }, sender, messageTimestamp)); } else { // If there is no event - we're viewing an avatar, we set // an empty div here, since the panel uses space-between // and we want the same placement of elements info = /*#__PURE__*/_react.default.createElement("div", null); } let contextMenuButton; if (this.props.mxEvent) { contextMenuButton = /*#__PURE__*/_react.default.createElement(_ContextMenuTooltipButton.ContextMenuTooltipButton, { className: "mx_ImageView_button mx_ImageView_button_more", title: (0, _languageHandler._t)("Options"), onClick: this.onOpenContextMenu, inputRef: this.contextMenuButton, isExpanded: this.state.contextMenuDisplayed }); } let zoomOutButton; let zoomInButton; if (!zoomingDisabled) { zoomOutButton = /*#__PURE__*/_react.default.createElement(_AccessibleTooltipButton.default, { className: "mx_ImageView_button mx_ImageView_button_zoomOut", title: (0, _languageHandler._t)("Zoom out"), onClick: this.onZoomOutClick }); zoomInButton = /*#__PURE__*/_react.default.createElement(_AccessibleTooltipButton.default, { className: "mx_ImageView_button mx_ImageView_button_zoomIn", title: (0, _languageHandler._t)("Zoom in"), onClick: this.onZoomInClick }); } return /*#__PURE__*/_react.default.createElement(_reactFocusLock.default, { returnFocus: true, lockProps: { onKeyDown: this.onKeyDown, role: "dialog" }, className: "mx_ImageView", ref: this.focusLock }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_ImageView_panel" }, info, /*#__PURE__*/_react.default.createElement("div", { className: "mx_ImageView_toolbar" }, /*#__PURE__*/_react.default.createElement(_AccessibleTooltipButton.default, { className: "mx_ImageView_button mx_ImageView_button_rotateCCW", title: (0, _languageHandler._t)("Rotate Left"), onClick: this.onRotateCounterClockwiseClick }), /*#__PURE__*/_react.default.createElement(_AccessibleTooltipButton.default, { className: "mx_ImageView_button mx_ImageView_button_rotateCW", title: (0, _languageHandler._t)("Rotate Right"), onClick: this.onRotateClockwiseClick }), zoomOutButton, zoomInButton, /*#__PURE__*/_react.default.createElement(_AccessibleTooltipButton.default, { className: "mx_ImageView_button mx_ImageView_button_download", title: (0, _languageHandler._t)("Download"), onClick: this.onDownloadClick }), contextMenuButton, /*#__PURE__*/_react.default.createElement(_AccessibleTooltipButton.default, { className: "mx_ImageView_button mx_ImageView_button_close", title: (0, _languageHandler._t)("Close"), onClick: this.props.onFinished }), this.renderContextMenu())), /*#__PURE__*/_react.default.createElement("div", { className: "mx_ImageView_image_wrapper", ref: this.imageWrapper }, /*#__PURE__*/_react.default.createElement("img", { src: this.props.src, title: this.props.name, style: style, ref: this.image, className: "mx_ImageView_image", draggable: true, onMouseDown: this.onStartMoving, onMouseMove: this.onMoving, onMouseUp: this.onEndMoving, onMouseLeave: this.onEndMoving }))); } }, _temp)) || _class); exports.default = ImageView; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL2VsZW1lbnRzL0ltYWdlVmlldy50c3giXSwibmFtZXMiOlsiTUFYX1NDQUxFIiwiWk9PTV9TVEVQIiwiWk9PTV9DT0VGRklDSUVOVCIsIlpPT01fRElTVEFOQ0UiLCJJbWFnZVZpZXciLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJpbWFnZSIsImN1cnJlbnQiLCJpbWFnZVdyYXBwZXIiLCJ6b29tWCIsImNsaWVudFdpZHRoIiwibmF0dXJhbFdpZHRoIiwiem9vbVkiLCJjbGllbnRIZWlnaHQiLCJuYXR1cmFsSGVpZ2h0Iiwic2V0U3RhdGUiLCJ6b29tIiwibWluWm9vbSIsIm1heFpvb20iLCJNYXRoIiwibWluIiwic3RhdGUiLCJldiIsInN0b3BQcm9wYWdhdGlvbiIsInByZXZlbnREZWZhdWx0IiwiZGVsdGFZIiwia2V5IiwiS2V5IiwiRVNDQVBFIiwib25GaW5pc2hlZCIsImN1ciIsInJvdGF0aW9uIiwicm90YXRpb25EZWdyZWVzIiwiYSIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudCIsImhyZWYiLCJzcmMiLCJkb3dubG9hZCIsIm5hbWUiLCJ0YXJnZXQiLCJyZWwiLCJjbGljayIsImNvbnRleHRNZW51RGlzcGxheWVkIiwiZGlzIiwiZGlzcGF0Y2giLCJhY3Rpb24iLCJldmVudF9pZCIsIm14RXZlbnQiLCJnZXRJZCIsImhpZ2hsaWdodGVkIiwicm9vbV9pZCIsImdldFJvb21JZCIsImJ1dHRvbiIsIm1vdmluZyIsInByZXZpb3VzWCIsInRyYW5zbGF0aW9uWCIsInByZXZpb3VzWSIsInRyYW5zbGF0aW9uWSIsImluaXRYIiwicGFnZVgiLCJsYXN0WCIsImluaXRZIiwicGFnZVkiLCJsYXN0WSIsImFicyIsImNvbXBvbmVudERpZE1vdW50IiwiZm9jdXNMb2NrIiwiYWRkRXZlbnRMaXN0ZW5lciIsIm9uV2hlZWwiLCJwYXNzaXZlIiwid2luZG93IiwiY2FsY3VsYXRlWm9vbSIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsImRlbHRhIiwibmV3Wm9vbSIsInJlbmRlckNvbnRleHRNZW51IiwiY29udGV4dE1lbnUiLCJjb250ZXh0TWVudUJ1dHRvbiIsImdldEJvdW5kaW5nQ2xpZW50UmVjdCIsIm9uQ2xvc2VDb250ZXh0TWVudSIsInBlcm1hbGlua0NyZWF0b3IiLCJyZW5kZXIiLCJzaG93RXZlbnRNZXRhIiwiem9vbWluZ0Rpc2FibGVkIiwiY3Vyc29yIiwidHJhbnNsYXRlUGl4ZWxzWCIsInRyYW5zbGF0ZVBpeGVsc1kiLCJzdHlsZSIsInRyYW5zaXRpb24iLCJ0cmFuc2Zvcm0iLCJpbmZvIiwic2hvd1R3ZWx2ZUhvdXIiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJwZXJtYWxpbmsiLCJmb3JFdmVudCIsInNlbmRlck5hbWUiLCJzZW5kZXIiLCJnZXRTZW5kZXIiLCJtZXNzYWdlVGltZXN0YW1wIiwib25QZXJtYWxpbmtDbGlja2VkIiwiRGF0ZSIsImdldFRzIiwiYXZhdGFyIiwib25PcGVuQ29udGV4dE1lbnUiLCJ6b29tT3V0QnV0dG9uIiwiem9vbUluQnV0dG9uIiwib25ab29tT3V0Q2xpY2siLCJvblpvb21JbkNsaWNrIiwib25LZXlEb3duIiwicm9sZSIsIm9uUm90YXRlQ291bnRlckNsb2Nrd2lzZUNsaWNrIiwib25Sb3RhdGVDbG9ja3dpc2VDbGljayIsIm9uRG93bmxvYWRDbGljayIsIm9uU3RhcnRNb3ZpbmciLCJvbk1vdmluZyIsIm9uRW5kTW92aW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFrQkE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBR0E7Ozs7QUFFQTtBQUNBLE1BQU1BLFNBQVMsR0FBRyxJQUFsQixDLENBQ0E7O0FBQ0EsTUFBTUMsU0FBUyxHQUFHLElBQWxCLEMsQ0FD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WUFBWSxFQUFFLEtBQUtBO0FBVnZCLE1BSEosQ0F0Q0osQ0FESjtBQXlESDs7QUEvWmtFLEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMTUsIDIwMTYgT3Blbk1hcmtldCBMdGRcbkNvcHlyaWdodCAyMDE5IE1pY2hhZWwgVGVsYXR5bnNraSA8N3QzY2hndXlAZ21haWwuY29tPlxuQ29weXJpZ2h0IDIwMjAsIDIwMjEgxaBpbW9uIEJyYW5kbmVyIDxzaW1vbi5icmEuYWdAZ21haWwuY29tPlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBjcmVhdGVSZWYgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBfdCB9IGZyb20gJy4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlcic7XG5pbXBvcnQgQWNjZXNzaWJsZVRvb2x0aXBCdXR0b24gZnJvbSBcIi4vQWNjZXNzaWJsZVRvb2x0aXBCdXR0b25cIjtcbmltcG9ydCB7S2V5fSBmcm9tIFwiLi4vLi4vLi4vS2V5Ym9hcmRcIjtcbmltcG9ydCBGb2N1c0xvY2sgZnJvbSBcInJlYWN0LWZvY3VzLWxvY2tcIjtcbmltcG9ydCBNZW1iZXJBdmF0YXIgZnJvbSBcIi4uL2F2YXRhcnMvTWVtYmVyQXZhdGFyXCI7XG5pbXBvcnQge0NvbnRleHRNZW51VG9vbHRpcEJ1dHRvbn0gZnJvbSBcIi4uLy4uLy4uL2FjY2Vzc2liaWxpdHkvY29udGV4dF9tZW51L0NvbnRleHRNZW51VG9vbHRpcEJ1dHRvblwiO1xuaW1wb3J0IE1lc3NhZ2VDb250ZXh0TWVudSBmcm9tIFwiLi4vY29udGV4dF9tZW51cy9NZXNzYWdlQ29udGV4dE1lbnVcIjtcbmltcG9ydCB7YWJvdmVMZWZ0T2YsIENvbnRleHRNZW51fSBmcm9tICcuLi8uLi9zdHJ1Y3R1cmVzL0NvbnRleHRNZW51JztcbmltcG9ydCBNZXNzYWdlVGltZXN0YW1wIGZyb20gXCIuLi9tZXNzYWdlcy9NZXNzYWdlVGltZXN0YW1wXCI7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IHtmb3JtYXRGdWxsRGF0ZX0gZnJvbSBcIi4uLy4uLy4uL0RhdGVVdGlsc1wiO1xuaW1wb3J0IGRpcyBmcm9tICcuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXInO1xuaW1wb3J0IHtyZXBsYWNlYWJsZUNvbXBvbmVudH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL3JlcGxhY2VhYmxlQ29tcG9uZW50XCI7XG5pbXBvcnQge1Jvb21QZXJtYWxpbmtDcmVhdG9yfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvcGVybWFsaW5rcy9QZXJtYWxpbmtzXCJcbmltcG9ydCB7TWF0cml4RXZlbnR9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tb2RlbHMvZXZlbnRcIjtcbmltcG9ydCB7bm9ybWFsaXplV2hlZWxFdmVudH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL01vdXNlXCI7XG5cbi8vIE1heCBzY2FsZSB0byBrZWVwIGdhcHMgYXJvdW5kIHRoZSBpbWFnZVxuY29uc3QgTUFYX1NDQUxFID0gMC45NTtcbi8vIFRoaXMgaXMgdXNlZCBmb3IgdGhlIGJ1dHRvbnNcbmNvbnN0IFpPT01fU1RFUCA9IDAuMTA7XG4vLyBUaGlzIGlzIHVzZWQgZm9yIG1vdXNlIHdoZWVsIGV2ZW50c1xuY29uc3QgWk9PTV9DT0VGRklDSUVOVCA9IDAuMDAyNTtcbi8vIElmIHdlIGhhdmUgbW92ZWQgb25seSB0aGlzIG11Y2ggd2UgY2FuIHpvb21cbmNvbnN0IFpPT01fRElTVEFOQ0UgPSAxMDtcblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgc3JjOiBzdHJpbmcsIC8vIHRoZSBzb3VyY2Ugb2YgdGhlIGltYWdlIGJlaW5nIGRpc3BsYXllZFxuICAgIG5hbWU/OiBzdHJpbmcsIC8vIHRoZSBtYWluIHRpdGxlICgnbmFtZScpIGZvciB0aGUgaW1hZ2VcbiAgICBsaW5rPzogc3RyaW5nLCAvLyB0aGUgbGluayAoaWYgYW55KSBhcHBsaWVkIHRvIHRoZSBuYW1lIG9mIHRoZSBpbWFnZVxuICAgIHdpZHRoPzogbnVtYmVyLCAvLyB3aWR0aCBvZiB0aGUgaW1hZ2Ugc3JjIGluIHBpeGVsc1xuICAgIGhlaWdodD86IG51bWJlciwgLy8gaGVpZ2h0IG9mIHRoZSBpbWFnZSBzcmMgaW4gcGl4ZWxzXG4gICAgZmlsZVNpemU/OiBudW1iZXIsIC8vIHNpemUgb2YgdGhlIGltYWdlIHNyYyBpbiBieXRlc1xuICAgIG9uRmluaXNoZWQoKTogdm9pZCwgLy8gY2FsbGJhY2sgd2hlbiB0aGUgbGlnaHRib3ggaXMgZGlzbWlzc2VkXG5cbiAgICAvLyB0aGUgZXZlbnQgKGlmIGFueSkgdGhhdCB0aGUgSW1hZ2UgaXMgZGlzcGxheWluZy4gVXNlZCBmb3IgZXZlbnQtc3BlY2lmaWMgc3R1ZmYgbGlrZVxuICAgIC8vIHJlZGFjdGlvbnMsIHNlbmRlcnMsIHRpbWVzdGFtcHMgZXRjLiAgT3RoZXIgZGVzY3JpcHRvcnMgYXJlIHRha2VuIGZyb20gdGhlIGV4cGxpY2l0XG4gICAgLy8gcHJvcGVydGllcyBhYm92ZSwgd2hpY2ggbGV0IHVzIHVzZSBsaWdodGJveGVzIHRvIGRpc3BsYXkgaW1hZ2VzIHdoaWNoIGFyZW4ndCBhc3NvY2lhdGVkXG4gICAgLy8gd2l0aCBldmVudHMuXG4gICAgbXhFdmVudDogTWF0cml4RXZlbnQsXG4gICAgcGVybWFsaW5rQ3JlYXRvcjogUm9vbVBlcm1hbGlua0NyZWF0b3IsXG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIHpvb206IG51bWJlcixcbiAgICBtaW5ab29tOiBudW1iZXIsXG4gICAgbWF4Wm9vbTogbnVtYmVyLFxuICAgIHJvdGF0aW9uOiBudW1iZXIsXG4gICAgdHJhbnNsYXRpb25YOiBudW1iZXIsXG4gICAgdHJhbnNsYXRpb25ZOiBudW1iZXIsXG4gICAgbW92aW5nOiBib29sZWFuLFxuICAgIGNvbnRleHRNZW51RGlzcGxheWVkOiBib29sZWFuLFxufVxuXG5AcmVwbGFjZWFibGVDb21wb25lbnQoXCJ2aWV3cy5lbGVtZW50cy5JbWFnZVZpZXdcIilcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEltYWdlVmlldyBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIHpvb206IDAsXG4gICAgICAgICAgICBtaW5ab29tOiBNQVhfU0NBTEUsXG4gICAgICAgICAgICBtYXhab29tOiBNQVhfU0NBTEUsXG4gICAgICAgICAgICByb3RhdGlvbjogMCxcbiAgICAgICAgICAgIHRyYW5zbGF0aW9uWDogMCxcbiAgICAgICAgICAgIHRyYW5zbGF0aW9uWTogMCxcbiAgICAgICAgICAgIG1vdmluZzogZmFsc2UsXG4gICAgICAgICAgICBjb250ZXh0TWVudURpc3BsYXllZDogZmFsc2UsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gWFhYOiBSZWZzIHRvIGZ1bmN0aW9uYWwgY29tcG9uZW50c1xuICAgIHByaXZhdGUgY29udGV4dE1lbnVCdXR0b24gPSBjcmVhdGVSZWY8YW55PigpO1xuICAgIHByaXZhdGUgZm9jdXNMb2NrID0gY3JlYXRlUmVmPGFueT4oKTtcbiAgICBwcml2YXRlIGltYWdlV3JhcHBlciA9IGNyZWF0ZVJlZjxIVE1MRGl2RWxlbWVudD4oKTtcbiAgICBwcml2YXRlIGltYWdlID0gY3JlYXRlUmVmPEhUTUxJbWFnZUVsZW1lbnQ+KCk7XG5cbiAgICBwcml2YXRlIGluaXRYID0gMDtcbiAgICBwcml2YXRlIGluaXRZID0gMDtcbiAgICBwcml2YXRlIGxhc3RYID0gMDtcbiAgICBwcml2YXRlIGxhc3RZID0gMDtcbiAgICBwcml2YXRlIHByZXZpb3VzWCA9IDA7XG4gICAgcHJpdmF0ZSBwcmV2aW91c1kgPSAwO1xuXG4gICAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgICAgIC8vIFdlIGhhdmUgdG8gdXNlIGFkZEV2ZW50TGlzdGVuZXIoKSBiZWNhdXNlIHRoZSBsaXN0ZW5lclxuICAgICAgICAvLyBuZWVkcyB0byBiZSBwYXNzaXZlIGluIG9yZGVyIHRvIHdvcmsgd2l0aCBDaHJvbWl1bVxuICAgICAgICB0aGlzLmZvY3VzTG9jay5jdXJyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgdGhpcy5vbldoZWVsLCB7IHBhc3NpdmU6IGZhbHNlIH0pO1xuICAgICAgICAvLyBXZSB3YW50IHRvIHJlY2FsY3VsYXRlIHpvb20gd2hlbmV2ZXIgdGhlIHdpbmRvdydzIHNpemUgY2hhbmdlc1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInJlc2l6ZVwiLCB0aGlzLmNhbGN1bGF0ZVpvb20pO1xuICAgICAgICAvLyBBZnRlciB0aGUgaW1hZ2UgbG9hZHMgZm9yIHRoZSBmaXJzdCB0aW1lIHdlIHdhbnQgdG8gY2FsY3VsYXRlIHRoZSB6b29tXG4gICAgICAgIHRoaXMuaW1hZ2UuY3VycmVudC5hZGRFdmVudExpc3RlbmVyKFwibG9hZFwiLCB0aGlzLmNhbGN1bGF0ZVpvb20pO1xuICAgIH1cblxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgICB0aGlzLmZvY3VzTG9jay5jdXJyZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3doZWVsJywgdGhpcy5vbldoZWVsKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIiwgdGhpcy5jYWxjdWxhdGVab29tKTtcbiAgICAgICAgdGhpcy5pbWFnZS5jdXJyZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJsb2FkXCIsIHRoaXMuY2FsY3VsYXRlWm9vbSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVab29tID0gKCkgPT4ge1xuICAgICAgICBjb25zdCBpbWFnZSA9IHRoaXMuaW1hZ2UuY3VycmVudDtcbiAgICAgICAgY29uc3QgaW1hZ2VXcmFwcGVyID0gdGhpcy5pbWFnZVdyYXBwZXIuY3VycmVudDtcblxuICAgICAgICBjb25zdCB6b29tWCA9IGltYWdlV3JhcHBlci5jbGllbnRXaWR0aCAvIGltYWdlLm5hdHVyYWxXaWR0aDtcbiAgICAgICAgY29uc3Qgem9vbVkgPSBpbWFnZVdyYXBwZXIuY2xpZW50SGVpZ2h0IC8gaW1hZ2UubmF0dXJhbEhlaWdodDtcblxuICAgICAgICAvLyBJZiB0aGUgaW1hZ2UgaXMgc21hbGxlciBpbiBib3RoIGRpbWVuc2lvbnMgc2V0IGl0cyB0aGUgem9vbSB0byAxIHRvXG4gICAgICAgIC8vIGRpc3BsYXkgaXQgaW4gaXRzIG9yaWdpbmFsIHNpemVcbiAgICAgICAgaWYgKHpvb21YID49IDEgJiYgem9vbVkgPj0gMSkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgem9vbTogMSxcbiAgICAgICAgICAgICAgICBtaW5ab29tOiAxLFxuICAgICAgICAgICAgICAgIG1heFpvb206IDEsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBXZSBzZXQgbWluWm9vbSB0byB0aGUgbWluIG9mIHRoZSB6b29tWCBhbmQgem9vbVkgdG8gYXZvaWQgb3ZlcmZsb3cgaW5cbiAgICAgICAgLy8gYW55IGRpcmVjdGlvbi4gV2UgYWxzbyBtdWx0aXBseSBieSBNQVhfU0NBTEUgdG8gZ2V0IGEgZ2FwIGFyb3VuZCB0aGVcbiAgICAgICAgLy8gaW1hZ2UgYnkgZGVmYXVsdFxuICAgICAgICBjb25zdCBtaW5ab29tID0gTWF0aC5taW4oem9vbVgsIHpvb21ZKSAqIE1BWF9TQ0FMRTtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS56b29tIDw9IHRoaXMuc3RhdGUubWluWm9vbSkgdGhpcy5zZXRTdGF0ZSh7em9vbTogbWluWm9vbX0pO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIG1pblpvb206IG1pblpvb20sXG4gICAgICAgICAgICBtYXhab29tOiAxLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHpvb20oZGVsdGE6IG51bWJlcikge1xuICAgICAgICBjb25zdCBuZXdab29tID0gdGhpcy5zdGF0ZS56b29tICsgZGVsdGE7XG5cbiAgICAgICAgaWYgKG5ld1pvb20gPD0gdGhpcy5zdGF0ZS5taW5ab29tKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICB6b29tOiB0aGlzLnN0YXRlLm1pblpvb20sXG4gICAgICAgICAgICAgICAgdHJhbnNsYXRpb25YOiAwLFxuICAgICAgICAgICAgICAgIHRyYW5zbGF0aW9uWTogMCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXdab29tID49IHRoaXMuc3RhdGUubWF4Wm9vbSkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7em9vbTogdGhpcy5zdGF0ZS5tYXhab29tfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHpvb206IG5ld1pvb20sXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25XaGVlbCA9IChldjogV2hlZWxFdmVudCkgPT4ge1xuICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICBjb25zdCB7ZGVsdGFZfSA9IG5vcm1hbGl6ZVdoZWVsRXZlbnQoZXYpO1xuICAgICAgICB0aGlzLnpvb20oLShkZWx0YVkgKiBaT09NX0NPRUZGSUNJRU5UKSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25ab29tSW5DbGljayA9ICgpID0+IHtcbiAgICAgICAgdGhpcy56b29tKFpPT01fU1RFUCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25ab29tT3V0Q2xpY2sgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuem9vbSgtWk9PTV9TVEVQKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbktleURvd24gPSAoZXY6IEtleWJvYXJkRXZlbnQpID0+IHtcbiAgICAgICAgaWYgKGV2LmtleSA9PT0gS2V5LkVTQ0FQRSkge1xuICAgICAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdGhpcy5wcm9wcy5vbkZpbmlzaGVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblJvdGF0ZUNvdW50ZXJDbG9ja3dpc2VDbGljayA9ICgpID0+IHtcbiAgICAgICAgY29uc3QgY3VyID0gdGhpcy5zdGF0ZS5yb3RhdGlvbjtcbiAgICAgICAgY29uc3Qgcm90YXRpb25EZWdyZWVzID0gY3VyIC0gOTA7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyByb3RhdGlvbjogcm90YXRpb25EZWdyZWVzIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUm90YXRlQ2xvY2t3aXNlQ2xpY2sgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGN1ciA9IHRoaXMuc3RhdGUucm90YXRpb247XG4gICAgICAgIGNvbnN0IHJvdGF0aW9uRGVncmVlcyA9IGN1ciArIDkwO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgcm90YXRpb246IHJvdGF0aW9uRGVncmVlcyB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkRvd25sb2FkQ2xpY2sgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtcbiAgICAgICAgYS5ocmVmID0gdGhpcy5wcm9wcy5zcmM7XG4gICAgICAgIGEuZG93bmxvYWQgPSB0aGlzLnByb3BzLm5hbWU7XG4gICAgICAgIGEudGFyZ2V0ID0gXCJfYmxhbmtcIjtcbiAgICAgICAgYS5yZWwgPSBcIm5vcmVmZXJyZXIgbm9vcGVuZXJcIjtcbiAgICAgICAgYS5jbGljaygpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uT3BlbkNvbnRleHRNZW51ID0gKCkgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGNvbnRleHRNZW51RGlzcGxheWVkOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkNsb3NlQ29udGV4dE1lbnUgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgY29udGV4dE1lbnVEaXNwbGF5ZWQ6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblBlcm1hbGlua0NsaWNrZWQgPSAoZXY6IFJlYWN0Lk1vdXNlRXZlbnQpID0+IHtcbiAgICAgICAgLy8gVGhpcyBhbGxvd3MgdGhlIHBlcm1hbGluayB0byBiZSBvcGVuZWQgaW4gYSBuZXcgdGFiL3dpbmRvdyBvciBjb3BpZWQgYXNcbiAgICAgICAgLy8gbWF0cml4LnRvLCBidXQgYWxzbyBmb3IgaXQgdG8gZW5hYmxlIHJvdXRpbmcgd2l0aGluIEVsZW1lbnQgd2hlbiBjbGlja2VkLlxuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgYWN0aW9uOiAndmlld19yb29tJyxcbiAgICAgICAgICAgIGV2ZW50X2lkOiB0aGlzLnByb3BzLm14RXZlbnQuZ2V0SWQoKSxcbiAgICAgICAgICAgIGhpZ2hsaWdodGVkOiB0cnVlLFxuICAgICAgICAgICAgcm9vbV9pZDogdGhpcy5wcm9wcy5teEV2ZW50LmdldFJvb21JZCgpLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5wcm9wcy5vbkZpbmlzaGVkKCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25TdGFydE1vdmluZyA9IChldjogUmVhY3QuTW91c2VFdmVudCkgPT4ge1xuICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiB3ZSBwcmVzc2VkIGFueVxuICAgICAgICAvLyBvdGhlciBidXR0b24gdGhhbiB0aGUgbGVmdCBvbmVcbiAgICAgICAgaWYgKGV2LmJ1dHRvbiAhPT0gMCkgcmV0dXJuO1xuXG4gICAgICAgIC8vIFpvb20gaW4gaWYgd2UgYXJlIGNvbXBsZXRlbHkgem9vbWVkIG91dFxuICAgICAgICBpZiAodGhpcy5zdGF0ZS56b29tID09PSB0aGlzLnN0YXRlLm1pblpvb20pIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe3pvb206IHRoaXMuc3RhdGUubWF4Wm9vbX0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bW92aW5nOiB0cnVlfSk7XG4gICAgICAgIHRoaXMucHJldmlvdXNYID0gdGhpcy5zdGF0ZS50cmFuc2xhdGlvblg7XG4gICAgICAgIHRoaXMucHJldmlvdXNZID0gdGhpcy5zdGF0ZS50cmFuc2xhdGlvblk7XG4gICAgICAgIHRoaXMuaW5pdFggPSBldi5wYWdlWCAtIHRoaXMubGFzdFg7XG4gICAgICAgIHRoaXMuaW5pdFkgPSBldi5wYWdlWSAtIHRoaXMubGFzdFk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Nb3ZpbmcgPSAoZXY6IFJlYWN0Lk1vdXNlRXZlbnQpID0+IHtcbiAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLm1vdmluZykgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMubGFzdFggPSBldi5wYWdlWCAtIHRoaXMuaW5pdFg7XG4gICAgICAgIHRoaXMubGFzdFkgPSBldi5wYWdlWSAtIHRoaXMuaW5pdFk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgdHJhbnNsYXRpb25YOiB0aGlzLmxhc3RYLFxuICAgICAgICAgICAgdHJhbnNsYXRpb25ZOiB0aGlzLmxhc3RZLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkVuZE1vdmluZyA9ICgpID0+IHtcbiAgICAgICAgLy8gWm9vbSBvdXQgaWYgd2UgaGF2ZW4ndCBtb3ZlZCBtdWNoXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuc3RhdGUubW92aW5nID09PSB0cnVlICYmXG4gICAgICAgICAgICBNYXRoLmFicyh0aGlzLnN0YXRlLnRyYW5zbGF0aW9uWCAtIHRoaXMucHJldmlvdXNYKSA8IFpPT01fRElTVEFOQ0UgJiZcbiAgICAgICAgICAgIE1hdGguYWJzKHRoaXMuc3RhdGUudHJhbnNsYXRpb25ZIC0gdGhpcy5wcmV2aW91c1kpIDwgWk9PTV9ESVNUQU5DRVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIHpvb206IHRoaXMuc3RhdGUubWluWm9vbSxcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGlvblg6IDAsXG4gICAgICAgICAgICAgICAgdHJhbnNsYXRpb25ZOiAwLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bW92aW5nOiBmYWxzZX0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHJlbmRlckNvbnRleHRNZW51KCkge1xuICAgICAgICBsZXQgY29udGV4dE1lbnUgPSBudWxsO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5jb250ZXh0TWVudURpc3BsYXllZCkge1xuICAgICAgICAgICAgY29udGV4dE1lbnUgPSAoXG4gICAgICAgICAgICAgICAgPENvbnRleHRNZW51XG4gICAgICAgICAgICAgICAgICAgIHsuLi5hYm92ZUxlZnRPZih0aGlzLmNvbnRleHRNZW51QnV0dG9uLmN1cnJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkpfVxuICAgICAgICAgICAgICAgICAgICBvbkZpbmlzaGVkPXt0aGlzLm9uQ2xvc2VDb250ZXh0TWVudX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxNZXNzYWdlQ29udGV4dE1lbnVcbiAgICAgICAgICAgICAgICAgICAgICAgIG14RXZlbnQ9e3RoaXMucHJvcHMubXhFdmVudH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBlcm1hbGlua0NyZWF0b3I9e3RoaXMucHJvcHMucGVybWFsaW5rQ3JlYXRvcn1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uRmluaXNoZWQ9e3RoaXMub25DbG9zZUNvbnRleHRNZW51fVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbG9zZURpYWxvZz17dGhpcy5wcm9wcy5vbkZpbmlzaGVkfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDwvQ29udGV4dE1lbnU+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxSZWFjdC5GcmFnbWVudD5cbiAgICAgICAgICAgICAgICB7IGNvbnRleHRNZW51IH1cbiAgICAgICAgICAgIDwvUmVhY3QuRnJhZ21lbnQ+XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmVuZGVyKCkge1xuICAgICAgICBjb25zdCBzaG93RXZlbnRNZXRhID0gISF0aGlzLnByb3BzLm14RXZlbnQ7XG4gICAgICAgIGNvbnN0IHpvb21pbmdEaXNhYmxlZCA9IHRoaXMuc3RhdGUubWF4Wm9vbSA9PT0gdGhpcy5zdGF0ZS5taW5ab29tO1xuXG4gICAgICAgIGxldCBjdXJzb3I7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLm1vdmluZykge1xuICAgICAgICAgICAgY3Vyc29yPSBcImdyYWJiaW5nXCI7XG4gICAgICAgIH0gZWxzZSBpZiAoem9vbWluZ0Rpc2FibGVkKSB7XG4gICAgICAgICAgICBjdXJzb3IgPSBcImRlZmF1bHRcIjtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLnpvb20gPT09IHRoaXMuc3RhdGUubWluWm9vbSkge1xuICAgICAgICAgICAgY3Vyc29yID0gXCJ6b29tLWluXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjdXJzb3IgPSBcInpvb20tb3V0XCI7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgcm90YXRpb25EZWdyZWVzID0gdGhpcy5zdGF0ZS5yb3RhdGlvbiArIFwiZGVnXCI7XG4gICAgICAgIGNvbnN0IHpvb20gPSB0aGlzLnN0YXRlLnpvb207XG4gICAgICAgIGNvbnN0IHRyYW5zbGF0ZVBpeGVsc1ggPSB0aGlzLnN0YXRlLnRyYW5zbGF0aW9uWCArIFwicHhcIjtcbiAgICAgICAgY29uc3QgdHJhbnNsYXRlUGl4ZWxzWSA9IHRoaXMuc3RhdGUudHJhbnNsYXRpb25ZICsgXCJweFwiO1xuICAgICAgICAvLyBUaGUgb3JkZXIgb2YgdGhlIHZhbHVlcyBpcyBpbXBvcnRhbnQhXG4gICAgICAgIC8vIEZpcnN0LCB3ZSB0cmFuc2xhdGUgYW5kIG9ubHkgdGhlbiB3ZSByb3RhdGUsIG90aGVyd2lzZVxuICAgICAgICAvLyB3ZSB3b3VsZCBhcHBseSB0aGUgdHJhbnNsYXRpb24gdG8gYW4gYWxyZWFkeSByb3RhdGVkXG4gICAgICAgIC8vIGltYWdlIGNhdXNpbmcgaXQgdHJhbnNsYXRlIGluIHRoZSB3cm9uZyBkaXJlY3Rpb24uXG4gICAgICAgIGNvbnN0IHN0eWxlID0ge1xuICAgICAgICAgICAgY3Vyc29yOiBjdXJzb3IsXG4gICAgICAgICAgICB0cmFuc2l0aW9uOiB0aGlzLnN0YXRlLm1vdmluZyA/IG51bGwgOiBcInRyYW5zZm9ybSAyMDBtcyBlYXNlIDBzXCIsXG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGVYKCR7dHJhbnNsYXRlUGl4ZWxzWH0pXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVZKCR7dHJhbnNsYXRlUGl4ZWxzWX0pXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSgke3pvb219KVxuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlKCR7cm90YXRpb25EZWdyZWVzfSlgLFxuICAgICAgICB9O1xuXG4gICAgICAgIGxldCBpbmZvO1xuICAgICAgICBpZiAoc2hvd0V2ZW50TWV0YSkge1xuICAgICAgICAgICAgY29uc3QgbXhFdmVudCA9IHRoaXMucHJvcHMubXhFdmVudDtcbiAgICAgICAgICAgIGNvbnN0IHNob3dUd2VsdmVIb3VyID0gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcInNob3dUd2VsdmVIb3VyVGltZXN0YW1wc1wiKTtcbiAgICAgICAgICAgIGxldCBwZXJtYWxpbmsgPSBcIiNcIjtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLnBlcm1hbGlua0NyZWF0b3IpIHtcbiAgICAgICAgICAgICAgICBwZXJtYWxpbmsgPSB0aGlzLnByb3BzLnBlcm1hbGlua0NyZWF0b3IuZm9yRXZlbnQodGhpcy5wcm9wcy5teEV2ZW50LmdldElkKCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBzZW5kZXJOYW1lID0gbXhFdmVudC5zZW5kZXIgPyBteEV2ZW50LnNlbmRlci5uYW1lIDogbXhFdmVudC5nZXRTZW5kZXIoKTtcbiAgICAgICAgICAgIGNvbnN0IHNlbmRlciA9IChcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0ltYWdlVmlld19pbmZvX3NlbmRlclwiPlxuICAgICAgICAgICAgICAgICAgICB7c2VuZGVyTmFtZX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlVGltZXN0YW1wID0gKFxuICAgICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgICAgIGhyZWY9e3Blcm1hbGlua31cbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vblBlcm1hbGlua0NsaWNrZWR9XG4gICAgICAgICAgICAgICAgICAgIGFyaWEtbGFiZWw9e2Zvcm1hdEZ1bGxEYXRlKG5ldyBEYXRlKHRoaXMucHJvcHMubXhFdmVudC5nZXRUcygpKSwgc2hvd1R3ZWx2ZUhvdXIsIGZhbHNlKX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxNZXNzYWdlVGltZXN0YW1wXG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93RnVsbERhdGU9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93VHdlbHZlSG91cj17c2hvd1R3ZWx2ZUhvdXJ9XG4gICAgICAgICAgICAgICAgICAgICAgICB0cz17bXhFdmVudC5nZXRUcygpfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2hvd1NlY29uZHM9e2ZhbHNlfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBhdmF0YXIgPSAoXG4gICAgICAgICAgICAgICAgPE1lbWJlckF2YXRhclxuICAgICAgICAgICAgICAgICAgICBtZW1iZXI9e214RXZlbnQuc2VuZGVyfVxuICAgICAgICAgICAgICAgICAgICB3aWR0aD17MzJ9IGhlaWdodD17MzJ9XG4gICAgICAgICAgICAgICAgICAgIHZpZXdVc2VyT25DbGljaz17dHJ1ZX1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaW5mbyA9IChcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0ltYWdlVmlld19pbmZvX3dyYXBwZXJcIj5cbiAgICAgICAgICAgICAgICAgICAge2F2YXRhcn1cbiAgICAgICAgIC