UNPKG

matrix-react-sdk

Version:
274 lines (260 loc) 47.1 kB
"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 = _interopRequireDefault(require("react")); var _logger = require("matrix-js-sdk/src/logger"); var _languageHandler = require("../../../languageHandler"); var _VoiceRecording = require("../../../audio/VoiceRecording"); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _LiveRecordingWaveform = _interopRequireDefault(require("../audio_messages/LiveRecordingWaveform")); var _LiveRecordingClock = _interopRequireDefault(require("../audio_messages/LiveRecordingClock")); var _VoiceRecordingStore = require("../../../stores/VoiceRecordingStore"); var _AsyncStore = require("../../../stores/AsyncStore"); var _RecordingPlayback = _interopRequireWildcard(require("../audio_messages/RecordingPlayback")); var _Modal = _interopRequireDefault(require("../../../Modal")); var _ErrorDialog = _interopRequireDefault(require("../dialogs/ErrorDialog")); var _MediaDeviceHandler = _interopRequireWildcard(require("../../../MediaDeviceHandler")); var _NotificationBadge = _interopRequireDefault(require("./NotificationBadge")); var _StaticNotificationState = require("../../../stores/notifications/StaticNotificationState"); var _NotificationLevel = require("../../../stores/notifications/NotificationLevel"); var _InlineSpinner = _interopRequireDefault(require("../elements/InlineSpinner")); var _PlaybackManager = require("../../../audio/PlaybackManager"); var _localRoom = require("../../../utils/local-room"); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _SendMessageComposer = require("./SendMessageComposer"); var _Reply = require("../../../utils/Reply"); var _RoomContext = _interopRequireDefault(require("../../../contexts/RoomContext")); var _createVoiceMessageContent = require("../../../utils/createVoiceMessageContent"); var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton")); 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 2021, 2022 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. */ /** * Container tile for rendering the voice message recorder in the composer. */ class VoiceRecordComposerTile extends _react.default.PureComponent { constructor(props, context) { super(props, context); (0, _defineProperty2.default)(this, "voiceRecordingId", void 0); (0, _defineProperty2.default)(this, "onCancel", async () => { await this.disposeRecording(); }); (0, _defineProperty2.default)(this, "onRecordStartEndClick", async () => { if (this.state.recorder) { await this.state.recorder.stop(); return; } // The "microphone access error" dialogs are used a lot, so let's functionify them const accessError = () => { _Modal.default.createDialog(_ErrorDialog.default, { title: (0, _languageHandler._t)("voip|unable_to_access_audio_input_title"), description: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("voip|unable_to_access_audio_input_description"))) }); }; // Do a sanity test to ensure we're about to grab a valid microphone reference. Things might // change between this and recording, but at least we will have tried. try { const devices = await _MediaDeviceHandler.default.getDevices(); if (!devices?.[_MediaDeviceHandler.MediaDeviceKindEnum.AudioInput]?.length) { _Modal.default.createDialog(_ErrorDialog.default, { title: (0, _languageHandler._t)("voip|no_audio_input_title"), description: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("voip|no_audio_input_description"))) }); return; } // else we probably have a device that is good enough } catch (e) { _logger.logger.error("Error getting devices: ", e); accessError(); return; } try { // stop any noises which might be happening _PlaybackManager.PlaybackManager.instance.pauseAllExcept(); const recorder = _VoiceRecordingStore.VoiceRecordingStore.instance.startRecording(this.voiceRecordingId); await recorder.start(); this.bindNewRecorder(recorder); this.setState({ recorder, recordingPhase: _VoiceRecording.RecordingState.Started }); } catch (e) { _logger.logger.error("Error starting recording: ", e); accessError(); // noinspection ES6MissingAwait - if this goes wrong we don't want it to affect the call stack _VoiceRecordingStore.VoiceRecordingStore.instance.disposeRecording(this.voiceRecordingId); } }); (0, _defineProperty2.default)(this, "onRecordingUpdate", ev => { if (ev === _VoiceRecording.RecordingState.EndingSoon) return; // ignore this state: it has no UI purpose here this.setState({ recordingPhase: ev }); }); this.state = {}; this.voiceRecordingId = _VoiceRecordingStore.VoiceRecordingStore.getVoiceRecordingId(this.props.room, this.props.relation); } componentDidMount() { const recorder = _VoiceRecordingStore.VoiceRecordingStore.instance.getActiveRecording(this.voiceRecordingId); if (recorder) { if (recorder.isRecording || !recorder.hasRecording) { _logger.logger.warn("Cached recording hasn't ended yet and might cause issues"); } this.bindNewRecorder(recorder); this.setState({ recorder, recordingPhase: _VoiceRecording.RecordingState.Ended }); } } async componentWillUnmount() { // Stop recording, but keep the recording memory (don't dispose it). This is to let the user // come back and finish working with it. const recording = _VoiceRecordingStore.VoiceRecordingStore.instance.getActiveRecording(this.voiceRecordingId); await recording?.stop(); // Clean up our listeners by binding a falsy recorder this.bindNewRecorder(null); } // called by composer async send() { if (!this.state.recorder) { throw new Error("No recording started - cannot send anything"); } const { replyToEvent, relation, permalinkCreator } = this.props; await this.state.recorder.stop(); let upload; try { upload = await this.state.recorder.upload(this.voiceRecordingId); } catch (e) { _logger.logger.error("Error uploading voice message:", e); // Flag error and move on. The recording phase will be reset by the upload function. this.setState({ didUploadFail: true }); return; // don't dispose the recording: the user has a chance to re-upload } try { // noinspection ES6MissingAwait - we don't care if it fails, it'll get queued. const content = (0, _createVoiceMessageContent.createVoiceMessageContent)(upload.mxc, this.state.recorder.contentType, Math.round(this.state.recorder.durationSeconds * 1000), this.state.recorder.contentLength, upload.encrypted, this.state.recorder.getPlayback().thumbnailWaveform.map(v => Math.round(v * 1024))); // Attach mentions, which really only applies if there's a replyToEvent. (0, _SendMessageComposer.attachMentions)(_MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId(), content, null, replyToEvent); (0, _SendMessageComposer.attachRelation)(content, relation); if (replyToEvent) { (0, _Reply.addReplyToMessageContent)(content, replyToEvent, { permalinkCreator, includeLegacyFallback: true }); // Clear reply_to_event as we put the message into the queue // if the send fails, retry will handle resending. _dispatcher.default.dispatch({ action: "reply_to_event", event: null, context: this.context.timelineRenderingType }); } (0, _localRoom.doMaybeLocalRoomAction)(this.props.room.roomId, actualRoomId => _MatrixClientPeg.MatrixClientPeg.safeGet().sendMessage(actualRoomId, content), this.props.room.client); } catch (e) { _logger.logger.error("Error sending voice message:", e); // Voice message should be in the timeline at this point, so let other things take care // of error handling. We also shouldn't need the recording anymore, so fall through to // disposal. } await this.disposeRecording(); } async disposeRecording() { await _VoiceRecordingStore.VoiceRecordingStore.instance.disposeRecording(this.voiceRecordingId); // Reset back to no recording, which means no phase (ie: restart component entirely) this.setState({ recorder: undefined, recordingPhase: undefined, didUploadFail: false }); } bindNewRecorder(recorder) { if (this.state.recorder) { this.state.recorder.off(_AsyncStore.UPDATE_EVENT, this.onRecordingUpdate); } if (recorder) { recorder.on(_AsyncStore.UPDATE_EVENT, this.onRecordingUpdate); } } renderWaveformArea() { if (!this.state.recorder) return null; // no recorder means we're not recording: no waveform if (this.state.recordingPhase !== _VoiceRecording.RecordingState.Started) { return /*#__PURE__*/_react.default.createElement(_RecordingPlayback.default, { playback: this.state.recorder.getPlayback(), layout: _RecordingPlayback.PlaybackLayout.Composer }); } // only other UI is the recording-in-progress UI return /*#__PURE__*/_react.default.createElement("div", { className: "mx_MediaBody mx_VoiceMessagePrimaryContainer mx_VoiceRecordComposerTile_recording" }, /*#__PURE__*/_react.default.createElement(_LiveRecordingClock.default, { recorder: this.state.recorder }), /*#__PURE__*/_react.default.createElement(_LiveRecordingWaveform.default, { recorder: this.state.recorder })); } render() { if (!this.state.recordingPhase) return null; let stopBtn; let deleteButton; if (this.state.recordingPhase === _VoiceRecording.RecordingState.Started) { let tooltip = (0, _languageHandler._t)("composer|send_voice_message"); if (!!this.state.recorder) { tooltip = (0, _languageHandler._t)("composer|stop_voice_message"); } stopBtn = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { className: "mx_VoiceRecordComposerTile_stop", onClick: this.onRecordStartEndClick, title: tooltip }); if (this.state.recorder && !this.state.recorder?.isRecording) { stopBtn = null; } } if (this.state.recorder && this.state.recordingPhase !== _VoiceRecording.RecordingState.Uploading) { deleteButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { className: "mx_VoiceRecordComposerTile_delete", title: (0, _languageHandler._t)("action|delete"), onClick: this.onCancel }); } let uploadIndicator; if (this.state.recordingPhase === _VoiceRecording.RecordingState.Uploading) { uploadIndicator = /*#__PURE__*/_react.default.createElement("span", { className: "mx_VoiceRecordComposerTile_uploadingState" }, /*#__PURE__*/_react.default.createElement(_InlineSpinner.default, { w: 16, h: 16 })); } else if (this.state.didUploadFail && this.state.recordingPhase === _VoiceRecording.RecordingState.Ended) { uploadIndicator = /*#__PURE__*/_react.default.createElement("span", { className: "mx_VoiceRecordComposerTile_failedState" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_VoiceRecordComposerTile_uploadState_badge" }, /*#__PURE__*/_react.default.createElement(_NotificationBadge.default, { notification: _StaticNotificationState.StaticNotificationState.forSymbol("!", _NotificationLevel.NotificationLevel.Highlight) })), /*#__PURE__*/_react.default.createElement("span", { className: "text-warning" }, (0, _languageHandler._t)("timeline|send_state_failed"))); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, uploadIndicator, deleteButton, stopBtn, this.renderWaveformArea()); } } exports.default = VoiceRecordComposerTile; (0, _defineProperty2.default)(VoiceRecordComposerTile, "contextType", _RoomContext.default); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX1ZvaWNlUmVjb3JkaW5nIiwiX01hdHJpeENsaWVudFBlZyIsIl9MaXZlUmVjb3JkaW5nV2F2ZWZvcm0iLCJfTGl2ZVJlY29yZGluZ0Nsb2NrIiwiX1ZvaWNlUmVjb3JkaW5nU3RvcmUiLCJfQXN5bmNTdG9yZSIsIl9SZWNvcmRpbmdQbGF5YmFjayIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwiX01vZGFsIiwiX0Vycm9yRGlhbG9nIiwiX01lZGlhRGV2aWNlSGFuZGxlciIsIl9Ob3RpZmljYXRpb25CYWRnZSIsIl9TdGF0aWNOb3RpZmljYXRpb25TdGF0ZSIsIl9Ob3RpZmljYXRpb25MZXZlbCIsIl9JbmxpbmVTcGlubmVyIiwiX1BsYXliYWNrTWFuYWdlciIsIl9sb2NhbFJvb20iLCJfZGlzcGF0Y2hlciIsIl9TZW5kTWVzc2FnZUNvbXBvc2VyIiwiX1JlcGx5IiwiX1Jvb21Db250ZXh0IiwiX2NyZWF0ZVZvaWNlTWVzc2FnZUNvbnRlbnQiLCJfQWNjZXNzaWJsZUJ1dHRvbiIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIlZvaWNlUmVjb3JkQ29tcG9zZXJUaWxlIiwiUmVhY3QiLCJQdXJlQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsImNvbnRleHQiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGlzcG9zZVJlY29yZGluZyIsInN0YXRlIiwicmVjb3JkZXIiLCJzdG9wIiwiYWNjZXNzRXJyb3IiLCJNb2RhbCIsImNyZWF0ZURpYWxvZyIsIkVycm9yRGlhbG9nIiwidGl0bGUiLCJfdCIsImRlc2NyaXB0aW9uIiwiY3JlYXRlRWxlbWVudCIsIkZyYWdtZW50IiwiZGV2aWNlcyIsIk1lZGlhRGV2aWNlSGFuZGxlciIsImdldERldmljZXMiLCJNZWRpYURldmljZUtpbmRFbnVtIiwiQXVkaW9JbnB1dCIsImxlbmd0aCIsImxvZ2dlciIsImVycm9yIiwiUGxheWJhY2tNYW5hZ2VyIiwiaW5zdGFuY2UiLCJwYXVzZUFsbEV4Y2VwdCIsIlZvaWNlUmVjb3JkaW5nU3RvcmUiLCJzdGFydFJlY29yZGluZyIsInZvaWNlUmVjb3JkaW5nSWQiLCJzdGFydCIsImJpbmROZXdSZWNvcmRlciIsInNldFN0YXRlIiwicmVjb3JkaW5nUGhhc2UiLCJSZWNvcmRpbmdTdGF0ZSIsIlN0YXJ0ZWQiLCJldiIsIkVuZGluZ1Nvb24iLCJnZXRWb2ljZVJlY29yZGluZ0lkIiwicm9vbSIsInJlbGF0aW9uIiwiY29tcG9uZW50RGlkTW91bnQiLCJnZXRBY3RpdmVSZWNvcmRpbmciLCJpc1JlY29yZGluZyIsImhhc1JlY29yZGluZyIsIndhcm4iLCJFbmRlZCIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwicmVjb3JkaW5nIiwic2VuZCIsIkVycm9yIiwicmVwbHlUb0V2ZW50IiwicGVybWFsaW5rQ3JlYXRvciIsInVwbG9hZCIsImRpZFVwbG9hZEZhaWwiLCJjb250ZW50IiwiY3JlYXRlVm9pY2VNZXNzYWdlQ29udGVudCIsIm14YyIsImNvbnRlbnRUeXBlIiwiTWF0aCIsInJvdW5kIiwiZHVyYXRpb25TZWNvbmRzIiwiY29udGVudExlbmd0aCIsImVuY3J5cHRlZCIsImdldFBsYXliYWNrIiwidGh1bWJuYWlsV2F2ZWZvcm0iLCJtYXAiLCJ2IiwiYXR0YWNoTWVudGlvbnMiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwiZ2V0U2FmZVVzZXJJZCIsImF0dGFjaFJlbGF0aW9uIiwiYWRkUmVwbHlUb01lc3NhZ2VDb250ZW50IiwiaW5jbHVkZUxlZ2FjeUZhbGxiYWNrIiwiZGVmYXVsdERpc3BhdGNoZXIiLCJkaXNwYXRjaCIsImFjdGlvbiIsImV2ZW50IiwidGltZWxpbmVSZW5kZXJpbmdUeXBlIiwiZG9NYXliZUxvY2FsUm9vbUFjdGlvbiIsInJvb21JZCIsImFjdHVhbFJvb21JZCIsInNlbmRNZXNzYWdlIiwiY2xpZW50IiwidW5kZWZpbmVkIiwib2ZmIiwiVVBEQVRFX0VWRU5UIiwib25SZWNvcmRpbmdVcGRhdGUiLCJvbiIsInJlbmRlcldhdmVmb3JtQXJlYSIsInBsYXliYWNrIiwibGF5b3V0IiwiUGxheWJhY2tMYXlvdXQiLCJDb21wb3NlciIsImNsYXNzTmFtZSIsInJlbmRlciIsInN0b3BCdG4iLCJkZWxldGVCdXR0b24iLCJ0b29sdGlwIiwib25DbGljayIsIm9uUmVjb3JkU3RhcnRFbmRDbGljayIsIlVwbG9hZGluZyIsIm9uQ2FuY2VsIiwidXBsb2FkSW5kaWNhdG9yIiwidyIsImgiLCJub3RpZmljYXRpb24iLCJTdGF0aWNOb3RpZmljYXRpb25TdGF0ZSIsImZvclN5bWJvbCIsIk5vdGlmaWNhdGlvbkxldmVsIiwiSGlnaGxpZ2h0IiwiZXhwb3J0cyIsIlJvb21Db250ZXh0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdmlld3Mvcm9vbXMvVm9pY2VSZWNvcmRDb21wb3NlclRpbGUudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDIxLCAyMDIyIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBSZWFjdE5vZGUgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IFJvb20sIElFdmVudFJlbGF0aW9uLCBNYXRyaXhFdmVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcbmltcG9ydCB7IE9wdGlvbmFsIH0gZnJvbSBcIm1hdHJpeC1ldmVudHMtc2RrXCI7XG5cbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IHsgUmVjb3JkaW5nU3RhdGUgfSBmcm9tIFwiLi4vLi4vLi4vYXVkaW8vVm9pY2VSZWNvcmRpbmdcIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBMaXZlUmVjb3JkaW5nV2F2ZWZvcm0gZnJvbSBcIi4uL2F1ZGlvX21lc3NhZ2VzL0xpdmVSZWNvcmRpbmdXYXZlZm9ybVwiO1xuaW1wb3J0IExpdmVSZWNvcmRpbmdDbG9jayBmcm9tIFwiLi4vYXVkaW9fbWVzc2FnZXMvTGl2ZVJlY29yZGluZ0Nsb2NrXCI7XG5pbXBvcnQgeyBWb2ljZVJlY29yZGluZ1N0b3JlIH0gZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9Wb2ljZVJlY29yZGluZ1N0b3JlXCI7XG5pbXBvcnQgeyBVUERBVEVfRVZFTlQgfSBmcm9tIFwiLi4vLi4vLi4vc3RvcmVzL0FzeW5jU3RvcmVcIjtcbmltcG9ydCBSZWNvcmRpbmdQbGF5YmFjaywgeyBQbGF5YmFja0xheW91dCB9IGZyb20gXCIuLi9hdWRpb19tZXNzYWdlcy9SZWNvcmRpbmdQbGF5YmFja1wiO1xuaW1wb3J0IE1vZGFsIGZyb20gXCIuLi8uLi8uLi9Nb2RhbFwiO1xuaW1wb3J0IEVycm9yRGlhbG9nIGZyb20gXCIuLi9kaWFsb2dzL0Vycm9yRGlhbG9nXCI7XG5pbXBvcnQgTWVkaWFEZXZpY2VIYW5kbGVyLCB7IE1lZGlhRGV2aWNlS2luZEVudW0gfSBmcm9tIFwiLi4vLi4vLi4vTWVkaWFEZXZpY2VIYW5kbGVyXCI7XG5pbXBvcnQgTm90aWZpY2F0aW9uQmFkZ2UgZnJvbSBcIi4vTm90aWZpY2F0aW9uQmFkZ2VcIjtcbmltcG9ydCB7IFN0YXRpY05vdGlmaWNhdGlvblN0YXRlIH0gZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9ub3RpZmljYXRpb25zL1N0YXRpY05vdGlmaWNhdGlvblN0YXRlXCI7XG5pbXBvcnQgeyBOb3RpZmljYXRpb25MZXZlbCB9IGZyb20gXCIuLi8uLi8uLi9zdG9yZXMvbm90aWZpY2F0aW9ucy9Ob3RpZmljYXRpb25MZXZlbFwiO1xuaW1wb3J0IElubGluZVNwaW5uZXIgZnJvbSBcIi4uL2VsZW1lbnRzL0lubGluZVNwaW5uZXJcIjtcbmltcG9ydCB7IFBsYXliYWNrTWFuYWdlciB9IGZyb20gXCIuLi8uLi8uLi9hdWRpby9QbGF5YmFja01hbmFnZXJcIjtcbmltcG9ydCB7IGRvTWF5YmVMb2NhbFJvb21BY3Rpb24gfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvbG9jYWwtcm9vbVwiO1xuaW1wb3J0IGRlZmF1bHREaXNwYXRjaGVyIGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCB7IGF0dGFjaE1lbnRpb25zLCBhdHRhY2hSZWxhdGlvbiB9IGZyb20gXCIuL1NlbmRNZXNzYWdlQ29tcG9zZXJcIjtcbmltcG9ydCB7IGFkZFJlcGx5VG9NZXNzYWdlQ29udGVudCB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9SZXBseVwiO1xuaW1wb3J0IHsgUm9vbVBlcm1hbGlua0NyZWF0b3IgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvcGVybWFsaW5rcy9QZXJtYWxpbmtzXCI7XG5pbXBvcnQgUm9vbUNvbnRleHQgZnJvbSBcIi4uLy4uLy4uL2NvbnRleHRzL1Jvb21Db250ZXh0XCI7XG5pbXBvcnQgeyBJVXBsb2FkLCBWb2ljZU1lc3NhZ2VSZWNvcmRpbmcgfSBmcm9tIFwiLi4vLi4vLi4vYXVkaW8vVm9pY2VNZXNzYWdlUmVjb3JkaW5nXCI7XG5pbXBvcnQgeyBjcmVhdGVWb2ljZU1lc3NhZ2VDb250ZW50IH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL2NyZWF0ZVZvaWNlTWVzc2FnZUNvbnRlbnRcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIHJvb206IFJvb207XG4gICAgcGVybWFsaW5rQ3JlYXRvcj86IFJvb21QZXJtYWxpbmtDcmVhdG9yO1xuICAgIHJlbGF0aW9uPzogSUV2ZW50UmVsYXRpb247XG4gICAgcmVwbHlUb0V2ZW50PzogTWF0cml4RXZlbnQ7XG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIHJlY29yZGVyPzogVm9pY2VNZXNzYWdlUmVjb3JkaW5nO1xuICAgIHJlY29yZGluZ1BoYXNlPzogUmVjb3JkaW5nU3RhdGU7XG4gICAgZGlkVXBsb2FkRmFpbD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogQ29udGFpbmVyIHRpbGUgZm9yIHJlbmRlcmluZyB0aGUgdm9pY2UgbWVzc2FnZSByZWNvcmRlciBpbiB0aGUgY29tcG9zZXIuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZvaWNlUmVjb3JkQ29tcG9zZXJUaWxlIGV4dGVuZHMgUmVhY3QuUHVyZUNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIHB1YmxpYyBzdGF0aWMgY29udGV4dFR5cGUgPSBSb29tQ29udGV4dDtcbiAgICBwdWJsaWMgZGVjbGFyZSBjb250ZXh0OiBSZWFjdC5Db250ZXh0VHlwZTx0eXBlb2YgUm9vbUNvbnRleHQ+O1xuICAgIHByaXZhdGUgdm9pY2VSZWNvcmRpbmdJZDogc3RyaW5nO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMsIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBSb29tQ29udGV4dD4pIHtcbiAgICAgICAgc3VwZXIocHJvcHMsIGNvbnRleHQpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSB7fTtcblxuICAgICAgICB0aGlzLnZvaWNlUmVjb3JkaW5nSWQgPSBWb2ljZVJlY29yZGluZ1N0b3JlLmdldFZvaWNlUmVjb3JkaW5nSWQodGhpcy5wcm9wcy5yb29tLCB0aGlzLnByb3BzLnJlbGF0aW9uKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJlY29yZGVyID0gVm9pY2VSZWNvcmRpbmdTdG9yZS5pbnN0YW5jZS5nZXRBY3RpdmVSZWNvcmRpbmcodGhpcy52b2ljZVJlY29yZGluZ0lkKTtcbiAgICAgICAgaWYgKHJlY29yZGVyKSB7XG4gICAgICAgICAgICBpZiAocmVjb3JkZXIuaXNSZWNvcmRpbmcgfHwgIXJlY29yZGVyLmhhc1JlY29yZGluZykge1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiQ2FjaGVkIHJlY29yZGluZyBoYXNuJ3QgZW5kZWQgeWV0IGFuZCBtaWdodCBjYXVzZSBpc3N1ZXNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmJpbmROZXdSZWNvcmRlcihyZWNvcmRlcik7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgcmVjb3JkZXIsIHJlY29yZGluZ1BoYXNlOiBSZWNvcmRpbmdTdGF0ZS5FbmRlZCB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBjb21wb25lbnRXaWxsVW5tb3VudCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgLy8gU3RvcCByZWNvcmRpbmcsIGJ1dCBrZWVwIHRoZSByZWNvcmRpbmcgbWVtb3J5IChkb24ndCBkaXNwb3NlIGl0KS4gVGhpcyBpcyB0byBsZXQgdGhlIHVzZXJcbiAgICAgICAgLy8gY29tZSBiYWNrIGFuZCBmaW5pc2ggd29ya2luZyB3aXRoIGl0LlxuICAgICAgICBjb25zdCByZWNvcmRpbmcgPSBWb2ljZVJlY29yZGluZ1N0b3JlLmluc3RhbmNlLmdldEFjdGl2ZVJlY29yZGluZyh0aGlzLnZvaWNlUmVjb3JkaW5nSWQpO1xuICAgICAgICBhd2FpdCByZWNvcmRpbmc/LnN0b3AoKTtcblxuICAgICAgICAvLyBDbGVhbiB1cCBvdXIgbGlzdGVuZXJzIGJ5IGJpbmRpbmcgYSBmYWxzeSByZWNvcmRlclxuICAgICAgICB0aGlzLmJpbmROZXdSZWNvcmRlcihudWxsKTtcbiAgICB9XG5cbiAgICAvLyBjYWxsZWQgYnkgY29tcG9zZXJcbiAgICBwdWJsaWMgYXN5bmMgc2VuZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnJlY29yZGVyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyByZWNvcmRpbmcgc3RhcnRlZCAtIGNhbm5vdCBzZW5kIGFueXRoaW5nXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyByZXBseVRvRXZlbnQsIHJlbGF0aW9uLCBwZXJtYWxpbmtDcmVhdG9yIH0gPSB0aGlzLnByb3BzO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuc3RhdGUucmVjb3JkZXIuc3RvcCgpO1xuXG4gICAgICAgIGxldCB1cGxvYWQ6IElVcGxvYWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB1cGxvYWQgPSBhd2FpdCB0aGlzLnN0YXRlLnJlY29yZGVyLnVwbG9hZCh0aGlzLnZvaWNlUmVjb3JkaW5nSWQpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciB1cGxvYWRpbmcgdm9pY2UgbWVzc2FnZTpcIiwgZSk7XG5cbiAgICAgICAgICAgIC8vIEZsYWcgZXJyb3IgYW5kIG1vdmUgb24uIFRoZSByZWNvcmRpbmcgcGhhc2Ugd2lsbCBiZSByZXNldCBieSB0aGUgdXBsb2FkIGZ1bmN0aW9uLlxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGRpZFVwbG9hZEZhaWw6IHRydWUgfSk7XG5cbiAgICAgICAgICAgIHJldHVybjsgLy8gZG9uJ3QgZGlzcG9zZSB0aGUgcmVjb3JkaW5nOiB0aGUgdXNlciBoYXMgYSBjaGFuY2UgdG8gcmUtdXBsb2FkXG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gbm9pbnNwZWN0aW9uIEVTNk1pc3NpbmdBd2FpdCAtIHdlIGRvbid0IGNhcmUgaWYgaXQgZmFpbHMsIGl0J2xsIGdldCBxdWV1ZWQuXG4gICAgICAgICAgICBjb25zdCBjb250ZW50ID0gY3JlYXRlVm9pY2VNZXNzYWdlQ29udGVudChcbiAgICAgICAgICAgICAgICB1cGxvYWQubXhjLFxuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUucmVjb3JkZXIuY29udGVudFR5cGUsXG4gICAgICAgICAgICAgICAgTWF0aC5yb3VuZCh0aGlzLnN0YXRlLnJlY29yZGVyLmR1cmF0aW9uU2Vjb25kcyAqIDEwMDApLFxuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUucmVjb3JkZXIuY29udGVudExlbmd0aCxcbiAgICAgICAgICAgICAgICB1cGxvYWQuZW5jcnlwdGVkLFxuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUucmVjb3JkZXIuZ2V0UGxheWJhY2soKS50aHVtYm5haWxXYXZlZm9ybS5tYXAoKHYpID0+IE1hdGgucm91bmQodiAqIDEwMjQpKSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCBtZW50aW9ucywgd2hpY2ggcmVhbGx5IG9ubHkgYXBwbGllcyBpZiB0aGVyZSdzIGEgcmVwbHlUb0V2ZW50LlxuICAgICAgICAgICAgYXR0YWNoTWVudGlvbnMoTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRTYWZlVXNlcklkKCksIGNvbnRlbnQsIG51bGwsIHJlcGx5VG9FdmVudCk7XG4gICAgICAgICAgICBhdHRhY2hSZWxhdGlvbihjb250ZW50LCByZWxhdGlvbik7XG4gICAgICAgICAgICBpZiAocmVwbHlUb0V2ZW50KSB7XG4gICAgICAgICAgICAgICAgYWRkUmVwbHlUb01lc3NhZ2VDb250ZW50KGNvbnRlbnQsIHJlcGx5VG9FdmVudCwge1xuICAgICAgICAgICAgICAgICAgICBwZXJtYWxpbmtDcmVhdG9yLFxuICAgICAgICAgICAgICAgICAgICBpbmNsdWRlTGVnYWN5RmFsbGJhY2s6IHRydWUsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gQ2xlYXIgcmVwbHlfdG9fZXZlbnQgYXMgd2UgcHV0IHRoZSBtZXNzYWdlIGludG8gdGhlIHF1ZXVlXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIHNlbmQgZmFpbHMsIHJldHJ5IHdpbGwgaGFuZGxlIHJlc2VuZGluZy5cbiAgICAgICAgICAgICAgICBkZWZhdWx0RGlzcGF0Y2hlci5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogXCJyZXBseV90b19ldmVudFwiLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dDogdGhpcy5jb250ZXh0LnRpbWVsaW5lUmVuZGVyaW5nVHlwZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZG9NYXliZUxvY2FsUm9vbUFjdGlvbihcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BzLnJvb20ucm9vbUlkLFxuICAgICAgICAgICAgICAgIChhY3R1YWxSb29tSWQ6IHN0cmluZykgPT4gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5zZW5kTWVzc2FnZShhY3R1YWxSb29tSWQsIGNvbnRlbnQpLFxuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMucm9vbS5jbGllbnQsXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciBzZW5kaW5nIHZvaWNlIG1lc3NhZ2U6XCIsIGUpO1xuXG4gICAgICAgICAgICAvLyBWb2ljZSBtZXNzYWdlIHNob3VsZCBiZSBpbiB0aGUgdGltZWxpbmUgYXQgdGhpcyBwb2ludCwgc28gbGV0IG90aGVyIHRoaW5ncyB0YWtlIGNhcmVcbiAgICAgICAgICAgIC8vIG9mIGVycm9yIGhhbmRsaW5nLiBXZSBhbHNvIHNob3VsZG4ndCBuZWVkIHRoZSByZWNvcmRpbmcgYW55bW9yZSwgc28gZmFsbCB0aHJvdWdoIHRvXG4gICAgICAgICAgICAvLyBkaXNwb3NhbC5cbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLmRpc3Bvc2VSZWNvcmRpbmcoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGRpc3Bvc2VSZWNvcmRpbmcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IFZvaWNlUmVjb3JkaW5nU3RvcmUuaW5zdGFuY2UuZGlzcG9zZVJlY29yZGluZyh0aGlzLnZvaWNlUmVjb3JkaW5nSWQpO1xuXG4gICAgICAgIC8vIFJlc2V0IGJhY2sgdG8gbm8gcmVjb3JkaW5nLCB3aGljaCBtZWFucyBubyBwaGFzZSAoaWU6IHJlc3RhcnQgY29tcG9uZW50IGVudGlyZWx5KVxuICAgICAgICB0aGlzLnNldFN0YXRlKHsgcmVjb3JkZXI6IHVuZGVmaW5lZCwgcmVjb3JkaW5nUGhhc2U6IHVuZGVmaW5lZCwgZGlkVXBsb2FkRmFpbDogZmFsc2UgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkNhbmNlbCA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNwb3NlUmVjb3JkaW5nKCk7XG4gICAgfTtcblxuICAgIHB1YmxpYyBvblJlY29yZFN0YXJ0RW5kQ2xpY2sgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnJlY29yZGVyKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnN0YXRlLnJlY29yZGVyLnN0b3AoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZSBcIm1pY3JvcGhvbmUgYWNjZXNzIGVycm9yXCIgZGlhbG9ncyBhcmUgdXNlZCBhIGxvdCwgc28gbGV0J3MgZnVuY3Rpb25pZnkgdGhlbVxuICAgICAgICBjb25zdCBhY2Nlc3NFcnJvciA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhFcnJvckRpYWxvZywge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBfdChcInZvaXB8dW5hYmxlX3RvX2FjY2Vzc19hdWRpb19pbnB1dF90aXRsZVwiKSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogKFxuICAgICAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICAgICAgPHA+e190KFwidm9pcHx1bmFibGVfdG9fYWNjZXNzX2F1ZGlvX2lucHV0X2Rlc2NyaXB0aW9uXCIpfTwvcD5cbiAgICAgICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIERvIGEgc2FuaXR5IHRlc3QgdG8gZW5zdXJlIHdlJ3JlIGFib3V0IHRvIGdyYWIgYSB2YWxpZCBtaWNyb3Bob25lIHJlZmVyZW5jZS4gVGhpbmdzIG1pZ2h0XG4gICAgICAgIC8vIGNoYW5nZSBiZXR3ZWVuIHRoaXMgYW5kIHJlY29yZGluZywgYnV0IGF0IGxlYXN0IHdlIHdpbGwgaGF2ZSB0cmllZC5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGRldmljZXMgPSBhd2FpdCBNZWRpYURldmljZUhhbmRsZXIuZ2V0RGV2aWNlcygpO1xuICAgICAgICAgICAgaWYgKCFkZXZpY2VzPy5bTWVkaWFEZXZpY2VLaW5kRW51bS5BdWRpb0lucHV0XT8ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiBfdChcInZvaXB8bm9fYXVkaW9faW5wdXRfdGl0bGVcIiksXG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAoXG4gICAgICAgICAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwPntfdChcInZvaXB8bm9fYXVkaW9faW5wdXRfZGVzY3JpcHRpb25cIil9PC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZWxzZSB3ZSBwcm9iYWJseSBoYXZlIGEgZGV2aWNlIHRoYXQgaXMgZ29vZCBlbm91Z2hcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiRXJyb3IgZ2V0dGluZyBkZXZpY2VzOiBcIiwgZSk7XG4gICAgICAgICAgICBhY2Nlc3NFcnJvcigpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIHN0b3AgYW55IG5vaXNlcyB3aGljaCBtaWdodCBiZSBoYXBwZW5pbmdcbiAgICAgICAgICAgIFBsYXliYWNrTWFuYWdlci5pbnN0YW5jZS5wYXVzZUFsbEV4Y2VwdCgpO1xuICAgICAgICAgICAgY29uc3QgcmVjb3JkZXIgPSBWb2ljZVJlY29yZGluZ1N0b3JlLmluc3RhbmNlLnN0YXJ0UmVjb3JkaW5nKHRoaXMudm9pY2VSZWNvcmRpbmdJZCk7XG4gICAgICAgICAgICBhd2FpdCByZWNvcmRlci5zdGFydCgpO1xuXG4gICAgICAgICAgICB0aGlzLmJpbmROZXdSZWNvcmRlcihyZWNvcmRlcik7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyByZWNvcmRlciwgcmVjb3JkaW5nUGhhc2U6IFJlY29yZGluZ1N0YXRlLlN0YXJ0ZWQgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHN0YXJ0aW5nIHJlY29yZGluZzogXCIsIGUpO1xuICAgICAgICAgICAgYWNjZXNzRXJyb3IoKTtcblxuICAgICAgICAgICAgLy8gbm9pbnNwZWN0aW9uIEVTNk1pc3NpbmdBd2FpdCAtIGlmIHRoaXMgZ29lcyB3cm9uZyB3ZSBkb24ndCB3YW50IGl0IHRvIGFmZmVjdCB0aGUgY2FsbCBzdGFja1xuICAgICAgICAgICAgVm9pY2VSZWNvcmRpbmdTdG9yZS5pbnN0YW5jZS5kaXNwb3NlUmVjb3JkaW5nKHRoaXMudm9pY2VSZWNvcmRpbmdJZCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBiaW5kTmV3UmVjb3JkZXIocmVjb3JkZXI6IE9wdGlvbmFsPFZvaWNlTWVzc2FnZVJlY29yZGluZz4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUucmVjb3JkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuc3RhdGUucmVjb3JkZXIub2ZmKFVQREFURV9FVkVOVCwgdGhpcy5vblJlY29yZGluZ1VwZGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlY29yZGVyKSB7XG4gICAgICAgICAgICByZWNvcmRlci5vbihVUERBVEVfRVZFTlQsIHRoaXMub25SZWNvcmRpbmdVcGRhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblJlY29yZGluZ1VwZGF0ZSA9IChldjogUmVjb3JkaW5nU3RhdGUpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKGV2ID09PSBSZWNvcmRpbmdTdGF0ZS5FbmRpbmdTb29uKSByZXR1cm47IC8vIGlnbm9yZSB0aGlzIHN0YXRlOiBpdCBoYXMgbm8gVUkgcHVycG9zZSBoZXJlXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyByZWNvcmRpbmdQaGFzZTogZXYgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgcmVuZGVyV2F2ZWZvcm1BcmVhKCk6IFJlYWN0Tm9kZSB7XG4gICAgICAgIGlmICghdGhpcy5zdGF0ZS5yZWNvcmRlcikgcmV0dXJuIG51bGw7IC8vIG5vIHJlY29yZGVyIG1lYW5zIHdlJ3JlIG5vdCByZWNvcmRpbmc6IG5vIHdhdmVmb3JtXG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUucmVjb3JkaW5nUGhhc2UgIT09IFJlY29yZGluZ1N0YXRlLlN0YXJ0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiA8UmVjb3JkaW5nUGxheWJhY2sgcGxheWJhY2s9e3RoaXMuc3RhdGUucmVjb3JkZXIuZ2V0UGxheWJhY2soKX0gbGF5b3V0PXtQbGF5YmFja0xheW91dC5Db21wb3Nlcn0gLz47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBvbmx5IG90aGVyIFVJIGlzIHRoZSByZWNvcmRpbmctaW4tcHJvZ3Jlc3MgVUlcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfTWVkaWFCb2R5IG14X1ZvaWNlTWVzc2FnZVByaW1hcnlDb250YWluZXIgbXhfVm9pY2VSZWNvcmRDb21wb3NlclRpbGVfcmVjb3JkaW5nXCI+XG4gICAgICAgICAgICAgICAgPExpdmVSZWNvcmRpbmdDbG9jayByZWNvcmRlcj17dGhpcy5zdGF0ZS5yZWNvcmRlcn0gLz5cbiAgICAgICAgICAgICAgICA8TGl2ZVJlY29yZGluZ1dhdmVmb3JtIHJlY29yZGVyPXt0aGlzLnN0YXRlLnJlY29yZGVyfSAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbmRlcigpOiBSZWFjdE5vZGUge1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGUucmVjb3JkaW5nUGhhc2UpIHJldHVybiBudWxsO1xuXG4gICAgICAgIGxldCBzdG9wQnRuO1xuICAgICAgICBsZXQgZGVsZXRlQnV0dG9uO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5yZWNvcmRpbmdQaGFzZSA9PT0gUmVjb3JkaW5nU3RhdGUuU3RhcnRlZCkge1xuICAgICAgICAgICAgbGV0IHRvb2x0aXAgPSBfdChcImNvbXBvc2VyfHNlbmRfdm9pY2VfbWVzc2FnZVwiKTtcbiAgICAgICAgICAgIGlmICghIXRoaXMuc3RhdGUucmVjb3JkZXIpIHtcbiAgICAgICAgICAgICAgICB0b29sdGlwID0gX3QoXCJjb21wb3NlcnxzdG9wX3ZvaWNlX21lc3NhZ2VcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN0b3BCdG4gPSAoXG4gICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfVm9pY2VSZWNvcmRDb21wb3NlclRpbGVfc3RvcFwiXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25SZWNvcmRTdGFydEVuZENsaWNrfVxuICAgICAgICAgICAgICAgICAgICB0aXRsZT17dG9vbHRpcH1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnJlY29yZGVyICYmICF0aGlzLnN0YXRlLnJlY29yZGVyPy5pc1JlY29yZGluZykge1xuICAgICAgICAgICAgICAgIHN0b3BCdG4gPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc3RhdGUucmVjb3JkZXIgJiYgdGhpcy5zdGF0ZS5yZWNvcmRpbmdQaGFzZSAhPT0gUmVjb3JkaW5nU3RhdGUuVXBsb2FkaW5nKSB7XG4gICAgICAgICAgICBkZWxldGVCdXR0b24gPSAoXG4gICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfVm9pY2VSZWNvcmRDb21wb3NlclRpbGVfZGVsZXRlXCJcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU9e190KFwiYWN0aW9ufGRlbGV0ZVwiKX1cbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vbkNhbmNlbH1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB1cGxvYWRJbmRpY2F0b3I7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnJlY29yZGluZ1BoYXNlID09PSBSZWNvcmRpbmdTdGF0ZS5VcGxvYWRpbmcpIHtcbiAgICAgICAgICAgIHVwbG9hZEluZGljYXRvciA9IChcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9Wb2ljZVJlY29yZENvbXBvc2VyVGlsZV91cGxvYWRpbmdTdGF0ZVwiPlxuICAgICAgICAgICAgICAgICAgICA8SW5saW5lU3Bpbm5lciB3PXsxNn0gaD17MTZ9IC8+XG4gICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmRpZFVwbG9hZEZhaWwgJiYgdGhpcy5zdGF0ZS5yZWNvcmRpbmdQaGFzZSA9PT0gUmVjb3JkaW5nU3RhdGUuRW5kZWQpIHtcbiAgICAgICAgICAgIHVwbG9hZEluZGljYXRvciA9IChcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9Wb2ljZVJlY29yZENvbXBvc2VyVGlsZV9mYWlsZWRTdGF0ZVwiPlxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9Wb2ljZVJlY29yZENvbXBvc2VyVGlsZV91cGxvYWRTdGF0ZV9iYWRnZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgey8qIE5lZWQgdG8gc3RpY2sgdGhlIGJhZGdlIGluIGEgc3BhbiB0byBlbnN1cmUgaXQgZG9lc24ndCBjcmVhdGUgYSBibG9jayBjb21wb25lbnQgKi99XG4gICAgICAgICAgICAgICAgICAgICAgICA8Tm90aWZpY2F0aW9uQmFkZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3RpZmljYXRpb249e1N0YXRpY05vdGlmaWNhdGlvblN0YXRlLmZvclN5bWJvbChcIiFcIiwgTm90aWZpY2F0aW9uTGV2ZWwuSGlnaGxpZ2h0KX1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC13YXJuaW5nXCI+e190KFwidGltZWxpbmV8c2VuZF9zdGF0ZV9mYWlsZWRcIil9PC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICB7dXBsb2FkSW5kaWNhdG9yfVxuICAgICAgICAgICAgICAgIHtkZWxldGVCdXR0b259XG4gICAgICAgICAgICAgICAge3N0b3BCdG59XG4gICAgICAgICAgICAgICAge3RoaXMucmVuZGVyV2F2ZWZvcm1BcmVhKCl9XG4gICAgICAgICAgICA8Lz5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBR0EsSUFBQUUsZ0JBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLGVBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLGdCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxzQkFBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sbUJBQUEsR0FBQVAsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFPLG9CQUFBLEdBQUFQLE9BQUE7QUFDQSxJQUFBUSxXQUFBLEdBQUFSLE9BQUE7QUFDQSxJQUFBUyxrQkFBQSxHQUFBQyx1QkFBQSxDQUFBVixPQUFBO0FBQ0EsSUFBQVcsTUFBQSxHQUFBWixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVksWUFBQSxHQUFBYixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQWEsbUJBQUEsR0FBQUgsdUJBQUEsQ0FBQVYsT0FBQTtBQUNBLElB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