matrix-react-sdk
Version:
SDK for matrix.org using React
201 lines (198 loc) • 39.2 kB
JavaScript
;
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 _call = require("matrix-js-sdk/src/webrtc/call");
var _languageHandler = require("../../../../../languageHandler");
var _MediaDeviceHandler = _interopRequireWildcard(require("../../../../../MediaDeviceHandler"));
var _Field = _interopRequireDefault(require("../../../elements/Field"));
var _AccessibleButton = _interopRequireDefault(require("../../../elements/AccessibleButton"));
var _SettingLevel = require("../../../../../settings/SettingLevel");
var _SettingsFlag = _interopRequireDefault(require("../../../elements/SettingsFlag"));
var _LabelledToggleSwitch = _interopRequireDefault(require("../../../elements/LabelledToggleSwitch"));
var _requestMediaPermissions = require("../../../../../utils/media/requestMediaPermissions");
var _SettingsTab = _interopRequireDefault(require("../SettingsTab"));
var _SettingsSection = require("../../shared/SettingsSection");
var _SettingsSubsection = _interopRequireDefault(require("../../shared/SettingsSubsection"));
var _MatrixClientContext = _interopRequireDefault(require("../../../../../contexts/MatrixClientContext"));
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 2020 The Matrix.org Foundation C.I.C.
Copyright 2019 New Vector Ltd
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
/**
* Maps deviceKind to the right get method on MediaDeviceHandler
* Helpful for setting state
*/
const mapDeviceKindToHandlerValue = deviceKind => {
switch (deviceKind) {
case _MediaDeviceHandler.MediaDeviceKindEnum.AudioOutput:
return _MediaDeviceHandler.default.getAudioOutput();
case _MediaDeviceHandler.MediaDeviceKindEnum.AudioInput:
return _MediaDeviceHandler.default.getAudioInput();
case _MediaDeviceHandler.MediaDeviceKindEnum.VideoInput:
return _MediaDeviceHandler.default.getVideoInput();
}
};
class VoiceUserSettingsTab extends _react.default.Component {
constructor(props, context) {
super(props, context);
(0, _defineProperty2.default)(this, "refreshMediaDevices", async stream => {
this.setState({
mediaDevices: (await _MediaDeviceHandler.default.getDevices()) ?? null,
[_MediaDeviceHandler.MediaDeviceKindEnum.AudioOutput]: mapDeviceKindToHandlerValue(_MediaDeviceHandler.MediaDeviceKindEnum.AudioOutput),
[_MediaDeviceHandler.MediaDeviceKindEnum.AudioInput]: mapDeviceKindToHandlerValue(_MediaDeviceHandler.MediaDeviceKindEnum.AudioInput),
[_MediaDeviceHandler.MediaDeviceKindEnum.VideoInput]: mapDeviceKindToHandlerValue(_MediaDeviceHandler.MediaDeviceKindEnum.VideoInput)
});
if (stream) {
// kill stream (after we've enumerated the devices, otherwise we'd get empty labels again)
// so that we don't leave it lingering around with webcam enabled etc
// as here we called gUM to ask user for permission to their device names only
stream.getTracks().forEach(track => track.stop());
}
});
(0, _defineProperty2.default)(this, "requestMediaPermissions", async () => {
const stream = await (0, _requestMediaPermissions.requestMediaPermissions)();
if (stream) {
await this.refreshMediaDevices(stream);
}
});
(0, _defineProperty2.default)(this, "setDevice", async (deviceId, kind) => {
// set state immediately so UI is responsive
this.setState({
[kind]: deviceId
});
try {
await _MediaDeviceHandler.default.instance.setDevice(deviceId, kind);
} catch (error) {
_logger.logger.error(`Failed to set device ${kind}: ${deviceId}`);
// reset state to current value
this.setState({
[kind]: mapDeviceKindToHandlerValue(kind)
});
}
});
(0, _defineProperty2.default)(this, "changeWebRtcMethod", p2p => {
this.context.setForceTURN(!p2p);
});
this.state = {
mediaDevices: null,
[_MediaDeviceHandler.MediaDeviceKindEnum.AudioOutput]: null,
[_MediaDeviceHandler.MediaDeviceKindEnum.AudioInput]: null,
[_MediaDeviceHandler.MediaDeviceKindEnum.VideoInput]: null,
audioAutoGainControl: _MediaDeviceHandler.default.getAudioAutoGainControl(),
audioEchoCancellation: _MediaDeviceHandler.default.getAudioEchoCancellation(),
audioNoiseSuppression: _MediaDeviceHandler.default.getAudioNoiseSuppression()
};
}
async componentDidMount() {
const canSeeDeviceLabels = await _MediaDeviceHandler.default.hasAnyLabeledDevices();
if (canSeeDeviceLabels) {
await this.refreshMediaDevices();
}
}
renderDeviceOptions(devices, category) {
return devices.map(d => {
return /*#__PURE__*/_react.default.createElement("option", {
key: `${category}-${d.deviceId}`,
value: d.deviceId
}, d.label);
});
}
renderDropdown(kind, label) {
const devices = this.state.mediaDevices?.[kind].slice(0);
if (!devices?.length) return null;
const defaultDevice = _MediaDeviceHandler.default.getDefaultDevice(devices);
return /*#__PURE__*/_react.default.createElement(_Field.default, {
element: "select",
label: label,
value: this.state[kind] || defaultDevice,
onChange: e => this.setDevice(e.target.value, kind)
}, this.renderDeviceOptions(devices, kind));
}
render() {
let requestButton;
let speakerDropdown;
let microphoneDropdown;
let webcamDropdown;
if (!this.state.mediaDevices) {
requestButton = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|voip|missing_permissions_prompt")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: this.requestMediaPermissions,
kind: "primary"
}, (0, _languageHandler._t)("settings|voip|request_permissions")));
} else if (this.state.mediaDevices) {
speakerDropdown = this.renderDropdown(_MediaDeviceHandler.MediaDeviceKindEnum.AudioOutput, (0, _languageHandler._t)("settings|voip|audio_output")) || /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|voip|audio_output_empty"));
microphoneDropdown = this.renderDropdown(_MediaDeviceHandler.MediaDeviceKindEnum.AudioInput, (0, _languageHandler._t)("common|microphone")) || /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|voip|audio_input_empty"));
webcamDropdown = this.renderDropdown(_MediaDeviceHandler.MediaDeviceKindEnum.VideoInput, (0, _languageHandler._t)("common|camera")) || /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|voip|video_input_empty"));
}
return /*#__PURE__*/_react.default.createElement(_SettingsTab.default, null, /*#__PURE__*/_react.default.createElement(_SettingsSection.SettingsSection, null, requestButton, /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|voip|voice_section"),
stretchContent: true
}, speakerDropdown, microphoneDropdown, /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: this.state.audioAutoGainControl,
onChange: async v => {
await _MediaDeviceHandler.default.setAudioAutoGainControl(v);
this.setState({
audioAutoGainControl: _MediaDeviceHandler.default.getAudioAutoGainControl()
});
},
label: (0, _languageHandler._t)("settings|voip|voice_agc"),
"data-testid": "voice-auto-gain"
})), /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|voip|video_section"),
stretchContent: true
}, webcamDropdown, /*#__PURE__*/_react.default.createElement(_SettingsFlag.default, {
name: "VideoView.flipVideoHorizontally",
level: _SettingLevel.SettingLevel.ACCOUNT
}))), /*#__PURE__*/_react.default.createElement(_SettingsSection.SettingsSection, {
heading: (0, _languageHandler._t)("common|advanced")
}, /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|voip|voice_processing")
}, /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: this.state.audioNoiseSuppression,
onChange: async v => {
await _MediaDeviceHandler.default.setAudioNoiseSuppression(v);
this.setState({
audioNoiseSuppression: _MediaDeviceHandler.default.getAudioNoiseSuppression()
});
},
label: (0, _languageHandler._t)("settings|voip|noise_suppression"),
"data-testid": "voice-noise-suppression"
}), /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: this.state.audioEchoCancellation,
onChange: async v => {
await _MediaDeviceHandler.default.setAudioEchoCancellation(v);
this.setState({
audioEchoCancellation: _MediaDeviceHandler.default.getAudioEchoCancellation()
});
},
label: (0, _languageHandler._t)("settings|voip|echo_cancellation"),
"data-testid": "voice-echo-cancellation"
})), /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|voip|connection_section")
}, /*#__PURE__*/_react.default.createElement(_SettingsFlag.default, {
name: "webRtcAllowPeerToPeer",
level: _SettingLevel.SettingLevel.DEVICE,
onChange: this.changeWebRtcMethod
}), /*#__PURE__*/_react.default.createElement(_SettingsFlag.default, {
name: "fallbackICEServerAllowed",
label: (0, _languageHandler._t)("settings|voip|enable_fallback_ice_server", {
server: new URL(_call.FALLBACK_ICE_SERVER).pathname
}),
level: _SettingLevel.SettingLevel.DEVICE,
hideIfCannotSet: true
}))));
}
}
exports.default = VoiceUserSettingsTab;
(0, _defineProperty2.default)(VoiceUserSettingsTab, "contextType", _MatrixClientContext.default);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfY2FsbCIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfTWVkaWFEZXZpY2VIYW5kbGVyIiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJfRmllbGQiLCJfQWNjZXNzaWJsZUJ1dHRvbiIsIl9TZXR0aW5nTGV2ZWwiLCJfU2V0dGluZ3NGbGFnIiwiX0xhYmVsbGVkVG9nZ2xlU3dpdGNoIiwiX3JlcXVlc3RNZWRpYVBlcm1pc3Npb25zIiwiX1NldHRpbmdzVGFiIiwiX1NldHRpbmdzU2VjdGlvbiIsIl9TZXR0aW5nc1N1YnNlY3Rpb24iLCJfTWF0cml4Q2xpZW50Q29udGV4dCIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIm1hcERldmljZUtpbmRUb0hhbmRsZXJWYWx1ZSIsImRldmljZUtpbmQiLCJNZWRpYURldmljZUtpbmRFbnVtIiwiQXVkaW9PdXRwdXQiLCJNZWRpYURldmljZUhhbmRsZXIiLCJnZXRBdWRpb091dHB1dCIsIkF1ZGlvSW5wdXQiLCJnZXRBdWRpb0lucHV0IiwiVmlkZW9JbnB1dCIsImdldFZpZGVvSW5wdXQiLCJWb2ljZVVzZXJTZXR0aW5nc1RhYiIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsImNvbnRleHQiLCJfZGVmaW5lUHJvcGVydHkyIiwic3RyZWFtIiwic2V0U3RhdGUiLCJtZWRpYURldmljZXMiLCJnZXREZXZpY2VzIiwiZ2V0VHJhY2tzIiwiZm9yRWFjaCIsInRyYWNrIiwic3RvcCIsInJlcXVlc3RNZWRpYVBlcm1pc3Npb25zIiwicmVmcmVzaE1lZGlhRGV2aWNlcyIsImRldmljZUlkIiwia2luZCIsImluc3RhbmNlIiwic2V0RGV2aWNlIiwiZXJyb3IiLCJsb2dnZXIiLCJwMnAiLCJzZXRGb3JjZVRVUk4iLCJzdGF0ZSIsImF1ZGlvQXV0b0dhaW5Db250cm9sIiwiZ2V0QXVkaW9BdXRvR2FpbkNvbnRyb2wiLCJhdWRpb0VjaG9DYW5jZWxsYXRpb24iLCJnZXRBdWRpb0VjaG9DYW5jZWxsYXRpb24iLCJhdWRpb05vaXNlU3VwcHJlc3Npb24iLCJnZXRBdWRpb05vaXNlU3VwcHJlc3Npb24iLCJjb21wb25lbnREaWRNb3VudCIsImNhblNlZURldmljZUxhYmVscyIsImhhc0FueUxhYmVsZWREZXZpY2VzIiwicmVuZGVyRGV2aWNlT3B0aW9ucyIsImRldmljZXMiLCJjYXRlZ29yeSIsIm1hcCIsImQiLCJjcmVhdGVFbGVtZW50Iiwia2V5IiwidmFsdWUiLCJsYWJlbCIsInJlbmRlckRyb3Bkb3duIiwic2xpY2UiLCJsZW5ndGgiLCJkZWZhdWx0RGV2aWNlIiwiZ2V0RGVmYXVsdERldmljZSIsImVsZW1lbnQiLCJvbkNoYW5nZSIsInRhcmdldCIsInJlbmRlciIsInJlcXVlc3RCdXR0b24iLCJzcGVha2VyRHJvcGRvd24iLCJtaWNyb3Bob25lRHJvcGRvd24iLCJ3ZWJjYW1Ecm9wZG93biIsIl90Iiwib25DbGljayIsIlNldHRpbmdzU2VjdGlvbiIsImhlYWRpbmciLCJzdHJldGNoQ29udGVudCIsInYiLCJzZXRBdWRpb0F1dG9HYWluQ29udHJvbCIsIm5hbWUiLCJsZXZlbCIsIlNldHRpbmdMZXZlbCIsIkFDQ09VTlQiLCJzZXRBdWRpb05vaXNlU3VwcHJlc3Npb24iLCJzZXRBdWRpb0VjaG9DYW5jZWxsYXRpb24iLCJERVZJQ0UiLCJjaGFuZ2VXZWJSdGNNZXRob2QiLCJzZXJ2ZXIiLCJVUkwiLCJGQUxMQkFDS19JQ0VfU0VSVkVSIiwicGF0aG5hbWUiLCJoaWRlSWZDYW5ub3RTZXQiLCJleHBvcnRzIiwiTWF0cml4Q2xpZW50Q29udGV4dCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3NldHRpbmdzL3RhYnMvdXNlci9Wb2ljZVVzZXJTZXR0aW5nc1RhYi50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cbkNvcHlyaWdodCAyMDE5IE5ldyBWZWN0b3IgTHRkXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBSZWFjdE5vZGUgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcbmltcG9ydCB7IEZBTExCQUNLX0lDRV9TRVJWRVIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvd2VicnRjL2NhbGxcIjtcblxuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgTWVkaWFEZXZpY2VIYW5kbGVyLCB7IElNZWRpYURldmljZXMsIE1lZGlhRGV2aWNlS2luZEVudW0gfSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vTWVkaWFEZXZpY2VIYW5kbGVyXCI7XG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uLy4uLy4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgQWNjZXNzaWJsZUJ1dHRvbiBmcm9tIFwiLi4vLi4vLi4vZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IHsgU2V0dGluZ0xldmVsIH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdMZXZlbFwiO1xuaW1wb3J0IFNldHRpbmdzRmxhZyBmcm9tIFwiLi4vLi4vLi4vZWxlbWVudHMvU2V0dGluZ3NGbGFnXCI7XG5pbXBvcnQgTGFiZWxsZWRUb2dnbGVTd2l0Y2ggZnJvbSBcIi4uLy4uLy4uL2VsZW1lbnRzL0xhYmVsbGVkVG9nZ2xlU3dpdGNoXCI7XG5pbXBvcnQgeyByZXF1ZXN0TWVkaWFQZXJtaXNzaW9ucyB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi91dGlscy9tZWRpYS9yZXF1ZXN0TWVkaWFQZXJtaXNzaW9uc1wiO1xuaW1wb3J0IFNldHRpbmdzVGFiIGZyb20gXCIuLi9TZXR0aW5nc1RhYlwiO1xuaW1wb3J0IHsgU2V0dGluZ3NTZWN0aW9uIH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9TZXR0aW5nc1NlY3Rpb25cIjtcbmltcG9ydCBTZXR0aW5nc1N1YnNlY3Rpb24gZnJvbSBcIi4uLy4uL3NoYXJlZC9TZXR0aW5nc1N1YnNlY3Rpb25cIjtcbmltcG9ydCBNYXRyaXhDbGllbnRDb250ZXh0IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9jb250ZXh0cy9NYXRyaXhDbGllbnRDb250ZXh0XCI7XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIG1lZGlhRGV2aWNlczogSU1lZGlhRGV2aWNlcyB8IG51bGw7XG4gICAgW01lZGlhRGV2aWNlS2luZEVudW0uQXVkaW9PdXRwdXRdOiBzdHJpbmcgfCBudWxsO1xuICAgIFtNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvSW5wdXRdOiBzdHJpbmcgfCBudWxsO1xuICAgIFtNZWRpYURldmljZUtpbmRFbnVtLlZpZGVvSW5wdXRdOiBzdHJpbmcgfCBudWxsO1xuICAgIGF1ZGlvQXV0b0dhaW5Db250cm9sOiBib29sZWFuO1xuICAgIGF1ZGlvRWNob0NhbmNlbGxhdGlvbjogYm9vbGVhbjtcbiAgICBhdWRpb05vaXNlU3VwcHJlc3Npb246IGJvb2xlYW47XG59XG5cbi8qKlxuICogTWFwcyBkZXZpY2VLaW5kIHRvIHRoZSByaWdodCBnZXQgbWV0aG9kIG9uIE1lZGlhRGV2aWNlSGFuZGxlclxuICogSGVscGZ1bCBmb3Igc2V0dGluZyBzdGF0ZVxuICovXG5jb25zdCBtYXBEZXZpY2VLaW5kVG9IYW5kbGVyVmFsdWUgPSAoZGV2aWNlS2luZDogTWVkaWFEZXZpY2VLaW5kRW51bSk6IHN0cmluZyB8IG51bGwgPT4ge1xuICAgIHN3aXRjaCAoZGV2aWNlS2luZCkge1xuICAgICAgICBjYXNlIE1lZGlhRGV2aWNlS2luZEVudW0uQXVkaW9PdXRwdXQ6XG4gICAgICAgICAgICByZXR1cm4gTWVkaWFEZXZpY2VIYW5kbGVyLmdldEF1ZGlvT3V0cHV0KCk7XG4gICAgICAgIGNhc2UgTWVkaWFEZXZpY2VLaW5kRW51bS5BdWRpb0lucHV0OlxuICAgICAgICAgICAgcmV0dXJuIE1lZGlhRGV2aWNlSGFuZGxlci5nZXRBdWRpb0lucHV0KCk7XG4gICAgICAgIGNhc2UgTWVkaWFEZXZpY2VLaW5kRW51bS5WaWRlb0lucHV0OlxuICAgICAgICAgICAgcmV0dXJuIE1lZGlhRGV2aWNlSGFuZGxlci5nZXRWaWRlb0lucHV0KCk7XG4gICAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVm9pY2VVc2VyU2V0dGluZ3NUYWIgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8e30sIElTdGF0ZT4ge1xuICAgIHB1YmxpYyBzdGF0aWMgY29udGV4dFR5cGUgPSBNYXRyaXhDbGllbnRDb250ZXh0O1xuICAgIHB1YmxpYyBkZWNsYXJlIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBNYXRyaXhDbGllbnRDb250ZXh0PjtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcm9wczoge30sIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBNYXRyaXhDbGllbnRDb250ZXh0Pikge1xuICAgICAgICBzdXBlcihwcm9wcywgY29udGV4dCk7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIG1lZGlhRGV2aWNlczogbnVsbCxcbiAgICAgICAgICAgIFtNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvT3V0cHV0XTogbnVsbCxcbiAgICAgICAgICAgIFtNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvSW5wdXRdOiBudWxsLFxuICAgICAgICAgICAgW01lZGlhRGV2aWNlS2luZEVudW0uVmlkZW9JbnB1dF06IG51bGwsXG4gICAgICAgICAgICBhdWRpb0F1dG9HYWluQ29udHJvbDogTWVkaWFEZXZpY2VIYW5kbGVyLmdldEF1ZGlvQXV0b0dhaW5Db250cm9sKCksXG4gICAgICAgICAgICBhdWRpb0VjaG9DYW5jZWxsYXRpb246IE1lZGlhRGV2aWNlSGFuZGxlci5nZXRBdWRpb0VjaG9DYW5jZWxsYXRpb24oKSxcbiAgICAgICAgICAgIGF1ZGlvTm9pc2VTdXBwcmVzc2lvbjogTWVkaWFEZXZpY2VIYW5kbGVyLmdldEF1ZGlvTm9pc2VTdXBwcmVzc2lvbigpLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBjb21wb25lbnREaWRNb3VudCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgY2FuU2VlRGV2aWNlTGFiZWxzID0gYXdhaXQgTWVkaWFEZXZpY2VIYW5kbGVyLmhhc0FueUxhYmVsZWREZXZpY2VzKCk7XG4gICAgICAgIGlmIChjYW5TZWVEZXZpY2VMYWJlbHMpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmVmcmVzaE1lZGlhRGV2aWNlcygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZWZyZXNoTWVkaWFEZXZpY2VzID0gYXN5bmMgKHN0cmVhbT86IE1lZGlhU3RyZWFtKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgbWVkaWFEZXZpY2VzOiAoYXdhaXQgTWVkaWFEZXZpY2VIYW5kbGVyLmdldERldmljZXMoKSkgPz8gbnVsbCxcbiAgICAgICAgICAgIFtNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvT3V0cHV0XTogbWFwRGV2aWNlS2luZFRvSGFuZGxlclZhbHVlKE1lZGlhRGV2aWNlS2luZEVudW0uQXVkaW9PdXRwdXQpLFxuICAgICAgICAgICAgW01lZGlhRGV2aWNlS2luZEVudW0uQXVkaW9JbnB1dF06IG1hcERldmljZUtpbmRUb0hhbmRsZXJWYWx1ZShNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvSW5wdXQpLFxuICAgICAgICAgICAgW01lZGlhRGV2aWNlS2luZEVudW0uVmlkZW9JbnB1dF06IG1hcERldmljZUtpbmRUb0hhbmRsZXJWYWx1ZShNZWRpYURldmljZUtpbmRFbnVtLlZpZGVvSW5wdXQpLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHN0cmVhbSkge1xuICAgICAgICAgICAgLy8ga2lsbCBzdHJlYW0gKGFmdGVyIHdlJ3ZlIGVudW1lcmF0ZWQgdGhlIGRldmljZXMsIG90aGVyd2lzZSB3ZSdkIGdldCBlbXB0eSBsYWJlbHMgYWdhaW4pXG4gICAgICAgICAgICAvLyBzbyB0aGF0IHdlIGRvbid0IGxlYXZlIGl0IGxpbmdlcmluZyBhcm91bmQgd2l0aCB3ZWJjYW0gZW5hYmxlZCBldGNcbiAgICAgICAgICAgIC8vIGFzIGhlcmUgd2UgY2FsbGVkIGdVTSB0byBhc2sgdXNlciBmb3IgcGVybWlzc2lvbiB0byB0aGVpciBkZXZpY2UgbmFtZXMgb25seVxuICAgICAgICAgICAgc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB0cmFjay5zdG9wKCkpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgcmVxdWVzdE1lZGlhUGVybWlzc2lvbnMgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IHJlcXVlc3RNZWRpYVBlcm1pc3Npb25zKCk7XG4gICAgICAgIGlmIChzdHJlYW0pIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmVmcmVzaE1lZGlhRGV2aWNlcyhzdHJlYW0pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgc2V0RGV2aWNlID0gYXN5bmMgKGRldmljZUlkOiBzdHJpbmcsIGtpbmQ6IE1lZGlhRGV2aWNlS2luZEVudW0pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgLy8gc2V0IHN0YXRlIGltbWVkaWF0ZWx5IHNvIFVJIGlzIHJlc3BvbnNpdmVcbiAgICAgICAgdGhpcy5zZXRTdGF0ZTxhbnk+KHsgW2tpbmRdOiBkZXZpY2VJZCB9KTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IE1lZGlhRGV2aWNlSGFuZGxlci5pbnN0YW5jZS5zZXREZXZpY2UoZGV2aWNlSWQsIGtpbmQpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gc2V0IGRldmljZSAke2tpbmR9OiAke2RldmljZUlkfWApO1xuICAgICAgICAgICAgLy8gcmVzZXQgc3RhdGUgdG8gY3VycmVudCB2YWx1ZVxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZTxhbnk+KHsgW2tpbmRdOiBtYXBEZXZpY2VLaW5kVG9IYW5kbGVyVmFsdWUoa2luZCkgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBjaGFuZ2VXZWJSdGNNZXRob2QgPSAocDJwOiBib29sZWFuKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuY29udGV4dC5zZXRGb3JjZVRVUk4oIXAycCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgcmVuZGVyRGV2aWNlT3B0aW9ucyhkZXZpY2VzOiBBcnJheTxNZWRpYURldmljZUluZm8+LCBjYXRlZ29yeTogTWVkaWFEZXZpY2VLaW5kRW51bSk6IEFycmF5PEpTWC5FbGVtZW50PiB7XG4gICAgICAgIHJldHVybiBkZXZpY2VzLm1hcCgoZCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8b3B0aW9uIGtleT17YCR7Y2F0ZWdvcnl9LSR7ZC5kZXZpY2VJZH1gfSB2YWx1ZT17ZC5kZXZpY2VJZH0+XG4gICAgICAgICAgICAgICAgICAgIHtkLmxhYmVsfVxuICAgICAgICAgICAgICAgIDwvb3B0aW9uPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW5kZXJEcm9wZG93bihraW5kOiBNZWRpYURldmljZUtpbmRFbnVtLCBsYWJlbDogc3RyaW5nKTogUmVhY3ROb2RlIHtcbiAgICAgICAgY29uc3QgZGV2aWNlcyA9IHRoaXMuc3RhdGUubWVkaWFEZXZpY2VzPy5ba2luZF0uc2xpY2UoMCk7XG4gICAgICAgIGlmICghZGV2aWNlcz8ubGVuZ3RoKSByZXR1cm4gbnVsbDtcblxuICAgICAgICBjb25zdCBkZWZhdWx0RGV2aWNlID0gTWVkaWFEZXZpY2VIYW5kbGVyLmdldERlZmF1bHREZXZpY2UoZGV2aWNlcyk7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICBlbGVtZW50PVwic2VsZWN0XCJcbiAgICAgICAgICAgICAgICBsYWJlbD17bGFiZWx9XG4gICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGVba2luZF0gfHwgZGVmYXVsdERldmljZX1cbiAgICAgICAgICAgICAgICBvbkNoYW5nZT17KGUpID0+IHRoaXMuc2V0RGV2aWNlKGUudGFyZ2V0LnZhbHVlLCBraW5kKX1cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7dGhpcy5yZW5kZXJEZXZpY2VPcHRpb25zKGRldmljZXMsIGtpbmQpfVxuICAgICAgICAgICAgPC9GaWVsZD5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0Tm9kZSB7XG4gICAgICAgIGxldCByZXF1ZXN0QnV0dG9uOiBSZWFjdE5vZGUgfCB1bmRlZmluZWQ7XG4gICAgICAgIGxldCBzcGVha2VyRHJvcGRvd246IFJlYWN0Tm9kZSB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IG1pY3JvcGhvbmVEcm9wZG93bjogUmVhY3ROb2RlIHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgd2ViY2FtRHJvcGRvd246IFJlYWN0Tm9kZSB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLm1lZGlhRGV2aWNlcykge1xuICAgICAgICAgICAgcmVxdWVzdEJ1dHRvbiA9IChcbiAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICA8cD57X3QoXCJzZXR0aW5nc3x2b2lwfG1pc3NpbmdfcGVybWlzc2lvbnNfcHJvbXB0XCIpfTwvcD5cbiAgICAgICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b24gb25DbGljaz17dGhpcy5yZXF1ZXN0TWVkaWFQZXJtaXNzaW9uc30ga2luZD1cInByaW1hcnlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcInNldHRpbmdzfHZvaXB8cmVxdWVzdF9wZXJtaXNzaW9uc1wiKX1cbiAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLm1lZGlhRGV2aWNlcykge1xuICAgICAgICAgICAgc3BlYWtlckRyb3Bkb3duID0gdGhpcy5yZW5kZXJEcm9wZG93bihcbiAgICAgICAgICAgICAgICBNZWRpYURldmljZUtpbmRFbnVtLkF1ZGlvT3V0cHV0LFxuICAgICAgICAgICAgICAgIF90KFwic2V0dGluZ3N8dm9pcHxhdWRpb19vdXRwdXRcIiksXG4gICAgICAgICAgICApIHx8IDxwPntfdChcInNldHRpbmdzfHZvaXB8YXVkaW9fb3V0cHV0X2VtcHR5XCIpfTwvcD47XG4gICAgICAgICAgICBtaWNyb3Bob25lRHJvcGRvd24gPSB0aGlzLnJlbmRlckRyb3Bkb3duKE1lZGlhRGV2aWNlS2luZEVudW0uQXVkaW9JbnB1dCwgX3QoXCJjb21tb258bWljcm9waG9uZVwiKSkgfHwgKFxuICAgICAgICAgICAgICAgIDxwPntfdChcInNldHRpbmdzfHZvaXB8YXVkaW9faW5wdXRfZW1wdHlcIil9PC9wPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHdlYmNhbURyb3Bkb3duID0gdGhpcy5yZW5kZXJEcm9wZG93bihNZWRpYURldmljZUtpbmRFbnVtLlZpZGVvSW5wdXQsIF90KFwiY29tbW9ufGNhbWVyYVwiKSkgfHwgKFxuICAgICAgICAgICAgICAgIDxwPntfdChcInNldHRpbmdzfHZvaXB8dmlkZW9faW5wdXRfZW1wdHlcIil9PC9wPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U2V0dGluZ3NUYWI+XG4gICAgICAgICAgICAgICAgPFNldHRpbmdzU2VjdGlvbj5cbiAgICAgICAgICAgICAgICAgICAge3JlcXVlc3RCdXR0b259XG4gICAgICAgICAgICAgICAgICAgIDxTZXR0aW5nc1N1YnNlY3Rpb24gaGVhZGluZz17X3QoXCJzZXR0aW5nc3x2b2lwfHZvaWNlX3NlY3Rpb25cIil9IHN0cmV0Y2hDb250ZW50PlxuICAgICAgICAgICAgICAgICAgICAgICAge3NwZWFrZXJEcm9wZG93bn1cbiAgICAgICAgICAgICAgICAgICAgICAgIHttaWNyb3Bob25lRHJvcGRvd259XG4gICAgICAgICAgICAgICAgICAgICAgICA8TGFiZWxsZWRUb2dnbGVTd2l0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17dGhpcy5zdGF0ZS5hdWRpb0F1dG9HYWluQ29udHJvbH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17YXN5bmMgKHYpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgTWVkaWFEZXZpY2VIYW5kbGVyLnNldEF1ZGlvQXV0b0dhaW5Db250cm9sKHYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgYXVkaW9BdXRvR2FpbkNvbnRyb2w6IE1lZGlhRGV2aWNlSGFuZGxlci5nZXRBdWRpb0F1dG9HYWluQ29udHJvbCgpIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e190KFwic2V0dGluZ3N8dm9pcHx2b2ljZV9hZ2NcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJ2b2ljZS1hdXRvLWdhaW5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9TZXR0aW5nc1N1YnNlY3Rpb24+XG4gICAgICAgICAgICAgICAgICAgIDxTZXR0aW5nc1N1YnNlY3Rpb24gaGVhZGluZz17X3QoXCJzZXR0aW5nc3x2b2lwfHZpZGVvX3NlY3Rpb25cIil9IHN0cmV0Y2hDb250ZW50PlxuICAgICAgICAgICAgICAgICAgICAgICAge3dlYmNhbURyb3Bkb3dufVxuICAgICAgICAgICAgICAgICAgICAgICAgPFNldHRpbmdzRmxhZyBuYW1lPVwiVmlkZW9WaWV3LmZsaXBWaWRlb0hvcml6b250YWxseVwiIGxldmVsPXtTZXR0aW5nTGV2ZWwuQUNDT1VOVH0gLz5cbiAgICAgICAgICAgICAgICAgICAgPC9TZXR0aW5nc1N1YnNlY3Rpb24+XG4gICAgICAgICAgICAgICAgPC9TZXR0aW5nc1NlY3Rpb24+XG5cbiAgICAgICAgICAgICAgICA8U2V0dGluZ3NTZWN0aW9uIGhlYWRpbmc9e190KFwiY29tbW9ufGFkdmFuY2VkXCIpfT5cbiAgICAgICAgICAgICAgICAgICAgPFNldHRpbmdzU3Vic2VjdGlvbiBoZWFkaW5nPXtfdChcInNldHRpbmdzfHZvaXB8dm9pY2VfcHJvY2Vzc2luZ1wiKX0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8TGFiZWxsZWRUb2dnbGVTd2l0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17dGhpcy5zdGF0ZS5hdWRpb05vaXNlU3VwcHJlc3Npb259XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e2FzeW5jICh2KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IE1lZGlhRGV2aWNlSGFuZGxlci5zZXRBdWRpb05vaXNlU3VwcHJlc3Npb24odik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBhdWRpb05vaXNlU3VwcHJlc3Npb246IE1lZGlhRGV2aWNlSGFuZGxlci5nZXRBdWRpb05vaXNlU3VwcHJlc3Npb24oKSB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcInNldHRpbmdzfHZvaXB8bm9pc2Vfc3VwcHJlc3Npb25cIil9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJ2b2ljZS1ub2lzZS1zdXBwcmVzc2lvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPExhYmVsbGVkVG9nZ2xlU3dpdGNoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUuYXVkaW9FY2hvQ2FuY2VsbGF0aW9ufVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXthc3luYyAodik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBNZWRpYURldmljZUhhbmRsZXIuc2V0QXVkaW9FY2hvQ2FuY2VsbGF0aW9uKHYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgYXVkaW9FY2hvQ2FuY2VsbGF0aW9uOiBNZWRpYURldmljZUhhbmRsZXIuZ2V0QXVkaW9FY2hvQ2FuY2VsbGF0aW9uKCkgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJzZXR0aW5nc3x2b2lwfGVjaG9fY2FuY2VsbGF0aW9uXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwidm9pY2UtZWNoby1jYW5jZWxsYXRpb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9TZXR0aW5nc1N1YnNlY3Rpb24+XG4gICAgICAgICAgICAgICAgICAgIDxTZXR0aW5nc1N1YnNlY3Rpb24gaGVhZGluZz17X3QoXCJzZXR0aW5nc3x2b2lwfGNvbm5lY3Rpb25fc2VjdGlvblwiKX0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8U2V0dGluZ3NGbGFnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cIndlYlJ0Y0FsbG93UGVlclRvUGVlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9e1NldHRpbmdMZXZlbC5ERVZJQ0V9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMuY2hhbmdlV2ViUnRjTWV0aG9kfVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxTZXR0aW5nc0ZsYWdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwiZmFsbGJhY2tJQ0VTZXJ2ZXJBbGxvd2VkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJzZXR0aW5nc3x2b2lwfGVuYWJsZV9mYWxsYmFja19pY2Vfc2VydmVyXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VydmVyOiBuZXcgVVJMKEZBTExCQUNLX0lDRV9TRVJWRVIpLnBhdGhuYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPXtTZXR0aW5nTGV2ZWwuREVWSUNFfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGVJZkNhbm5vdFNldFxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9TZXR0aW5nc1N1YnNlY3Rpb24+XG4gICAgICAgICAgICAgICAgPC9TZXR0aW5nc1NlY3Rpb24+XG4gICAgICAgICAgICA8L1NldHRpbmdzVGFiPlxuICAgICAgICApO1xuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQSxJQUFBQSxNQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxLQUFBLEdBQUFGLE9BQUE7QUFFQSxJQUFBRyxnQkFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksbUJBQUEsR0FBQUMsdUJBQUEsQ0FBQUwsT0FBQTtBQUNBLElBQUFNLE1BQUEsR0FBQVAsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFPLGlCQUFBLEdBQUFSLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUSxhQUFBLEdBQUFSLE9BQUE7QUFDQSxJQUFBUyxhQUFBLEdBQUFWLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBVSxxQkFBQSxHQUFBWCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVcsd0JBQUEsR0FBQVgsT0FBQTtBQUNBLElBQUFZLFlBQUEsR0FBQWIsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFhLGdCQUFBLEdBQUFiLE9BQUE7QUFDQSxJQUFBYyxtQkFBQSxHQUFBZixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQWUsb0JBQUEsR0FBQWhCLHNCQUFBLENBQUFDLE9BQUE7QUFBOEUsU0FBQWdCLHlCQUFBQyxDQUFBLDZCQUFBQyxPQUFBLG1CQUFBQyxDQUFBLE9BQUFELE9BQUEsSUFBQUUsQ0FBQSxPQUFBRixPQUFBLFlBQUFGLHdCQUFBLFlBQUFBLENB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QUM7TUFDM0YsQ0FBRTtNQUNGWSxLQUFLLEVBQUUsSUFBQWMsbUJBQUUsRUFBQyxpQ0FBaUMsQ0FBRTtNQUM3QyxlQUFZO0lBQXlCLENBQ3hDLENBQUMsZUFDRnpHLE1BQUEsQ0FBQXdCLE9BQUEsQ0FBQWdFLGFBQUEsQ0FBQzVFLHFCQUFBLENBQUFZLE9BQW9CO01BQ2pCa0UsS0FBSyxFQUFFLElBQUksQ0FBQ2pCLEtBQUssQ0FBQ0cscUJBQXNCO01BQ3hDc0IsUUFBUSxFQUFFLE1BQU9ZLENBQUMsSUFBb0I7UUFDbEMsTUFBTXBFLDJCQUFrQixDQUFDMkUsd0JBQXdCLENBQUNQLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUN0RCxRQUFRLENBQUM7VUFBRW9CLHFCQUFxQixFQUFFbEMsMkJBQWtCLENBQUNtQyx3QkFBd0IsQ0FBQztRQUFFLENBQUMsQ0FBQztNQUMzRixDQUFFO01BQ0ZjLEtBQUssRUFBRSxJQUFBYyxtQkFBRSxFQUFDLGlDQUFpQyxDQUFFO01BQzdDLGVBQVk7SUFBeUIsQ0FDeEMsQ0FDZSxDQUFDLGVBQ3JCekcsTUFBQSxDQUFBd0IsT0FBQSxDQUFBZ0UsYUFBQSxDQUFDeEUsbUJBQUEsQ0FBQVEsT0FBa0I7TUFBQ29GLE9BQU8sRUFBRSxJQUFBSCxtQkFBRSxFQUFDLGtDQUFrQztJQUFFLGdCQUNoRXpHLE1BQUEsQ0FBQXdCLE9BQUEsQ0FBQWdFLGFBQUEsQ0FBQzdFLGFBQUEsQ0FBQWEsT0FBWTtNQUNUd0YsSUFBSSxFQUFDLHVCQUF1QjtNQUM1QkMsS0FBSyxFQUFFQywwQkFBWSxDQUFDSSxNQUFPO01BQzNCcEIsUUFBUSxFQUFFLElBQUksQ0FBQ3FCO0lBQW1CLENBQ3JDLENBQUMsZUFDRnZILE1BQUEsQ0FBQXdCLE9BQUEsQ0FBQWdFLGFBQUEsQ0FBQzdFLGFBQUEsQ0FBQWEsT0FBWTtNQUNUd0YsSUFBSSxFQUFDLDBCQUEwQjtNQUMvQnJCLEtBQUssRUFBRSxJQUFBYyxtQkFBRSxFQUFDLDBDQUEwQyxFQUFFO1FBQ2xEZSxNQUFNLEVBQUUsSUFBSUMsR0FBRyxDQUFDQyx5QkFBbUIsQ0FBQyxDQUFDQztNQUN6QyxDQUFDLENBQUU7TUFDSFYsS0FBSyxFQUFFQywwQkFBWSxDQUFDSSxNQUFPO01BQzNCTSxlQUFlO0lBQUEsQ0FDbEIsQ0FDZSxDQUNQLENBQ1IsQ0FBQztFQUV0QjtBQUNKO0FBQUNDLE9BQUEsQ0FBQXJHLE9BQUEsR0FBQXdCLG9CQUFBO0FBQUEsSUFBQU0sZ0JBQUEsQ0FBQTlCLE9BQUEsRUFwTG9Cd0Isb0JBQW9CLGlCQUNUOEUsNEJBQW1CIiwiaWdub3JlTGlzdCI6W119