matrix-react-sdk
Version:
SDK for matrix.org using React
365 lines (362 loc) • 67.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _logger = require("matrix-js-sdk/src/logger");
var _classnames = _interopRequireDefault(require("classnames"));
var _BaseCard = _interopRequireDefault(require("../views/right_panel/BaseCard"));
var _RightPanelStorePhases = require("../../stores/right-panel/RightPanelStorePhases");
var _MessageComposer = _interopRequireDefault(require("../views/rooms/MessageComposer"));
var _Layout = require("../../settings/enums/Layout");
var _TimelinePanel = _interopRequireDefault(require("./TimelinePanel"));
var _dispatcher = _interopRequireDefault(require("../../dispatcher/dispatcher"));
var _actions = require("../../dispatcher/actions");
var _MatrixClientPeg = require("../../MatrixClientPeg");
var _EditorStateTransfer = _interopRequireDefault(require("../../utils/EditorStateTransfer"));
var _RoomContext = _interopRequireWildcard(require("../../contexts/RoomContext"));
var _ContentMessages = _interopRequireDefault(require("../../ContentMessages"));
var _UploadBar = _interopRequireDefault(require("./UploadBar"));
var _languageHandler = require("../../languageHandler");
var _ThreadListContextMenu = _interopRequireDefault(require("../views/context_menus/ThreadListContextMenu"));
var _RightPanelStore = _interopRequireDefault(require("../../stores/right-panel/RightPanelStore"));
var _SettingsStore = _interopRequireDefault(require("../../settings/SettingsStore"));
var _FileDropTarget = _interopRequireDefault(require("./FileDropTarget"));
var _KeyBindingsManager = require("../../KeyBindingsManager");
var _KeyboardShortcuts = require("../../accessibility/KeyboardShortcuts");
var _Measured = _interopRequireDefault(require("../views/elements/Measured"));
var _PosthogTrackers = _interopRequireDefault(require("../../PosthogTrackers"));
var _Spinner = _interopRequireDefault(require("../views/elements/Spinner"));
var _ComposerInsertPayload = require("../../dispatcher/payloads/ComposerInsertPayload");
var _Heading = _interopRequireDefault(require("../views/typography/Heading"));
var _SDKContext = require("../../contexts/SDKContext");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /*
Copyright 2024 New Vector Ltd.
Copyright 2021-2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
class ThreadView extends _react.default.Component {
constructor(props, context) {
super(props, context);
(0, _defineProperty2.default)(this, "dispatcherRef", null);
(0, _defineProperty2.default)(this, "layoutWatcherRef", void 0);
(0, _defineProperty2.default)(this, "timelinePanel", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "card", /*#__PURE__*/(0, _react.createRef)());
// Set by setEventId in ctor.
(0, _defineProperty2.default)(this, "eventId", void 0);
(0, _defineProperty2.default)(this, "onAction", payload => {
if (payload.phase == _RightPanelStorePhases.RightPanelPhases.ThreadView && payload.event) {
this.setupThread(payload.event);
}
switch (payload.action) {
case _actions.Action.ComposerInsert:
{
if (payload.composerType) break;
if (payload.timelineRenderingType !== _RoomContext.TimelineRenderingType.Thread) break;
// re-dispatch to the correct composer
_dispatcher.default.dispatch(_objectSpread(_objectSpread({}, payload), {}, {
composerType: this.state.editState ? _ComposerInsertPayload.ComposerType.Edit : _ComposerInsertPayload.ComposerType.Send
}));
break;
}
case _actions.Action.EditEvent:
// Quit early if it's not a thread context
if (payload.timelineRenderingType !== _RoomContext.TimelineRenderingType.Thread) return;
// Quit early if that's not a thread event
if (payload.event && !payload.event.getThread()) return;
this.setState({
editState: payload.event ? new _EditorStateTransfer.default(payload.event) : undefined
}, () => {
if (payload.event) {
this.timelinePanel.current?.scrollToEventIfNeeded(payload.event.getId());
}
});
break;
case "reply_to_event":
if (payload.context === _RoomContext.TimelineRenderingType.Thread) {
this.setState({
replyToEvent: payload.event
});
}
break;
default:
break;
}
});
(0, _defineProperty2.default)(this, "setupThread", mxEv => {
/** presence of event Id has been ensured by {@link setEventId} */
const eventId = mxEv.getId();
let thread = this.props.room.getThread(eventId);
if (!thread) {
const events = [];
// if the event is still being sent, don't include it in the Thread yet - otherwise the timeline panel
// will attempt to show it twice (once as a regular event, once as a pending event) and everything will
// blow up
if (mxEv.status === null) events.push(mxEv);
thread = this.props.room.createThread(eventId, mxEv, events, true);
}
this.updateThread(thread);
});
(0, _defineProperty2.default)(this, "onNewThread", thread => {
if (thread.id === this.props.mxEvent.getId()) {
this.setupThread(this.props.mxEvent);
}
});
(0, _defineProperty2.default)(this, "updateThreadRelation", () => {
this.setState({
lastReply: this.threadLastReply
});
});
(0, _defineProperty2.default)(this, "updateThread", thread => {
if (this.state.thread === thread) return;
this.setupThreadListeners(thread, this.state.thread);
if (thread) {
this.setState({
thread,
lastReply: this.threadLastReply
}, async () => this.postThreadUpdate(thread));
}
});
(0, _defineProperty2.default)(this, "resetJumpToEvent", event => {
if (this.props.initialEvent && this.props.initialEventScrollIntoView && event === this.props.initialEvent?.getId()) {
_dispatcher.default.dispatch({
action: _actions.Action.ViewRoom,
room_id: this.props.room.roomId,
event_id: this.props.initialEvent?.getId(),
highlighted: this.props.isInitialEventHighlighted,
scroll_into_view: false,
replyingToEvent: this.state.replyToEvent,
metricsTrigger: undefined // room doesn't change
});
}
});
(0, _defineProperty2.default)(this, "onMeasurement", narrow => {
this.setState({
narrow
});
});
(0, _defineProperty2.default)(this, "onKeyDown", ev => {
let handled = false;
const action = (0, _KeyBindingsManager.getKeyBindingsManager)().getRoomAction(ev);
switch (action) {
case _KeyboardShortcuts.KeyBindingAction.UploadFile:
{
_dispatcher.default.dispatch({
action: "upload_file",
context: _RoomContext.TimelineRenderingType.Thread
}, true);
handled = true;
break;
}
}
if (handled) {
ev.stopPropagation();
ev.preventDefault();
}
});
(0, _defineProperty2.default)(this, "onFileDrop", dataTransfer => {
const roomId = this.props.mxEvent.getRoomId();
if (roomId) {
_ContentMessages.default.sharedInstance().sendContentListToRoom(Array.from(dataTransfer.files), roomId, this.threadRelation, _MatrixClientPeg.MatrixClientPeg.safeGet(), _RoomContext.TimelineRenderingType.Thread);
} else {
console.warn("Unknwon roomId for event", this.props.mxEvent);
}
});
(0, _defineProperty2.default)(this, "renderThreadViewHeader", () => {
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_BaseCard_header_title"
}, /*#__PURE__*/_react.default.createElement(_Heading.default, {
size: "4",
className: "mx_BaseCard_header_title_heading"
}, (0, _languageHandler._t)("common|thread")), /*#__PURE__*/_react.default.createElement(_ThreadListContextMenu.default, {
mxEvent: this.props.mxEvent,
permalinkCreator: this.props.permalinkCreator
}));
});
this.setEventId(this.props.mxEvent);
const _thread = this.props.room.getThread(this.eventId) ?? undefined;
this.setupThreadListeners(_thread);
this.state = {
layout: _SettingsStore.default.getValue("layout"),
narrow: false,
thread: _thread,
lastReply: _thread?.lastReply(ev => {
return ev.isRelation(_matrix.THREAD_RELATION_TYPE.name) && !ev.status;
})
};
this.layoutWatcherRef = _SettingsStore.default.watchSetting("layout", null, (...[,,, value]) => this.setState({
layout: value
}));
}
componentDidMount() {
if (this.state.thread) {
this.postThreadUpdate(this.state.thread);
}
this.setupThread(this.props.mxEvent);
this.dispatcherRef = _dispatcher.default.register(this.onAction);
this.props.room.on(_matrix.ThreadEvent.New, this.onNewThread);
}
componentWillUnmount() {
if (this.dispatcherRef) _dispatcher.default.unregister(this.dispatcherRef);
const roomId = this.props.mxEvent.getRoomId();
_SettingsStore.default.unwatchSetting(this.layoutWatcherRef);
const hasRoomChanged = _SDKContext.SdkContextClass.instance.roomViewStore.getRoomId() !== roomId;
if (this.props.initialEvent && !hasRoomChanged) {
_dispatcher.default.dispatch({
action: _actions.Action.ViewRoom,
room_id: this.props.room.roomId,
metricsTrigger: undefined // room doesn't change
});
}
_dispatcher.default.dispatch({
action: _actions.Action.ViewThread,
thread_id: null
});
this.state.thread?.off(_matrix.ThreadEvent.NewReply, this.updateThreadRelation);
this.props.room.off(_matrix.RoomEvent.LocalEchoUpdated, this.updateThreadRelation);
this.props.room.removeListener(_matrix.ThreadEvent.New, this.onNewThread);
}
componentDidUpdate(prevProps) {
if (prevProps.mxEvent !== this.props.mxEvent) {
this.setEventId(this.props.mxEvent);
this.setupThread(this.props.mxEvent);
}
if (prevProps.room !== this.props.room) {
_RightPanelStore.default.instance.setCard({
phase: _RightPanelStorePhases.RightPanelPhases.RoomSummary
});
}
}
setEventId(event) {
if (!event.getId()) {
throw new Error("Got thread event without id");
}
this.eventId = event.getId();
}
get threadLastReply() {
return this.state.thread?.lastReply(ev => {
return ev.isRelation(_matrix.THREAD_RELATION_TYPE.name) && !ev.status;
}) ?? undefined;
}
async postThreadUpdate(thread) {
_dispatcher.default.dispatch({
action: _actions.Action.ViewThread,
thread_id: thread.id
});
thread.emit(_matrix.ThreadEvent.ViewThread);
this.updateThreadRelation();
this.timelinePanel.current?.refreshTimeline(this.props.initialEvent?.getId());
}
setupThreadListeners(thread, oldThread) {
if (oldThread) {
this.state.thread?.off(_matrix.ThreadEvent.NewReply, this.updateThreadRelation);
this.props.room.off(_matrix.RoomEvent.LocalEchoUpdated, this.updateThreadRelation);
}
if (thread) {
thread.on(_matrix.ThreadEvent.NewReply, this.updateThreadRelation);
this.props.room.on(_matrix.RoomEvent.LocalEchoUpdated, this.updateThreadRelation);
}
}
get threadRelation() {
const relation = {
rel_type: _matrix.THREAD_RELATION_TYPE.name,
event_id: this.state.thread?.id,
is_falling_back: true
};
const fallbackEventId = this.state.lastReply?.getId() ?? this.state.thread?.id;
if (fallbackEventId) {
relation["m.in_reply_to"] = {
event_id: fallbackEventId
};
}
return relation;
}
render() {
const highlightedEventId = this.props.isInitialEventHighlighted ? this.props.initialEvent?.getId() : undefined;
const threadRelation = this.threadRelation;
let timeline;
if (this.state.thread) {
if (this.props.initialEvent && this.props.initialEvent.getRoomId() !== this.state.thread.roomId) {
_logger.logger.warn("ThreadView attempting to render TimelinePanel with mismatched initialEvent", this.state.thread.roomId, this.props.initialEvent.getRoomId(), this.props.initialEvent.getId());
}
timeline = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_FileDropTarget.default, {
parent: this.card.current,
onFileDrop: this.onFileDrop
}), /*#__PURE__*/_react.default.createElement(_TimelinePanel.default, {
key: this.state.thread.id,
ref: this.timelinePanel,
showReadReceipts: this.context.showReadReceipts,
manageReadReceipts: true,
manageReadMarkers: true,
sendReadReceiptOnLoad: true,
timelineSet: this.state.thread.timelineSet,
showUrlPreview: this.context.showUrlPreview
// ThreadView doesn't support IRC layout at this time
,
layout: this.state.layout === _Layout.Layout.Bubble ? _Layout.Layout.Bubble : _Layout.Layout.Group,
hideThreadedMessages: false,
hidden: false,
showReactions: true,
className: "mx_RoomView_messagePanel",
permalinkCreator: this.props.permalinkCreator,
membersLoaded: true,
editState: this.state.editState,
eventId: this.props.initialEvent?.getId(),
highlightedEventId: highlightedEventId,
eventScrollIntoView: this.props.initialEventScrollIntoView,
onEventScrolledIntoView: this.resetJumpToEvent
}));
} else {
timeline = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_RoomView_messagePanelSpinner"
}, /*#__PURE__*/_react.default.createElement(_Spinner.default, null));
}
return /*#__PURE__*/_react.default.createElement(_RoomContext.default.Provider, {
value: _objectSpread(_objectSpread({}, this.context), {}, {
timelineRenderingType: _RoomContext.TimelineRenderingType.Thread,
threadId: this.state.thread?.id,
liveTimeline: this.state?.thread?.timelineSet?.getLiveTimeline(),
narrow: this.state.narrow
})
}, /*#__PURE__*/_react.default.createElement(_BaseCard.default, {
className: (0, _classnames.default)("mx_ThreadView mx_ThreadPanel", {
mx_ThreadView_narrow: this.state.narrow
}),
onClose: this.props.onClose,
withoutScrollContainer: true,
header: this.renderThreadViewHeader(),
ref: this.card,
onKeyDown: this.onKeyDown,
onBack: ev => {
_PosthogTrackers.default.trackInteraction("WebThreadViewBackButton", ev);
}
}, this.card.current && /*#__PURE__*/_react.default.createElement(_Measured.default, {
sensor: this.card.current,
onMeasurement: this.onMeasurement
}), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_ThreadView_timelinePanelWrapper"
}, timeline), _ContentMessages.default.sharedInstance().getCurrentUploads(threadRelation).length > 0 && /*#__PURE__*/_react.default.createElement(_UploadBar.default, {
room: this.props.room,
relation: threadRelation
}), this.state.thread?.timelineSet && /*#__PURE__*/_react.default.createElement(_MessageComposer.default, {
room: this.props.room,
resizeNotifier: this.props.resizeNotifier,
relation: threadRelation,
replyToEvent: this.state.replyToEvent,
permalinkCreator: this.props.permalinkCreator,
e2eStatus: this.props.e2eStatus,
compact: true
})));
}
}
exports.default = ThreadView;
(0, _defineProperty2.default)(ThreadView, "contextType", _RoomContext.default);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbWF0cml4IiwiX2xvZ2dlciIsIl9jbGFzc25hbWVzIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9CYXNlQ2FyZCIsIl9SaWdodFBhbmVsU3RvcmVQaGFzZXMiLCJfTWVzc2FnZUNvbXBvc2VyIiwiX0xheW91dCIsIl9UaW1lbGluZVBhbmVsIiwiX2Rpc3BhdGNoZXIiLCJfYWN0aW9ucyIsIl9NYXRyaXhDbGllbnRQZWciLCJfRWRpdG9yU3RhdGVUcmFuc2ZlciIsIl9Sb29tQ29udGV4dCIsIl9Db250ZW50TWVzc2FnZXMiLCJfVXBsb2FkQmFyIiwiX2xhbmd1YWdlSGFuZGxlciIsIl9UaHJlYWRMaXN0Q29udGV4dE1lbnUiLCJfUmlnaHRQYW5lbFN0b3JlIiwiX1NldHRpbmdzU3RvcmUiLCJfRmlsZURyb3BUYXJnZXQiLCJfS2V5QmluZGluZ3NNYW5hZ2VyIiwiX0tleWJvYXJkU2hvcnRjdXRzIiwiX01lYXN1cmVkIiwiX1Bvc3Rob2dUcmFja2VycyIsIl9TcGlubmVyIiwiX0NvbXBvc2VySW5zZXJ0UGF5bG9hZCIsIl9IZWFkaW5nIiwiX1NES0NvbnRleHQiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJvd25LZXlzIiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJUaHJlYWRWaWV3IiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiY29udGV4dCIsImNyZWF0ZVJlZiIsInBheWxvYWQiLCJwaGFzZSIsIlJpZ2h0UGFuZWxQaGFzZXMiLCJldmVudCIsInNldHVwVGhyZWFkIiwiYWN0aW9uIiwiQWN0aW9uIiwiQ29tcG9zZXJJbnNlcnQiLCJjb21wb3NlclR5cGUiLCJ0aW1lbGluZVJlbmRlcmluZ1R5cGUiLCJUaW1lbGluZVJlbmRlcmluZ1R5cGUiLCJUaHJlYWQiLCJkaXMiLCJkaXNwYXRjaCIsInN0YXRlIiwiZWRpdFN0YXRlIiwiQ29tcG9zZXJUeXBlIiwiRWRpdCIsIlNlbmQiLCJFZGl0RXZlbnQiLCJnZXRUaHJlYWQiLCJzZXRTdGF0ZSIsIkVkaXRvclN0YXRlVHJhbnNmZXIiLCJ1bmRlZmluZWQiLCJ0aW1lbGluZVBhbmVsIiwiY3VycmVudCIsInNjcm9sbFRvRXZlbnRJZk5lZWRlZCIsImdldElkIiwicmVwbHlUb0V2ZW50IiwibXhFdiIsImV2ZW50SWQiLCJ0aHJlYWQiLCJyb29tIiwiZXZlbnRzIiwic3RhdHVzIiwiY3JlYXRlVGhyZWFkIiwidXBkYXRlVGhyZWFkIiwiaWQiLCJteEV2ZW50IiwibGFzdFJlcGx5IiwidGhyZWFkTGFzdFJlcGx5Iiwic2V0dXBUaHJlYWRMaXN0ZW5lcnMiLCJwb3N0VGhyZWFkVXBkYXRlIiwiaW5pdGlhbEV2ZW50IiwiaW5pdGlhbEV2ZW50U2Nyb2xsSW50b1ZpZXciLCJWaWV3Um9vbSIsInJvb21faWQiLCJyb29tSWQiLCJldmVudF9pZCIsImhpZ2hsaWdodGVkIiwiaXNJbml0aWFsRXZlbnRIaWdobGlnaHRlZCIsInNjcm9sbF9pbnRvX3ZpZXciLCJyZXBseWluZ1RvRXZlbnQiLCJtZXRyaWNzVHJpZ2dlciIsIm5hcnJvdyIsImV2IiwiaGFuZGxlZCIsImdldEtleUJpbmRpbmdzTWFuYWdlciIsImdldFJvb21BY3Rpb24iLCJLZXlCaW5kaW5nQWN0aW9uIiwiVXBsb2FkRmlsZSIsInN0b3BQcm9wYWdhdGlvbiIsInByZXZlbnREZWZhdWx0IiwiZGF0YVRyYW5zZmVyIiwiZ2V0Um9vbUlkIiwiQ29udGVudE1lc3NhZ2VzIiwic2hhcmVkSW5zdGFuY2UiLCJzZW5kQ29udGVudExpc3RUb1Jvb20iLCJBcnJheSIsImZyb20iLCJmaWxlcyIsInRocmVhZFJlbGF0aW9uIiwiTWF0cml4Q2xpZW50UGVnIiwic2FmZUdldCIsImNvbnNvbGUiLCJ3YXJuIiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsInNpemUiLCJfdCIsInBlcm1hbGlua0NyZWF0b3IiLCJzZXRFdmVudElkIiwibGF5b3V0IiwiU2V0dGluZ3NTdG9yZSIsImdldFZhbHVlIiwiaXNSZWxhdGlvbiIsIlRIUkVBRF9SRUxBVElPTl9UWVBFIiwibmFtZSIsImxheW91dFdhdGNoZXJSZWYiLCJ3YXRjaFNldHRpbmciLCJ2YWx1ZSIsImNvbXBvbmVudERpZE1vdW50IiwiZGlzcGF0Y2hlclJlZiIsInJlZ2lzdGVyIiwib25BY3Rpb24iLCJvbiIsIlRocmVhZEV2ZW50IiwiTmV3Iiwib25OZXdUaHJlYWQiLCJjb21wb25lbnRXaWxsVW5tb3VudCIsInVucmVnaXN0ZXIiLCJ1bndhdGNoU2V0dGluZyIsImhhc1Jvb21DaGFuZ2VkIiwiU2RrQ29udGV4dENsYXNzIiwiaW5zdGFuY2UiLCJyb29tVmlld1N0b3JlIiwiVmlld1RocmVhZCIsInRocmVhZF9pZCIsIm9mZiIsIk5ld1JlcGx5IiwidXBkYXRlVGhyZWFkUmVsYXRpb24iLCJSb29tRXZlbnQiLCJMb2NhbEVjaG9VcGRhdGVkIiwicmVtb3ZlTGlzdGVuZXIiLCJjb21wb25lbnREaWRVcGRhdGUiLCJwcmV2UHJvcHMiLCJSaWdodFBhbmVsU3RvcmUiLCJzZXRDYXJkIiwiUm9vbVN1bW1hcnkiLCJFcnJvciIsImVtaXQiLCJyZWZyZXNoVGltZWxpbmUiLCJvbGRUaHJlYWQiLCJyZWxhdGlvbiIsInJlbF90eXBlIiwiaXNfZmFsbGluZ19iYWNrIiwiZmFsbGJhY2tFdmVudElkIiwicmVuZGVyIiwiaGlnaGxpZ2h0ZWRFdmVudElkIiwidGltZWxpbmUiLCJsb2dnZXIiLCJGcmFnbWVudCIsInBhcmVudCIsImNhcmQiLCJvbkZpbGVEcm9wIiwia2V5IiwicmVmIiwic2hvd1JlYWRSZWNlaXB0cyIsIm1hbmFnZVJlYWRSZWNlaXB0cyIsIm1hbmFnZVJlYWRNYXJrZXJzIiwic2VuZFJlYWRSZWNlaXB0T25Mb2FkIiwidGltZWxpbmVTZXQiLCJzaG93VXJsUHJldmlldyIsIkxheW91dCIsIkJ1YmJsZSIsIkdyb3VwIiwiaGlkZVRocmVhZGVkTWVzc2FnZXMiLCJoaWRkZW4iLCJzaG93UmVhY3Rpb25zIiwibWVtYmVyc0xvYWRlZCIsImV2ZW50U2Nyb2xsSW50b1ZpZXciLCJvbkV2ZW50U2Nyb2xsZWRJbnRvVmlldyIsInJlc2V0SnVtcFRvRXZlbnQiLCJQcm92aWRlciIsInRocmVhZElkIiwibGl2ZVRpbWVsaW5lIiwiZ2V0TGl2ZVRpbWVsaW5lIiwiY2xhc3NOYW1lcyIsIm14X1RocmVhZFZpZXdfbmFycm93Iiwib25DbG9zZSIsIndpdGhvdXRTY3JvbGxDb250YWluZXIiLCJoZWFkZXIiLCJyZW5kZXJUaHJlYWRWaWV3SGVhZGVyIiwib25LZXlEb3duIiwib25CYWNrIiwiUG9zdGhvZ1RyYWNrZXJzIiwidHJhY2tJbnRlcmFjdGlvbiIsInNlbnNvciIsIm9uTWVhc3VyZW1lbnQiLCJnZXRDdXJyZW50VXBsb2FkcyIsInJlc2l6ZU5vdGlmaWVyIiwiZTJlU3RhdHVzIiwiY29tcGFjdCIsImV4cG9ydHMiLCJSb29tQ29udGV4dCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3N0cnVjdHVyZXMvVGhyZWFkVmlldy50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjEtMjAyMyBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgY3JlYXRlUmVmLCBLZXlib2FyZEV2ZW50IH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1xuICAgIFRocmVhZCxcbiAgICBUSFJFQURfUkVMQVRJT05fVFlQRSxcbiAgICBUaHJlYWRFdmVudCxcbiAgICBSb29tLFxuICAgIFJvb21FdmVudCxcbiAgICBJRXZlbnRSZWxhdGlvbixcbiAgICBNYXRyaXhFdmVudCxcbn0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuaW1wb3J0IGNsYXNzTmFtZXMgZnJvbSBcImNsYXNzbmFtZXNcIjtcblxuaW1wb3J0IEJhc2VDYXJkIGZyb20gXCIuLi92aWV3cy9yaWdodF9wYW5lbC9CYXNlQ2FyZFwiO1xuaW1wb3J0IHsgUmlnaHRQYW5lbFBoYXNlcyB9IGZyb20gXCIuLi8uLi9zdG9yZXMvcmlnaHQtcGFuZWwvUmlnaHRQYW5lbFN0b3JlUGhhc2VzXCI7XG5pbXBvcnQgUmVzaXplTm90aWZpZXIgZnJvbSBcIi4uLy4uL3V0aWxzL1Jlc2l6ZU5vdGlmaWVyXCI7XG5pbXBvcnQgTWVzc2FnZUNvbXBvc2VyIGZyb20gXCIuLi92aWV3cy9yb29tcy9NZXNzYWdlQ29tcG9zZXJcIjtcbmltcG9ydCB7IFJvb21QZXJtYWxpbmtDcmVhdG9yIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3Blcm1hbGlua3MvUGVybWFsaW5rc1wiO1xuaW1wb3J0IHsgTGF5b3V0IH0gZnJvbSBcIi4uLy4uL3NldHRpbmdzL2VudW1zL0xheW91dFwiO1xuaW1wb3J0IFRpbWVsaW5lUGFuZWwgZnJvbSBcIi4vVGltZWxpbmVQYW5lbFwiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBBY3Rpb25QYXlsb2FkIH0gZnJvbSBcIi4uLy4uL2Rpc3BhdGNoZXIvcGF5bG9hZHNcIjtcbmltcG9ydCB7IEFjdGlvbiB9IGZyb20gXCIuLi8uLi9kaXNwYXRjaGVyL2FjdGlvbnNcIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCB7IEUyRVN0YXR1cyB9IGZyb20gXCIuLi8uLi91dGlscy9TaGllbGRVdGlsc1wiO1xuaW1wb3J0IEVkaXRvclN0YXRlVHJhbnNmZXIgZnJvbSBcIi4uLy4uL3V0aWxzL0VkaXRvclN0YXRlVHJhbnNmZXJcIjtcbmltcG9ydCBSb29tQ29udGV4dCwgeyBUaW1lbGluZVJlbmRlcmluZ1R5cGUgfSBmcm9tIFwiLi4vLi4vY29udGV4dHMvUm9vbUNvbnRleHRcIjtcbmltcG9ydCBDb250ZW50TWVzc2FnZXMgZnJvbSBcIi4uLy4uL0NvbnRlbnRNZXNzYWdlc1wiO1xuaW1wb3J0IFVwbG9hZEJhciBmcm9tIFwiLi9VcGxvYWRCYXJcIjtcbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IFRocmVhZExpc3RDb250ZXh0TWVudSBmcm9tIFwiLi4vdmlld3MvY29udGV4dF9tZW51cy9UaHJlYWRMaXN0Q29udGV4dE1lbnVcIjtcbmltcG9ydCBSaWdodFBhbmVsU3RvcmUgZnJvbSBcIi4uLy4uL3N0b3Jlcy9yaWdodC1wYW5lbC9SaWdodFBhbmVsU3RvcmVcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgeyBWaWV3Um9vbVBheWxvYWQgfSBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9WaWV3Um9vbVBheWxvYWRcIjtcbmltcG9ydCBGaWxlRHJvcFRhcmdldCBmcm9tIFwiLi9GaWxlRHJvcFRhcmdldFwiO1xuaW1wb3J0IHsgZ2V0S2V5QmluZGluZ3NNYW5hZ2VyIH0gZnJvbSBcIi4uLy4uL0tleUJpbmRpbmdzTWFuYWdlclwiO1xuaW1wb3J0IHsgS2V5QmluZGluZ0FjdGlvbiB9IGZyb20gXCIuLi8uLi9hY2Nlc3NpYmlsaXR5L0tleWJvYXJkU2hvcnRjdXRzXCI7XG5pbXBvcnQgTWVhc3VyZWQgZnJvbSBcIi4uL3ZpZXdzL2VsZW1lbnRzL01lYXN1cmVkXCI7XG5pbXBvcnQgUG9zdGhvZ1RyYWNrZXJzIGZyb20gXCIuLi8uLi9Qb3N0aG9nVHJhY2tlcnNcIjtcbmltcG9ydCB7IEJ1dHRvbkV2ZW50IH0gZnJvbSBcIi4uL3ZpZXdzL2VsZW1lbnRzL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCBTcGlubmVyIGZyb20gXCIuLi92aWV3cy9lbGVtZW50cy9TcGlubmVyXCI7XG5pbXBvcnQgeyBDb21wb3Nlckluc2VydFBheWxvYWQsIENvbXBvc2VyVHlwZSB9IGZyb20gXCIuLi8uLi9kaXNwYXRjaGVyL3BheWxvYWRzL0NvbXBvc2VySW5zZXJ0UGF5bG9hZFwiO1xuaW1wb3J0IEhlYWRpbmcgZnJvbSBcIi4uL3ZpZXdzL3R5cG9ncmFwaHkvSGVhZGluZ1wiO1xuaW1wb3J0IHsgU2RrQ29udGV4dENsYXNzIH0gZnJvbSBcIi4uLy4uL2NvbnRleHRzL1NES0NvbnRleHRcIjtcbmltcG9ydCB7IFRocmVhZFBheWxvYWQgfSBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9UaHJlYWRQYXlsb2FkXCI7XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIHJvb206IFJvb207XG4gICAgb25DbG9zZTogKCkgPT4gdm9pZDtcbiAgICByZXNpemVOb3RpZmllcjogUmVzaXplTm90aWZpZXI7XG4gICAgbXhFdmVudDogTWF0cml4RXZlbnQ7XG4gICAgcGVybWFsaW5rQ3JlYXRvcj86IFJvb21QZXJtYWxpbmtDcmVhdG9yO1xuICAgIGUyZVN0YXR1cz86IEUyRVN0YXR1cztcbiAgICBpbml0aWFsRXZlbnQ/OiBNYXRyaXhFdmVudDtcbiAgICBpc0luaXRpYWxFdmVudEhpZ2hsaWdodGVkPzogYm9vbGVhbjtcbiAgICBpbml0aWFsRXZlbnRTY3JvbGxJbnRvVmlldz86IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIHRocmVhZD86IFRocmVhZDtcbiAgICBsYXN0UmVwbHk/OiBNYXRyaXhFdmVudCB8IG51bGw7XG4gICAgbGF5b3V0OiBMYXlvdXQ7XG4gICAgZWRpdFN0YXRlPzogRWRpdG9yU3RhdGVUcmFuc2ZlcjtcbiAgICByZXBseVRvRXZlbnQ/OiBNYXRyaXhFdmVudDtcbiAgICBuYXJyb3c6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRocmVhZFZpZXcgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwdWJsaWMgc3RhdGljIGNvbnRleHRUeXBlID0gUm9vbUNvbnRleHQ7XG4gICAgcHVibGljIGRlY2xhcmUgY29udGV4dDogUmVhY3QuQ29udGV4dFR5cGU8dHlwZW9mIFJvb21Db250ZXh0PjtcblxuICAgIHByaXZhdGUgZGlzcGF0Y2hlclJlZjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWFkb25seSBsYXlvdXRXYXRjaGVyUmVmOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB0aW1lbGluZVBhbmVsID0gY3JlYXRlUmVmPFRpbWVsaW5lUGFuZWw+KCk7XG4gICAgcHJpdmF0ZSBjYXJkID0gY3JlYXRlUmVmPEhUTUxEaXZFbGVtZW50PigpO1xuXG4gICAgLy8gU2V0IGJ5IHNldEV2ZW50SWQgaW4gY3Rvci5cbiAgICBwcml2YXRlIGV2ZW50SWQhOiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcywgY29udGV4dDogUmVhY3QuQ29udGV4dFR5cGU8dHlwZW9mIFJvb21Db250ZXh0Pikge1xuICAgICAgICBzdXBlcihwcm9wcywgY29udGV4dCk7XG5cbiAgICAgICAgdGhpcy5zZXRFdmVudElkKHRoaXMucHJvcHMubXhFdmVudCk7XG4gICAgICAgIGNvbnN0IHRocmVhZCA9IHRoaXMucHJvcHMucm9vbS5nZXRUaHJlYWQodGhpcy5ldmVudElkKSA/PyB1bmRlZmluZWQ7XG5cbiAgICAgICAgdGhpcy5zZXR1cFRocmVhZExpc3RlbmVycyh0aHJlYWQpO1xuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgbGF5b3V0OiBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwibGF5b3V0XCIpLFxuICAgICAgICAgICAgbmFycm93OiBmYWxzZSxcbiAgICAgICAgICAgIHRocmVhZCxcbiAgICAgICAgICAgIGxhc3RSZXBseTogdGhyZWFkPy5sYXN0UmVwbHkoKGV2OiBNYXRyaXhFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBldi5pc1JlbGF0aW9uKFRIUkVBRF9SRUxBVElPTl9UWVBFLm5hbWUpICYmICFldi5zdGF0dXM7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmxheW91dFdhdGNoZXJSZWYgPSBTZXR0aW5nc1N0b3JlLndhdGNoU2V0dGluZyhcImxheW91dFwiLCBudWxsLCAoLi4uWywgLCAsIHZhbHVlXSkgPT5cbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBsYXlvdXQ6IHZhbHVlIGFzIExheW91dCB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnRocmVhZCkge1xuICAgICAgICAgICAgdGhpcy5wb3N0VGhyZWFkVXBkYXRlKHRoaXMuc3RhdGUudGhyZWFkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0dXBUaHJlYWQodGhpcy5wcm9wcy5teEV2ZW50KTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyUmVmID0gZGlzLnJlZ2lzdGVyKHRoaXMub25BY3Rpb24pO1xuXG4gICAgICAgIHRoaXMucHJvcHMucm9vbS5vbihUaHJlYWRFdmVudC5OZXcsIHRoaXMub25OZXdUaHJlYWQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnRXaWxsVW5tb3VudCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzcGF0Y2hlclJlZikgZGlzLnVucmVnaXN0ZXIodGhpcy5kaXNwYXRjaGVyUmVmKTtcbiAgICAgICAgY29uc3Qgcm9vbUlkID0gdGhpcy5wcm9wcy5teEV2ZW50LmdldFJvb21JZCgpO1xuICAgICAgICBTZXR0aW5nc1N0b3JlLnVud2F0Y2hTZXR0aW5nKHRoaXMubGF5b3V0V2F0Y2hlclJlZik7XG5cbiAgICAgICAgY29uc3QgaGFzUm9vbUNoYW5nZWQgPSBTZGtDb250ZXh0Q2xhc3MuaW5zdGFuY2Uucm9vbVZpZXdTdG9yZS5nZXRSb29tSWQoKSAhPT0gcm9vbUlkO1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5pbml0aWFsRXZlbnQgJiYgIWhhc1Jvb21DaGFuZ2VkKSB7XG4gICAgICAgICAgICBkaXMuZGlzcGF0Y2g8Vmlld1Jvb21QYXlsb2FkPih7XG4gICAgICAgICAgICAgICAgYWN0aW9uOiBBY3Rpb24uVmlld1Jvb20sXG4gICAgICAgICAgICAgICAgcm9vbV9pZDogdGhpcy5wcm9wcy5yb29tLnJvb21JZCxcbiAgICAgICAgICAgICAgICBtZXRyaWNzVHJpZ2dlcjogdW5kZWZpbmVkLCAvLyByb29tIGRvZXNuJ3QgY2hhbmdlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRpcy5kaXNwYXRjaDxUaHJlYWRQYXlsb2FkPih7XG4gICAgICAgICAgICBhY3Rpb246IEFjdGlvbi5WaWV3VGhyZWFkLFxuICAgICAgICAgICAgdGhyZWFkX2lkOiBudWxsLFxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnN0YXRlLnRocmVhZD8ub2ZmKFRocmVhZEV2ZW50Lk5ld1JlcGx5LCB0aGlzLnVwZGF0ZVRocmVhZFJlbGF0aW9uKTtcbiAgICAgICAgdGhpcy5wcm9wcy5yb29tLm9mZihSb29tRXZlbnQuTG9jYWxFY2hvVXBkYXRlZCwgdGhpcy51cGRhdGVUaHJlYWRSZWxhdGlvbik7XG4gICAgICAgIHRoaXMucHJvcHMucm9vbS5yZW1vdmVMaXN0ZW5lcihUaHJlYWRFdmVudC5OZXcsIHRoaXMub25OZXdUaHJlYWQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnREaWRVcGRhdGUocHJldlByb3BzOiBJUHJvcHMpOiB2b2lkIHtcbiAgICAgICAgaWYgKHByZXZQcm9wcy5teEV2ZW50ICE9PSB0aGlzLnByb3BzLm14RXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0RXZlbnRJZCh0aGlzLnByb3BzLm14RXZlbnQpO1xuICAgICAgICAgICAgdGhpcy5zZXR1cFRocmVhZCh0aGlzLnByb3BzLm14RXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByZXZQcm9wcy5yb29tICE9PSB0aGlzLnByb3BzLnJvb20pIHtcbiAgICAgICAgICAgIFJpZ2h0UGFuZWxTdG9yZS5pbnN0YW5jZS5zZXRDYXJkKHsgcGhhc2U6IFJpZ2h0UGFuZWxQaGFzZXMuUm9vbVN1bW1hcnkgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNldEV2ZW50SWQoZXZlbnQ6IE1hdHJpeEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmICghZXZlbnQuZ2V0SWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiR290IHRocmVhZCBldmVudCB3aXRob3V0IGlkXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ldmVudElkID0gZXZlbnQuZ2V0SWQoKSE7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkFjdGlvbiA9IChwYXlsb2FkOiBBY3Rpb25QYXlsb2FkKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChwYXlsb2FkLnBoYXNlID09IFJpZ2h0UGFuZWxQaGFzZXMuVGhyZWFkVmlldyAmJiBwYXlsb2FkLmV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNldHVwVGhyZWFkKHBheWxvYWQuZXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAocGF5bG9hZC5hY3Rpb24pIHtcbiAgICAgICAgICAgIGNhc2UgQWN0aW9uLkNvbXBvc2VySW5zZXJ0OiB7XG4gICAgICAgICAgICAgICAgaWYgKHBheWxvYWQuY29tcG9zZXJUeXBlKSBicmVhaztcbiAgICAgICAgICAgICAgICBpZiAocGF5bG9hZC50aW1lbGluZVJlbmRlcmluZ1R5cGUgIT09IFRpbWVsaW5lUmVuZGVyaW5nVHlwZS5UaHJlYWQpIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgLy8gcmUtZGlzcGF0Y2ggdG8gdGhlIGNvcnJlY3QgY29tcG9zZXJcbiAgICAgICAgICAgICAgICBkaXMuZGlzcGF0Y2g8Q29tcG9zZXJJbnNlcnRQYXlsb2FkPih7XG4gICAgICAgICAgICAgICAgICAgIC4uLihwYXlsb2FkIGFzIENvbXBvc2VySW5zZXJ0UGF5bG9hZCksXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvc2VyVHlwZTogdGhpcy5zdGF0ZS5lZGl0U3RhdGUgPyBDb21wb3NlclR5cGUuRWRpdCA6IENvbXBvc2VyVHlwZS5TZW5kLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYXNlIEFjdGlvbi5FZGl0RXZlbnQ6XG4gICAgICAgICAgICAgICAgLy8gUXVpdCBlYXJseSBpZiBpdCdzIG5vdCBhIHRocmVhZCBjb250ZXh0XG4gICAgICAgICAgICAgICAgaWYgKHBheWxvYWQudGltZWxpbmVSZW5kZXJpbmdUeXBlICE9PSBUaW1lbGluZVJlbmRlcmluZ1R5cGUuVGhyZWFkKSByZXR1cm47XG4gICAgICAgICAgICAgICAgLy8gUXVpdCBlYXJseSBpZiB0aGF0J3Mgbm90IGEgdGhyZWFkIGV2ZW50XG4gICAgICAgICAgICAgICAgaWYgKHBheWxvYWQuZXZlbnQgJiYgIXBheWxvYWQuZXZlbnQuZ2V0VGhyZWFkKCkpIHJldHVybjtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlZGl0U3RhdGU6IHBheWxvYWQuZXZlbnQgPyBuZXcgRWRpdG9yU3RhdGVUcmFuc2ZlcihwYXlsb2FkLmV2ZW50KSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBheWxvYWQuZXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRpbWVsaW5lUGFuZWwuY3VycmVudD8uc2Nyb2xsVG9FdmVudElmTmVlZGVkKHBheWxvYWQuZXZlbnQuZ2V0SWQoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJyZXBseV90b19ldmVudFwiOlxuICAgICAgICAgICAgICAgIGlmIChwYXlsb2FkLmNvbnRleHQgPT09IFRpbWVsaW5lUmVuZGVyaW5nVHlwZS5UaHJlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXBseVRvRXZlbnQ6IHBheWxvYWQuZXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBzZXR1cFRocmVhZCA9IChteEV2OiBNYXRyaXhFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICAvKiogcHJlc2VuY2Ugb2YgZXZlbnQgSWQgaGFzIGJlZW4gZW5zdXJlZCBieSB7QGxpbmsgc2V0RXZlbnRJZH0gKi9cbiAgICAgICAgY29uc3QgZXZlbnRJZCA9IG14RXYuZ2V0SWQoKSE7XG5cbiAgICAgICAgbGV0IHRocmVhZCA9IHRoaXMucHJvcHMucm9vbS5nZXRUaHJlYWQoZXZlbnRJZCk7XG5cbiAgICAgICAgaWYgKCF0aHJlYWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IFtdO1xuICAgICAgICAgICAgLy8gaWYgdGhlIGV2ZW50IGlzIHN0aWxsIGJlaW5nIHNlbnQsIGRvbid0IGluY2x1ZGUgaXQgaW4gdGhlIFRocmVhZCB5ZXQgLSBvdGhlcndpc2UgdGhlIHRpbWVsaW5lIHBhbmVsXG4gICAgICAgICAgICAvLyB3aWxsIGF0dGVtcHQgdG8gc2hvdyBpdCB0d2ljZSAob25jZSBhcyBhIHJlZ3VsYXIgZXZlbnQsIG9uY2UgYXMgYSBwZW5kaW5nIGV2ZW50KSBhbmQgZXZlcnl0aGluZyB3aWxsXG4gICAgICAgICAgICAvLyBibG93IHVwXG4gICAgICAgICAgICBpZiAobXhFdi5zdGF0dXMgPT09IG51bGwpIGV2ZW50cy5wdXNoKG14RXYpO1xuICAgICAgICAgICAgdGhyZWFkID0gdGhpcy5wcm9wcy5yb29tLmNyZWF0ZVRocmVhZChldmVudElkLCBteEV2LCBldmVudHMsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVUaHJlYWQodGhyZWFkKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbk5ld1RocmVhZCA9ICh0aHJlYWQ6IFRocmVhZCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAodGhyZWFkLmlkID09PSB0aGlzLnByb3BzLm14RXZlbnQuZ2V0SWQoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXR1cFRocmVhZCh0aGlzLnByb3BzLm14RXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgdXBkYXRlVGhyZWFkUmVsYXRpb24gPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgbGFzdFJlcGx5OiB0aGlzLnRocmVhZExhc3RSZXBseSxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgZ2V0IHRocmVhZExhc3RSZXBseSgpOiBNYXRyaXhFdmVudCB8IHVuZGVmaW5lZCB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnN0YXRlLnRocmVhZD8ubGFzdFJlcGx5KChldjogTWF0cml4RXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXYuaXNSZWxhdGlvbihUSFJFQURfUkVMQVRJT05fVFlQRS5uYW1lKSAmJiAhZXYuc3RhdHVzO1xuICAgICAgICAgICAgfSkgPz8gdW5kZWZpbmVkXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVUaHJlYWQgPSAodGhyZWFkPzogVGhyZWFkKTogdm9pZCA9PiB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnRocmVhZCA9PT0gdGhyZWFkKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5zZXR1cFRocmVhZExpc3RlbmVycyh0aHJlYWQsIHRoaXMuc3RhdGUudGhyZWFkKTtcbiAgICAgICAgaWYgKHRocmVhZCkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZShcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHRocmVhZCxcbiAgICAgICAgICAgICAgICAgICAgbGFzdFJlcGx5OiB0aGlzLnRocmVhZExhc3RSZXBseSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFzeW5jICgpID0+IHRoaXMucG9zdFRocmVhZFVwZGF0ZSh0aHJlYWQpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIGFzeW5jIHBvc3RUaHJlYWRVcGRhdGUodGhyZWFkOiBUaHJlYWQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgZGlzLmRpc3BhdGNoPFRocmVhZFBheWxvYWQ+KHtcbiAgICAgICAgICAgIGFjdGlvbjogQWN0aW9uLlZpZXdUaHJlYWQsXG4gICAgICAgICAgICB0aHJlYWRfaWQ6IHRocmVhZC5pZCxcbiAgICAgICAgfSk7XG4gICAgICAgIHRocmVhZC5lbWl0KFRocmVhZEV2ZW50LlZpZXdUaHJlYWQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVRocmVhZFJlbGF0aW9uKCk7XG4gICAgICAgIHRoaXMudGltZWxpbmVQYW5lbC5jdXJyZW50Py5yZWZyZXNoVGltZWxpbmUodGhpcy5wcm9wcy5pbml0aWFsRXZlbnQ/LmdldElkKCkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0dXBUaHJlYWRMaXN0ZW5lcnModGhyZWFkPzogVGhyZWFkIHwgdW5kZWZpbmVkLCBvbGRUaHJlYWQ/OiBUaHJlYWQgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICAgICAgaWYgKG9sZFRocmVhZCkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS50aHJlYWQ/Lm9mZihUaHJlYWRFdmVudC5OZXdSZXBseSwgdGhpcy51cGRhdGVUaHJlYWRSZWxhdGlvbik7XG4gICAgICAgICAgICB0aGlzLnByb3BzLnJvb20ub2ZmKFJvb21FdmVudC5Mb2NhbEVjaG9VcGRhdGVkLCB0aGlzLnVwZGF0ZVRocmVhZFJlbGF0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhyZWFkKSB7XG4gICAgICAgICAgICB0aHJlYWQub24oVGhyZWFkRXZlbnQuTmV3UmVwbHksIHRoaXMudXBkYXRlVGhyZWFkUmVsYXRpb24pO1xuICAgICAgICAgICAgdGhpcy5wcm9wcy5yb29tLm9uKFJvb21FdmVudC5Mb2NhbEVjaG9VcGRhdGVkLCB0aGlzLnVwZGF0ZVRocmVhZFJlbGF0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVzZXRKdW1wVG9FdmVudCA9IChldmVudD86IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLnByb3BzLmluaXRpYWxFdmVudCAmJlxuICAgICAgICAgICAgdGhpcy5wcm9wcy5pbml0aWFsRXZlbnRTY3JvbGxJbnRvVmlldyAmJlxuICAgICAgICAgICAgZXZlbnQgPT09IHRoaXMucHJvcHMuaW5pdGlhbEV2ZW50Py5nZXRJZCgpXG4gICAgICAgICkge1xuICAgICAgICAgICAgZGlzLmRpc3BhdGNoPFZpZXdSb29tUGF5bG9hZD4oe1xuICAgICAgICAgICAgICAgIGFjdGlvbjogQWN0aW9uLlZpZXdSb29tLFxuICAgICAgICAgICAgICAgIHJvb21faWQ6IHRoaXMucHJvcHMucm9vbS5yb29tSWQsXG4gICAgICAgICAgICAgICAgZXZlbnRfaWQ6IHRoaXMucHJvcHMuaW5pdGlhbEV2ZW50Py5nZXRJZCgpLFxuICAgICAgICAgICAgICAgIGhpZ2hsaWdodGVkOiB0aGlzLnByb3BzLmlzSW5pdGlhbEV2ZW50SGlnaGxpZ2h0ZWQsXG4gICAgICAgICAgICAgICAgc2Nyb2xsX2ludG9fdmlldzogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmVwbHlpbmdUb0V2ZW50OiB0aGlzLnN0YXRlLnJlcGx5VG9FdmVudCxcbiAgICAgICAgICAgICAgICBtZXRyaWNzVHJpZ2dlcjogdW5kZWZpbmVkLCAvLyByb29tIGRvZXNuJ3QgY2hhbmdlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIG9uTWVhc3VyZW1lbnQgPSAobmFycm93OiBib29sZWFuKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBuYXJyb3cgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25LZXlEb3duID0gKGV2OiBLZXlib2FyZEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGxldCBoYW5kbGVkID0gZmFsc2U7XG5cbiAgICAgICAgY29uc3QgYWN0aW9uID0gZ2V0S2V5QmluZGluZ3NNYW5hZ2VyKCkuZ2V0Um9vbUFjdGlvbihldik7XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgICBjYXNlIEtleUJpbmRpbmdBY3Rpb24uVXBsb2FkRmlsZToge1xuICAgICAgICAgICAgICAgIGRpcy5kaXNwYXRjaChcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBcInVwbG9hZF9maWxlXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiBUaW1lbGluZVJlbmRlcmluZ1R5cGUuVGhyZWFkLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFuZGxlZCkge1xuICAgICAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25GaWxlRHJvcCA9IChkYXRhVHJhbnNmZXI6IERhdGFUcmFuc2Zlcik6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCByb29tSWQgPSB0aGlzLnByb3BzLm14RXZlbnQuZ2V0Um9vbUlkKCk7XG4gICAgICAgIGlmIChyb29tSWQpIHtcbiAgICAgICAgICAgIENvbnRlbnRNZXNzYWdlcy5zaGFyZWRJbnN0YW5jZSgpLnNlbmRDb250ZW50TGlzdFRvUm9vbShcbiAgICAgICAgICAgICAgICBBcnJheS5mcm9tKGRhdGFUcmFuc2Zlci5maWxlcyksXG4gICAgICAgICAgICAgICAgcm9vbUlkLFxuICAgICAgICAgICAgICAgIHRoaXMudGhyZWFkUmVsYXRpb24sXG4gICAgICAgICAgICAgICAgTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKSxcbiAgICAgICAgICAgICAgICBUaW1lbGluZVJlbmRlcmluZ1R5cGUuVGhyZWFkLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlVua253b24gcm9vbUlkIGZvciBldmVudFwiLCB0aGlzLnByb3BzLm14RXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgZ2V0IHRocmVhZFJlbGF0aW9uKCk6IElFdmVudFJlbGF0aW9uIHtcbiAgICAgICAgY29uc3QgcmVsYXRpb246IElFdmVudFJlbGF0aW9uID0ge1xuICAgICAgICAgICAgcmVsX3R5cGU6IFRIUkVBRF9SRUxBVElPTl9UWVBFLm5hbWUsXG4gICAgICAgICAgICBldmVudF9pZDogdGhpcy5zdGF0ZS50aHJlYWQ/LmlkLFxuICAgICAgICAgICAgaXNfZmFsbGluZ19iYWNrOiB0cnVlLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGZhbGxiYWNrRXZlbnRJZCA9IHRoaXMuc3RhdGUubGFzdFJlcGx5Py5nZXRJZCgpID8/IHRoaXMuc3RhdGUudGhyZWFkPy5pZDtcbiAgICAgICAgaWYgKGZhbGxiYWNrRXZlbnRJZCkge1xuICAgICAgICAgICAgcmVsYXRpb25bXCJtLmluX3JlcGx5X3RvXCJdID0ge1xuICAgICAgICAgICAgICAgIGV2ZW50X2lkOiBmYWxsYmFja0V2ZW50SWQsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlbGF0aW9uO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVuZGVyVGhyZWFkVmlld0hlYWRlciA9ICgpOiBKU1guRWxlbWVudCA9PiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0Jhc2VDYXJkX2hlYWRlcl90aXRsZVwiPlxuICAgICAgICAgICAgICAgIDxIZWFkaW5nIHNpemU9XCI0XCIgY2xhc3NOYW1lPVwibXhfQmFzZUNhcmRfaGVhZGVyX3RpdGxlX2hlYWRpbmdcIj5cbiAgICAgICAgICAgICAgICAgICAge190KFwiY29tbW9ufHRocmVhZFwiKX1cbiAgICAgICAgICAgICAgICA8L0hlYWRpbmc+XG4gICAgICAgICAgICAgICAgPFRocmVhZExpc3RDb250ZXh0TWVudSBteEV2ZW50PXt0aGlzLnByb3BzLm14RXZlbnR9IHBlcm1hbGlua0NyZWF0b3I9e3RoaXMucHJvcHMucGVybWFsaW5rQ3JlYXRvcn0gLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICApO1xuICAgIH07XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGNvbnN0IGhpZ2hsaWdodGVkRXZlbnRJZCA9IHRoaXMucHJvcHMuaXNJbml0aWFsRXZlbnRIaWdobGlnaHRlZCA/IHRoaXMucHJvcHMuaW5pdGlhbEV2ZW50Py5nZXRJZCgpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGNvbnN0IHRocmVhZFJlbGF0aW9uID0gdGhpcy50aHJlYWRSZWxhdGlvbjtcblxuICAgICAgICBsZXQgdGltZWxpbmU6IEpTWC5FbGVtZW50IHwgbnVsbDtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUudGhyZWFkKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5wcm9wcy5pbml0aWFsRXZlbnQgJiYgdGhpcy5wcm9wcy5pbml0aWFsRXZlbnQuZ2V0Um9vbUlkKCkgIT09IHRoaXMuc3RhdGUudGhyZWFkLnJvb21JZCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgICAgICBcIlRocmVhZFZpZXcgYXR0ZW1wdGluZyB0byByZW5kZXIgVGltZWxpbmVQYW5lbCB3aXRoIG1pc21hdGNoZWQgaW5pdGlhbEV2ZW50XCIsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUudGhyZWFkLnJvb21JZCxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5pbml0aWFsRXZlbnQuZ2V0Um9vbUlkKCksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJvcHMuaW5pdGlhbEV2ZW50LmdldElkKCksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGltZWxpbmUgPSAoXG4gICAgICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICAgICAgPEZpbGVEcm9wVGFyZ2V0IHBhcmVudD17dGhpcy5jYXJkLmN1cnJlbnR9IG9uRmlsZURyb3A9e3RoaXMub25GaWxlRHJvcH0gLz5cbiAgICAgICAgICAgICAgICAgICAgPFRpbWVsaW5lUGFuZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleT17dGhpcy5zdGF0ZS50aHJlYWQuaWR9XG4gICAgICAgICAgICAgICAgICAgICAgICByZWY9e3RoaXMudGltZWxpbmVQYW5lbH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dSZWFkUmVjZWlwdHM9e3RoaXMuY29udGV4dC5zaG93UmVhZFJlY2VpcHRzfVxuICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlUmVhZFJlY2VpcHRzPXt0cnVlfVxuICAgICAgICAgICAgICAgICAgICAgICAgbWFuYWdlUmVhZE1hcmtlcnM9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kUmVhZFJlY2VpcHRPbkxvYWQ9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lbGluZVNldD17dGhpcy5zdGF0ZS50aHJlYWQudGltZWxpbmVTZXR9XG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93VXJsUHJldmlldz17dGhpcy5jb250ZXh0LnNob3dVcmxQcmV2aWV3fVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhyZWFkVmlldyBkb2Vzbid0IHN1cHBvcnQgSVJDIGxheW91dCBhdCB0aGlzIHRpbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIGxheW91dD17dGhpcy5zdGF0ZS5sYXlvdXQgPT09IExheW91dC5CdWJibGUgPyBMYXlvdXQuQnViYmxlIDogTGF5b3V0Lkdyb3VwfVxuICAgICAgICAgICAgICAgICAgICAgICAgaGlkZVRocmVhZGVkTWVzc2FnZXM9e2ZhbHNlfVxuICAgICAgICAgICAgICAgICAgICAgICAgaGlkZGVuPXtmYWxzZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dSZWFjdGlvbnM9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9Sb29tVmlld19tZXNzYWdlUGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgcGVybWFsaW5rQ3JlYXRvcj17dGhpcy5wcm9wcy5wZXJtYWxpbmtDcmVhdG9yfVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVtYmVyc0xvYWRlZD17dHJ1ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRTdGF0ZT17dGhpcy5zdGF0ZS5lZGl0U3RhdGV9XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudElkPXt0aGlzLnByb3BzLmluaXRpYWxFdmVudD8uZ2V0SWQoKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hsaWdodGVkRXZlbnRJZD17aGlnaGxpZ2h0ZWRFdmVudElkfVxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRTY3JvbGxJbnRvVmlldz17dGhpcy5wcm9wcy5pbml0aWFsRXZlbnRTY3JvbGxJbnRvVmlld31cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uRXZlbnRTY3JvbGxlZEludG9WaWV3PXt0aGlzLnJlc2V0SnVtcFRvRXZlbnR9XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGltZWxpbmUgPSAoXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9Sb29tVmlld19tZXNzYWdlUGFuZWxTcGlubmVyXCI+XG4gICAgICAgICAgICAgICAgICAgIDxTcGlubmVyIC8+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxSb29tQ29udGV4dC5Qcm92aWRlclxuICAgICAgICAgICAgICAgIHZhbHVlPXt7XG4gICAgICAgICAgICAgICAgICAgIC4uLnRoaXMuY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgdGltZWxpbmVSZW5kZXJpbmdUeXBlOiBUaW1lbGluZVJlbmRlcmluZ1R5cGUuVGhyZWFkLFxuICAgICAgICAgICAgICAgICAgICB0aHJlYWRJZDogdGhpcy5zdGF0ZS50aHJlYWQ/LmlkLFxuICAgICAgICAgICAgICAgICAgICBsaXZlVGltZWxpbmU6IHRoaXMuc3RhdGU/LnRocmVhZD8udGltZWxpbmVTZXQ/LmdldExpdmVUaW1lbGluZSgpLFxuICAgICAgICAgICAgICAgICAgICBuYXJyb3c6IHRoaXMuc3RhdGUubmFycm93LFxuICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPEJhc2VDYXJkXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT17Y2xhc3NOYW1lcyhcIm14X1RocmVhZFZpZXcgbXhfVGhyZWFkUGFuZWxcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXhfVGhyZWFkVmlld19uYXJyb3c6IHRoaXMuc3RhdGUubmFycm93LFxuICAgICAgICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgICAgICAgICAgb25DbG9zZT17dGhpcy5wcm9wcy5vbkNsb3NlfVxuICAgICAgICAgICAgICAgICAgICB3aXRob3V0U2Nyb2xsQ29udGFpbmVyPXt0cnVlfVxuICAgICAgICAgICAgICAgICAgICBoZWFkZXI9e3RoaXMucmVuZGVyVGhyZWFkVmlld0hlYWRlcigpfVxuICAgICAgICAgICAgICAgICAgICByZWY9e3RoaXMuY2FyZH1cbiAgICAgICAgICAgICAgICAgICAgb25LZXlEb3duPXt0aGlzLm9uS2V5RG93bn1cbiAgICAgICAgICAgICAgICAgICAgb25CYWNrPXsoZXY6IEJ1dHRvbkV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBQb3N0aG9nVHJhY2tlcnMudHJhY2tJbnRlcmFjdGlvbihcIldlYlRocmVhZFZpZXdCYWNrQnV0dG9uXCIsIGV2KTtcbiAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIHt0aGlzLmNhcmQuY3VycmVudCAmJiA8TWVhc3VyZWQgc2Vuc29yPXt0aGlzLmNhcmQuY3VycmVudH0gb25NZWFzdXJlbWVudD17dGhpcy5vbk1lYXN1cmVtZW50fSAvPn1cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9UaHJlYWRWaWV3X3RpbWVsaW5lUGFuZWxXcmFwcGVyXCI+e3RpbWVsaW5lfTwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgIHtDb250ZW50TWVzc2FnZXMuc2hhcmVkSW5zdGFuY2UoKS5nZXRDdXJyZW50VXBsb2Fkcyh0aHJlYWRSZWxhdGlvbikubGVuZ3RoID4gMCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICA8VXBsb2FkQmFyIHJvb209e3RoaXMucHJvcHMucm9vbX0gcmVsYXRpb249e3RocmVhZFJlbGF0aW9ufSAvPlxuICAgICAgICAgICAgICAgICAgICApfVxuXG4gICAgICAgICAgICAgICAgICAgIHt0aGlzLnN0YXRlLnRocmVhZD8udGltZWxpbmVTZXQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgPE1lc3NhZ2VDb21wb3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb209e3RoaXMucHJvcHMucm9vbX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNpemVOb3RpZmllcj17dGhpcy5wcm9wcy5yZXNpemVOb3RpZmllcn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxhdGlvbj17dGhyZWFkUmVsYXRpb259XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbHlUb0V2ZW50PXt0aGlzLnN0YXRlLnJlcGx5VG9FdmVudH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJtYWxpbmtDcmVhdG9yPXt0aGlzLnByb3BzLnBlcm1hbGlua0NyZWF0b3J9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZTJlU3RhdHVzPXt0aGlzLnByb3BzLmUyZVN0YXR1c31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wYWN0PXt0cnVlfVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgICA8L0Jhc2VDYXJkPlxuICAgICAgICAgICAgPC9Sb29tQ29udGV4dC5Qcm92aWRlcj5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBU0EsSUFBQUUsT0FBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsV0FBQSxHQUFBQyxzQkFBQSxDQUFBSixPQUFBO0FBRUEsSUFBQUssU0FBQSxHQUFBRCxzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQU0sc0JBQUEsR0FBQU4sT0FBQTtBQUVBLElBQUFPLGdCQUFBLEdBQUFILHNCQUFBLENBQUFKLE9BQUE7QUFFQSxJQUFBUSxPQUFBLEdBQUFSLE9BQUE7QUFDQSxJQUFBUyxjQUFBLEdBQUFMLHNCQUFBLENBQUFKLE9BQUE7QUFDQSxJQUFBVSxXQUFBLEdBQUFOLHNCQUFBLENBQUFKLE9BQUE7QUFFQSxJQUFBVyxRQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxnQkFBQSxHQUFBWixPQUFBO0FBRUEsSUFBQWEsb0JBQUEsR0FBQVQsc0JBQUEsQ0FBQUosT0FBQTtBQUNBLElBQUFjLFlBQUEsR0FBQWYsdUJBQUEsQ0FB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