matrix-react-sdk
Version:
SDK for matrix.org using React
248 lines (207 loc) • 31.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _languageHandler = require("../../../../../languageHandler");
var _SdkConfig = _interopRequireDefault(require("../../../../../SdkConfig"));
var _CallMediaHandler = _interopRequireDefault(require("../../../../../CallMediaHandler"));
var _Field = _interopRequireDefault(require("../../../elements/Field"));
var _AccessibleButton = _interopRequireDefault(require("../../../elements/AccessibleButton"));
var _MatrixClientPeg = require("../../../../../MatrixClientPeg");
var sdk = _interopRequireWildcard(require("../../../../../index"));
var _Modal = _interopRequireDefault(require("../../../../../Modal"));
var _SettingLevel = require("../../../../../settings/SettingLevel");
var _replaceableComponent = require("../../../../../utils/replaceableComponent");
var _dec, _class, _temp;
let VoiceUserSettingsTab = (_dec = (0, _replaceableComponent.replaceableComponent)("views.settings.tabs.user.VoiceUserSettingsTab"), _dec(_class = (_temp = class VoiceUserSettingsTab extends _react.default.Component {
constructor() {
super();
(0, _defineProperty2.default)(this, "_refreshMediaDevices", async stream => {
this.setState({
mediaDevices: await _CallMediaHandler.default.getDevices(),
activeAudioOutput: _CallMediaHandler.default.getAudioOutput(),
activeAudioInput: _CallMediaHandler.default.getAudioInput(),
activeVideoInput: _CallMediaHandler.default.getVideoInput()
});
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 () => {
let constraints;
let stream;
let error;
try {
constraints = {
video: true,
audio: true
};
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
// user likely doesn't have a webcam,
// we should still allow to select a microphone
if (err.name === "NotFoundError") {
constraints = {
audio: true
};
try {
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
error = err;
}
} else {
error = err;
}
}
if (error) {
console.log("Failed to list userMedia devices", error);
const brand = _SdkConfig.default.get().brand;
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
_Modal.default.createTrackedDialog('No media permissions', '', ErrorDialog, {
title: (0, _languageHandler._t)('No media permissions'),
description: (0, _languageHandler._t)('You may need to manually permit %(brand)s to access your microphone/webcam', {
brand
})
});
} else {
this._refreshMediaDevices(stream);
}
});
(0, _defineProperty2.default)(this, "_setAudioOutput", e => {
_CallMediaHandler.default.setAudioOutput(e.target.value);
this.setState({
activeAudioOutput: e.target.value
});
});
(0, _defineProperty2.default)(this, "_setAudioInput", e => {
_CallMediaHandler.default.setAudioInput(e.target.value);
this.setState({
activeAudioInput: e.target.value
});
});
(0, _defineProperty2.default)(this, "_setVideoInput", e => {
_CallMediaHandler.default.setVideoInput(e.target.value);
this.setState({
activeVideoInput: e.target.value
});
});
(0, _defineProperty2.default)(this, "_changeWebRtcMethod", p2p => {
_MatrixClientPeg.MatrixClientPeg.get().setForceTURN(!p2p);
});
(0, _defineProperty2.default)(this, "_changeFallbackICEServerAllowed", allow => {
_MatrixClientPeg.MatrixClientPeg.get().setFallbackICEServerAllowed(allow);
});
this.state = {
mediaDevices: false,
activeAudioOutput: null,
activeAudioInput: null,
activeVideoInput: null
};
}
async componentDidMount() {
const canSeeDeviceLabels = await _CallMediaHandler.default.hasAnyLabeledDevices();
if (canSeeDeviceLabels) {
this._refreshMediaDevices();
}
}
_renderDeviceOptions(devices, category) {
return devices.map(d => {
return /*#__PURE__*/_react.default.createElement("option", {
key: `${category}-${d.deviceId}`,
value: d.deviceId
}, d.label);
});
}
render() {
const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag");
let requestButton = null;
let speakerDropdown = null;
let microphoneDropdown = null;
let webcamDropdown = null;
if (this.state.mediaDevices === false) {
requestButton = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_VoiceUserSettingsTab_missingMediaPermissions"
}, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("Missing media permissions, click the button below to request.")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: this._requestMediaPermissions,
kind: "primary"
}, (0, _languageHandler._t)("Request media permissions")));
} else if (this.state.mediaDevices) {
speakerDropdown = /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)('No Audio Outputs detected'));
microphoneDropdown = /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)('No Microphones detected'));
webcamDropdown = /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)('No Webcams detected'));
const defaultOption = {
deviceId: '',
label: (0, _languageHandler._t)('Default Device')
};
const getDefaultDevice = devices => {
// Note we're looking for a device with deviceId 'default' but adding a device
// with deviceId == the empty string: this is because Chrome gives us a device
// with deviceId 'default', so we're looking for this, not the one we are adding.
if (!devices.some(i => i.deviceId === 'default')) {
devices.unshift(defaultOption);
return '';
} else {
return 'default';
}
};
const audioOutputs = this.state.mediaDevices.audiooutput.slice(0);
if (audioOutputs.length > 0) {
const defaultDevice = getDefaultDevice(audioOutputs);
speakerDropdown = /*#__PURE__*/_react.default.createElement(_Field.default, {
element: "select",
label: (0, _languageHandler._t)("Audio Output"),
value: this.state.activeAudioOutput || defaultDevice,
onChange: this._setAudioOutput
}, this._renderDeviceOptions(audioOutputs, 'audioOutput'));
}
const audioInputs = this.state.mediaDevices.audioinput.slice(0);
if (audioInputs.length > 0) {
const defaultDevice = getDefaultDevice(audioInputs);
microphoneDropdown = /*#__PURE__*/_react.default.createElement(_Field.default, {
element: "select",
label: (0, _languageHandler._t)("Microphone"),
value: this.state.activeAudioInput || defaultDevice,
onChange: this._setAudioInput
}, this._renderDeviceOptions(audioInputs, 'audioInput'));
}
const videoInputs = this.state.mediaDevices.videoinput.slice(0);
if (videoInputs.length > 0) {
const defaultDevice = getDefaultDevice(videoInputs);
webcamDropdown = /*#__PURE__*/_react.default.createElement(_Field.default, {
element: "select",
label: (0, _languageHandler._t)("Camera"),
value: this.state.activeVideoInput || defaultDevice,
onChange: this._setVideoInput
}, this._renderDeviceOptions(videoInputs, 'videoInput'));
}
}
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SettingsTab mx_VoiceUserSettingsTab"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SettingsTab_heading"
}, (0, _languageHandler._t)("Voice & Video")), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SettingsTab_section"
}, requestButton, speakerDropdown, microphoneDropdown, webcamDropdown, /*#__PURE__*/_react.default.createElement(SettingsFlag, {
name: "VideoView.flipVideoHorizontally",
level: _SettingLevel.SettingLevel.ACCOUNT
}), /*#__PURE__*/_react.default.createElement(SettingsFlag, {
name: "webRtcAllowPeerToPeer",
level: _SettingLevel.SettingLevel.DEVICE,
onChange: this._changeWebRtcMethod
}), /*#__PURE__*/_react.default.createElement(SettingsFlag, {
name: "fallbackICEServerAllowed",
level: _SettingLevel.SettingLevel.DEVICE,
onChange: this._changeFallbackICEServerAllowed
})));
}
}, _temp)) || _class);
exports.default = VoiceUserSettingsTab;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3NldHRpbmdzL3RhYnMvdXNlci9Wb2ljZVVzZXJTZXR0aW5nc1RhYi5qcyJdLCJuYW1lcyI6WyJWb2ljZVVzZXJTZXR0aW5nc1RhYiIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJzdHJlYW0iLCJzZXRTdGF0ZSIsIm1lZGlhRGV2aWNlcyIsIkNhbGxNZWRpYUhhbmRsZXIiLCJnZXREZXZpY2VzIiwiYWN0aXZlQXVkaW9PdXRwdXQiLCJnZXRBdWRpb091dHB1dCIsImFjdGl2ZUF1ZGlvSW5wdXQiLCJnZXRBdWRpb0lucHV0IiwiYWN0aXZlVmlkZW9JbnB1dCIsImdldFZpZGVvSW5wdXQiLCJnZXRUcmFja3MiLCJmb3JFYWNoIiwidHJhY2siLCJzdG9wIiwiY29uc3RyYWludHMiLCJlcnJvciIsInZpZGVvIiwiYXVkaW8iLCJuYXZpZ2F0b3IiLCJnZXRVc2VyTWVkaWEiLCJlcnIiLCJuYW1lIiwiY29uc29sZSIsImxvZyIsImJyYW5kIiwiU2RrQ29uZmlnIiwiZ2V0IiwiRXJyb3JEaWFsb2ciLCJzZGsiLCJnZXRDb21wb25lbnQiLCJNb2RhbCIsImNyZWF0ZVRyYWNrZWREaWFsb2ciLCJ0aXRsZSIsImRlc2NyaXB0aW9uIiwiX3JlZnJlc2hNZWRpYURldmljZXMiLCJlIiwic2V0QXVkaW9PdXRwdXQiLCJ0YXJnZXQiLCJ2YWx1ZSIsInNldEF1ZGlvSW5wdXQiLCJzZXRWaWRlb0lucHV0IiwicDJwIiwiTWF0cml4Q2xpZW50UGVnIiwic2V0Rm9yY2VUVVJOIiwiYWxsb3ciLCJzZXRGYWxsYmFja0lDRVNlcnZlckFsbG93ZWQiLCJzdGF0ZSIsImNvbXBvbmVudERpZE1vdW50IiwiY2FuU2VlRGV2aWNlTGFiZWxzIiwiaGFzQW55TGFiZWxlZERldmljZXMiLCJfcmVuZGVyRGV2aWNlT3B0aW9ucyIsImRldmljZXMiLCJjYXRlZ29yeSIsIm1hcCIsImQiLCJkZXZpY2VJZCIsImxhYmVsIiwicmVuZGVyIiwiU2V0dGluZ3NGbGFnIiwicmVxdWVzdEJ1dHRvbiIsInNwZWFrZXJEcm9wZG93biIsIm1pY3JvcGhvbmVEcm9wZG93biIsIndlYmNhbURyb3Bkb3duIiwiX3JlcXVlc3RNZWRpYVBlcm1pc3Npb25zIiwiZGVmYXVsdE9wdGlvbiIsImdldERlZmF1bHREZXZpY2UiLCJzb21lIiwiaSIsInVuc2hpZnQiLCJhdWRpb091dHB1dHMiLCJhdWRpb291dHB1dCIsInNsaWNlIiwibGVuZ3RoIiwiZGVmYXVsdERldmljZSIsIl9zZXRBdWRpb091dHB1dCIsImF1ZGlvSW5wdXRzIiwiYXVkaW9pbnB1dCIsIl9zZXRBdWRpb0lucHV0IiwidmlkZW9JbnB1dHMiLCJ2aWRlb2lucHV0IiwiX3NldFZpZGVvSW5wdXQiLCJTZXR0aW5nTGV2ZWwiLCJBQ0NPVU5UIiwiREVWSUNFIiwiX2NoYW5nZVdlYlJ0Y01ldGhvZCIsIl9jaGFuZ2VGYWxsYmFja0lDRVNlcnZlckFsbG93ZWQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFpQkE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7SUFHcUJBLG9CLFdBRHBCLGdEQUFxQiwrQ0FBckIsQyx5QkFBRCxNQUNxQkEsb0JBRHJCLFNBQ2tEQyxlQUFNQyxTQUR4RCxDQUNrRTtBQUM5REMsRUFBQUEsV0FBVyxHQUFHO0FBQ1Y7QUFEVSxnRUFrQlMsTUFBT0MsTUFBUCxJQUFrQjtBQUNyQyxXQUFLQyxRQUFMLENBQWM7QUFDVkMsUUFBQUEsWUFBWSxFQUFFLE1BQU1DLDBCQUFpQkMsVUFBakIsRUFEVjtBQUVWQyxRQUFBQSxpQkFBaUIsRUFBRUYsMEJBQWlCRyxjQUFqQixFQUZUO0FBR1ZDLFFBQUFBLGdCQUFnQixFQUFFSiwwQkFBaUJLLGFBQWpCLEVBSFI7QUFJVkMsUUFBQUEsZ0JBQWdCLEVBQUVOLDBCQUFpQk8sYUFBakI7QUFKUixPQUFkOztBQU1BLFVBQUlWLE1BQUosRUFB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S2hCLEtBQUwsQ0FBV3RDLGdCQUFYLElBQStCaUUsYUFEMUM7QUFFSSxVQUFBLFFBQVEsRUFBRSxLQUFLTztBQUZuQixXQUdLLEtBQUs5QixvQkFBTCxDQUEwQjRCLFdBQTFCLEVBQXVDLFlBQXZDLENBSEwsQ0FESjtBQU9IO0FBQ0o7O0FBRUQsd0JBQ0k7QUFBSyxNQUFBLFNBQVMsRUFBQztBQUFmLG9CQUNJO0FBQUssTUFBQSxTQUFTLEVBQUM7QUFBZixPQUF5Qyx5QkFBRyxlQUFILENBQXpDLENBREosZUFFSTtBQUFLLE1BQUEsU0FBUyxFQUFDO0FBQWYsT0FDS25CLGFBREwsRUFFS0MsZUFGTCxFQUdLQyxrQkFITCxFQUlLQyxjQUpMLGVBS0ksNkJBQUMsWUFBRDtBQUFjLE1BQUEsSUFBSSxFQUFDLGlDQUFuQjtBQUFxRCxNQUFBLEtBQUssRUFBRW1CLDJCQUFhQztBQUF6RSxNQUxKLGVBTUksNkJBQUMsWUFBRDtBQUNJLE1BQUEsSUFBSSxFQUFDLHVCQURUO0FBRUksTUFBQSxLQUFLLEVBQUVELDJCQUFhRSxNQUZ4QjtBQUdJLE1BQUEsUUFBUSxFQUFFLEtBQUtDO0FBSG5CLE1BTkosZUFXSSw2QkFBQyxZQUFEO0FBQ0ksTUFBQSxJQUFJLEVBQUMsMEJBRFQ7QUFFSSxNQUFBLEtBQUssRUFBRUgsMkJBQWFFLE1BRnhCO0FBR0ksTUFBQSxRQUFRLEVBQUUsS0FBS0U7QUFIbkIsTUFYSixDQUZKLENBREo7QUFzQkg7O0FBMU02RCxDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDE5IE5ldyBWZWN0b3IgTHRkXG5Db3B5cmlnaHQgMjAyMCBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQge190fSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgU2RrQ29uZmlnIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9TZGtDb25maWdcIjtcbmltcG9ydCBDYWxsTWVkaWFIYW5kbGVyIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9DYWxsTWVkaWFIYW5kbGVyXCI7XG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uLy4uLy4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgQWNjZXNzaWJsZUJ1dHRvbiBmcm9tIFwiLi4vLi4vLi4vZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IHtNYXRyaXhDbGllbnRQZWd9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCAqIGFzIHNkayBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vaW5kZXhcIjtcbmltcG9ydCBNb2RhbCBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vTW9kYWxcIjtcbmltcG9ydCB7U2V0dGluZ0xldmVsfSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ0xldmVsXCI7XG5pbXBvcnQge3JlcGxhY2VhYmxlQ29tcG9uZW50fSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vdXRpbHMvcmVwbGFjZWFibGVDb21wb25lbnRcIjtcblxuQHJlcGxhY2VhYmxlQ29tcG9uZW50KFwidmlld3Muc2V0dGluZ3MudGFicy51c2VyLlZvaWNlVXNlclNldHRpbmdzVGFiXCIpXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWb2ljZVVzZXJTZXR0aW5nc1RhYiBleHRlbmRzIFJlYWN0LkNvbXBvbmVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIG1lZGlhRGV2aWNlczogZmFsc2UsXG4gICAgICAgICAgICBhY3RpdmVBdWRpb091dHB1dDogbnVsbCxcbiAgICAgICAgICAgIGFjdGl2ZUF1ZGlvSW5wdXQ6IG51bGwsXG4gICAgICAgICAgICBhY3RpdmVWaWRlb0lucHV0OiBudWxsLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGFzeW5jIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgICBjb25zdCBjYW5TZWVEZXZpY2VMYWJlbHMgPSBhd2FpdCBDYWxsTWVkaWFIYW5kbGVyLmhhc0FueUxhYmVsZWREZXZpY2VzKCk7XG4gICAgICAgIGlmIChjYW5TZWVEZXZpY2VMYWJlbHMpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlZnJlc2hNZWRpYURldmljZXMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIF9yZWZyZXNoTWVkaWFEZXZpY2VzID0gYXN5bmMgKHN0cmVhbSkgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIG1lZGlhRGV2aWNlczogYXdhaXQgQ2FsbE1lZGlhSGFuZGxlci5nZXREZXZpY2VzKCksXG4gICAgICAgICAgICBhY3RpdmVBdWRpb091dHB1dDogQ2FsbE1lZGlhSGFuZGxlci5nZXRBdWRpb091dHB1dCgpLFxuICAgICAgICAgICAgYWN0aXZlQXVkaW9JbnB1dDogQ2FsbE1lZGlhSGFuZGxlci5nZXRBdWRpb0lucHV0KCksXG4gICAgICAgICAgICBhY3RpdmVWaWRlb0lucHV0OiBDYWxsTWVkaWFIYW5kbGVyLmdldFZpZGVvSW5wdXQoKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChzdHJlYW0pIHtcbiAgICAgICAgICAgIC8vIGtpbGwgc3RyZWFtIChhZnRlciB3ZSd2ZSBlbnVtZXJhdGVkIHRoZSBkZXZpY2VzLCBvdGhlcndpc2Ugd2UnZCBnZXQgZW1wdHkgbGFiZWxzIGFnYWluKVxuICAgICAgICAgICAgLy8gc28gdGhhdCB3ZSBkb24ndCBsZWF2ZSBpdCBsaW5nZXJpbmcgYXJvdW5kIHdpdGggd2ViY2FtIGVuYWJsZWQgZXRjXG4gICAgICAgICAgICAvLyBhcyBoZXJlIHdlIGNhbGxlZCBnVU0gdG8gYXNrIHVzZXIgZm9yIHBlcm1pc3Npb24gdG8gdGhlaXIgZGV2aWNlIG5hbWVzIG9ubHlcbiAgICAgICAgICAgIHN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKCh0cmFjaykgPT4gdHJhY2suc3RvcCgpKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBfcmVxdWVzdE1lZGlhUGVybWlzc2lvbnMgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgIGxldCBjb25zdHJhaW50cztcbiAgICAgICAgbGV0IHN0cmVhbTtcbiAgICAgICAgbGV0IGVycm9yO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3RyYWludHMgPSB7dmlkZW86IHRydWUsIGF1ZGlvOiB0cnVlfTtcbiAgICAgICAgICAgIHN0cmVhbSA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAvLyB1c2VyIGxpa2VseSBkb2Vzbid0IGhhdmUgYSB3ZWJjYW0sXG4gICAgICAgICAgICAvLyB3ZSBzaG91bGQgc3RpbGwgYWxsb3cgdG8gc2VsZWN0IGEgbWljcm9waG9uZVxuICAgICAgICAgICAgaWYgKGVyci5uYW1lID09PSBcIk5vdEZvdW5kRXJyb3JcIikge1xuICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzID0geyBhdWRpbzogdHJ1ZSB9O1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHN0cmVhbSA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlcnJvciA9IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRmFpbGVkIHRvIGxpc3QgdXNlck1lZGlhIGRldmljZXNcIiwgZXJyb3IpO1xuICAgICAgICAgICAgY29uc3QgYnJhbmQgPSBTZGtDb25maWcuZ2V0KCkuYnJhbmQ7XG4gICAgICAgICAgICBjb25zdCBFcnJvckRpYWxvZyA9IHNkay5nZXRDb21wb25lbnQoJ2RpYWxvZ3MuRXJyb3JEaWFsb2cnKTtcbiAgICAgICAgICAgIE1vZGFsLmNyZWF0ZVRyYWNrZWREaWFsb2coJ05vIG1lZGlhIHBlcm1pc3Npb25zJywgJycsIEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IF90KCdObyBtZWRpYSBwZXJtaXNzaW9ucycpLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBfdChcbiAgICAgICAgICAgICAgICAgICAgJ1lvdSBtYXkgbmVlZCB0byBtYW51YWxseSBwZXJtaXQgJShicmFuZClzIHRvIGFjY2VzcyB5b3VyIG1pY3JvcGhvbmUvd2ViY2FtJyxcbiAgICAgICAgICAgICAgICAgICAgeyBicmFuZCB9LFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX3JlZnJlc2hNZWRpYURldmljZXMoc3RyZWFtKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBfc2V0QXVkaW9PdXRwdXQgPSAoZSkgPT4ge1xuICAgICAgICBDYWxsTWVkaWFIYW5kbGVyLnNldEF1ZGlvT3V0cHV0KGUudGFyZ2V0LnZhbHVlKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBhY3RpdmVBdWRpb091dHB1dDogZS50YXJnZXQudmFsdWUsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfc2V0QXVkaW9JbnB1dCA9IChlKSA9PiB7XG4gICAgICAgIENhbGxNZWRpYUhhbmRsZXIuc2V0QXVkaW9JbnB1dChlLnRhcmdldC52YWx1ZSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgYWN0aXZlQXVkaW9JbnB1dDogZS50YXJnZXQudmFsdWUsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfc2V0VmlkZW9JbnB1dCA9IChlKSA9PiB7XG4gICAgICAgIENhbGxNZWRpYUhhbmRsZXIuc2V0VmlkZW9JbnB1dChlLnRhcmdldC52YWx1ZSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgYWN0aXZlVmlkZW9JbnB1dDogZS50YXJnZXQudmFsdWUsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfY2hhbmdlV2ViUnRjTWV0aG9kID0gKHAycCkgPT4ge1xuICAgICAgICBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuc2V0Rm9yY2VUVVJOKCFwMnApO1xuICAgIH07XG5cbiAgICBfY2hhbmdlRmFsbGJhY2tJQ0VTZXJ2ZXJBbGxvd2VkID0gKGFsbG93KSA9PiB7XG4gICAgICAgIE1hdHJpeENsaWVudFBlZy5nZXQoKS5zZXRGYWxsYmFja0lDRVNlcnZlckFsbG93ZWQoYWxsb3cpO1xuICAgIH07XG5cbiAgICBfcmVuZGVyRGV2aWNlT3B0aW9ucyhkZXZpY2VzLCBjYXRlZ29yeSkge1xuICAgICAgICByZXR1cm4gZGV2aWNlcy5tYXAoKGQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiAoPG9wdGlvbiBrZXk9e2Ake2NhdGVnb3J5fS0ke2QuZGV2aWNlSWR9YH0gdmFsdWU9e2QuZGV2aWNlSWR9PntkLmxhYmVsfTwvb3B0aW9uPik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3QgU2V0dGluZ3NGbGFnID0gc2RrLmdldENvbXBvbmVudChcInZpZXdzLmVsZW1lbnRzLlNldHRpbmdzRmxhZ1wiKTtcblxuICAgICAgICBsZXQgcmVxdWVzdEJ1dHRvbiA9IG51bGw7XG4gICAgICAgIGxldCBzcGVha2VyRHJvcGRvd24gPSBudWxsO1xuICAgICAgICBsZXQgbWljcm9waG9uZURyb3Bkb3duID0gbnVsbDtcbiAgICAgICAgbGV0IHdlYmNhbURyb3Bkb3duID0gbnVsbDtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUubWVkaWFEZXZpY2VzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmVxdWVzdEJ1dHRvbiA9IChcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT0nbXhfVm9pY2VVc2VyU2V0dGluZ3NUYWJfbWlzc2luZ01lZGlhUGVybWlzc2lvbnMnPlxuICAgICAgICAgICAgICAgICAgICA8cD57X3QoXCJNaXNzaW5nIG1lZGlhIHBlcm1pc3Npb25zLCBjbGljayB0aGUgYnV0dG9uIGJlbG93IHRvIHJlcXVlc3QuXCIpfTwvcD5cbiAgICAgICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b24gb25DbGljaz17dGhpcy5fcmVxdWVzdE1lZGlhUGVybWlzc2lvbnN9IGtpbmQ9XCJwcmltYXJ5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJSZXF1ZXN0IG1lZGlhIHBlcm1pc3Npb25zXCIpfVxuICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc3RhdGUubWVkaWFEZXZpY2VzKSB7XG4gICAgICAgICAgICBzcGVha2VyRHJvcGRvd24gPSA8cD57IF90KCdObyBBdWRpbyBPdXRwdXRzIGRldGVjdGVkJykgfTwvcD47XG4gICAgICAgICAgICBtaWNyb3Bob25lRHJvcGRvd24gPSA8cD57IF90KCdObyBNaWNyb3Bob25lcyBkZXRlY3RlZCcpIH08L3A+O1xuICAgICAgICAgICAgd2ViY2FtRHJvcGRvd24gPSA8cD57IF90KCdObyBXZWJjYW1zIGRldGVjdGVkJykgfTwvcD47XG5cbiAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRPcHRpb24gPSB7XG4gICAgICAgICAgICAgICAgZGV2aWNlSWQ6ICcnLFxuICAgICAgICAgICAgICAgIGxhYmVsOiBfdCgnRGVmYXVsdCBEZXZpY2UnKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBnZXREZWZhdWx0RGV2aWNlID0gKGRldmljZXMpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBOb3RlIHdlJ3JlIGxvb2tpbmcgZm9yIGEgZGV2aWNlIHdpdGggZGV2aWNlSWQgJ2RlZmF1bHQnIGJ1dCBhZGRpbmcgYSBkZXZpY2VcbiAgICAgICAgICAgICAgICAvLyB3aXRoIGRldmljZUlkID09IHRoZSBlbXB0eSBzdHJpbmc6IHRoaXMgaXMgYmVjYXVzZSBDaHJvbWUgZ2l2ZXMgdXMgYSBkZXZpY2VcbiAgICAgICAgICAgICAgICAvLyB3aXRoIGRldmljZUlkICdkZWZhdWx0Jywgc28gd2UncmUgbG9va2luZyBmb3IgdGhpcywgbm90IHRoZSBvbmUgd2UgYXJlIGFkZGluZy5cbiAgICAgICAgICAgICAgICBpZiAoIWRldmljZXMuc29tZSgoaSkgPT4gaS5kZXZpY2VJZCA9PT0gJ2RlZmF1bHQnKSkge1xuICAgICAgICAgICAgICAgICAgICBkZXZpY2VzLnVuc2hpZnQoZGVmYXVsdE9wdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2RlZmF1bHQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IGF1ZGlvT3V0cHV0cyA9IHRoaXMuc3RhdGUubWVkaWFEZXZpY2VzLmF1ZGlvb3V0cHV0LnNsaWNlKDApO1xuICAgICAgICAgICAgaWYgKGF1ZGlvT3V0cHV0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdERldmljZSA9IGdldERlZmF1bHREZXZpY2UoYXVkaW9PdXRwdXRzKTtcbiAgICAgICAgICAgICAgICBzcGVha2VyRHJvcGRvd24gPSAoXG4gICAgICAgICAgICAgICAgICAgIDxGaWVsZCBlbGVtZW50PVwic2VsZWN0XCIgbGFiZWw9e190KFwiQXVkaW8gT3V0cHV0XCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUuYWN0aXZlQXVkaW9PdXRwdXQgfHwgZGVmYXVsdERldmljZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLl9zZXRBdWRpb091dHB1dH0+XG4gICAgICAgICAgICAgICAgICAgICAgICB7dGhpcy5fcmVuZGVyRGV2aWNlT3B0aW9ucyhhdWRpb091dHB1dHMsICdhdWRpb091dHB1dCcpfVxuICAgICAgICAgICAgICAgICAgICA8L0ZpZWxkPlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGF1ZGlvSW5wdXRzID0gdGhpcy5zdGF0ZS5tZWRpYURldmljZXMuYXVkaW9pbnB1dC5zbGljZSgwKTtcbiAgICAgICAgICAgIGlmIChhdWRpb0lucHV0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdERldmljZSA9IGdldERlZmF1bHREZXZpY2UoYXVkaW9JbnB1dHMpO1xuICAgICAgICAgICAgICAgIG1pY3JvcGhvbmVEcm9wZG93biA9IChcbiAgICAgICAgICAgICAgICAgICAgPEZpZWxkIGVsZW1lbnQ9XCJzZWxlY3RcIiBsYWJlbD17X3QoXCJNaWNyb3Bob25lXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUuYWN0aXZlQXVkaW9JbnB1dCB8fCBkZWZhdWx0RGV2aWNlfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMuX3NldEF1ZGlvSW5wdXR9PlxuICAgICAgICAgICAgICAgICAgICAgICAge3RoaXMuX3JlbmRlckRldmljZU9wdGlvbnMoYXVkaW9JbnB1dHMsICdhdWRpb0lucHV0Jyl9XG4gICAgICAgICAgICAgICAgICAgIDwvRmllbGQ+XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgdmlkZW9JbnB1dHMgPSB0aGlzLnN0YXRlLm1lZGlhRGV2aWNlcy52aWRlb2lucHV0LnNsaWNlKDApO1xuICAgICAgICAgICAgaWYgKHZpZGVvSW5wdXRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkZWZhdWx0RGV2aWNlID0gZ2V0RGVmYXVsdERldmljZSh2aWRlb0lucHV0cyk7XG4gICAgICAgICAgICAgICAgd2ViY2FtRHJvcGRvd24gPSAoXG4gICAgICAgICAgICAgICAgICAgIDxGaWVsZCBlbGVtZW50PVwic2VsZWN0XCIgbGFiZWw9e190KFwiQ2FtZXJhXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUuYWN0aXZlVmlkZW9JbnB1dCB8fCBkZWZhdWx0RGV2aWNlfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMuX3NldFZpZGVvSW5wdXR9PlxuICAgICAgICAgICAgICAgICAgICAgICAge3RoaXMuX3JlbmRlckRldmljZU9wdGlvbnModmlkZW9JbnB1dHMsICd2aWRlb0lucHV0Jyl9XG4gICAgICAgICAgICAgICAgICAgIDwvRmllbGQ+XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1NldHRpbmdzVGFiIG14X1ZvaWNlVXNlclNldHRpbmdzVGFiXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9TZXR0aW5nc1RhYl9oZWFkaW5nXCI+e190KFwiVm9pY2UgJiBWaWRlb1wiKX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1NldHRpbmdzVGFiX3NlY3Rpb25cIj5cbiAgICAgICAgICAgICAgICAgICAge3JlcXVlc3RCdXR0b259XG4gICAgICAgICAgICAgICAgICAgIHtzcGVha2VyRHJvcGRvd259XG4gICAgICAgICAgICAgICAgICAgIHttaWNyb3Bob25lRHJvcGRvd259XG4gICAgICAgICAgICAgICAgICAgIHt3ZWJjYW1Ecm9wZG93bn1cbiAgICAgICAgICAgICAgICAgICAgPFNldHRpbmdzRmxhZyBuYW1lPSdWaWRlb1ZpZXcuZmxpcFZpZGVvSG9yaXpvbnRhbGx5JyBsZXZlbD17U2V0dGluZ0xldmVsLkFDQ09VTlR9IC8+XG4gICAgICAgICAgICAgICAgICAgIDxTZXR0aW5nc0ZsYWdcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9J3dlYlJ0Y0FsbG93UGVlclRvUGVlcidcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPXtTZXR0aW5nTGV2ZWwuREVWSUNFfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMuX2NoYW5nZVdlYlJ0Y01ldGhvZH1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPFNldHRpbmdzRmxhZ1xuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0nZmFsbGJhY2tJQ0VTZXJ2ZXJBbGxvd2VkJ1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9e1NldHRpbmdMZXZlbC5ERVZJQ0V9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5fY2hhbmdlRmFsbGJhY2tJQ0VTZXJ2ZXJBbGxvd2VkfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICk7XG4gICAgfVxufVxuIl19