matrix-react-sdk
Version:
SDK for matrix.org using React
323 lines (313 loc) • 46.8 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "RovingAccessibleButton", {
enumerable: true,
get: function () {
return _RovingAccessibleButton.RovingAccessibleButton;
}
});
exports.RovingTabIndexProvider = exports.RovingTabIndexContext = void 0;
Object.defineProperty(exports, "RovingTabIndexWrapper", {
enumerable: true,
get: function () {
return _RovingTabIndexWrapper.RovingTabIndexWrapper;
}
});
exports.Type = void 0;
exports.checkInputableElement = checkInputableElement;
exports.useRovingTabIndex = exports.reducer = exports.findSiblingElement = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _KeyBindingsManager = require("../KeyBindingsManager");
var _KeyboardShortcuts = require("./KeyboardShortcuts");
var _RovingTabIndexWrapper = require("./roving/RovingTabIndexWrapper");
var _RovingAccessibleButton = require("./roving/RovingAccessibleButton");
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 2020 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.
*/
/**
* Module to simplify implementing the Roving TabIndex accessibility technique
*
* Wrap the Widget in an RovingTabIndexContextProvider
* and then for all buttons make use of useRovingTabIndex or RovingTabIndexWrapper.
* The code will keep track of which tabIndex was most recently focused and expose that information as `isActive` which
* can then be used to only set the tabIndex to 0 as expected by the roving tabindex technique.
* When the active button gets unmounted the closest button will be chosen as expected.
* Initially the first button to mount will be given active state.
*
* https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets#Technique_1_Roving_tabindex
*/
// Check for form elements which utilize the arrow keys for native functions
// like many of the text input varieties.
//
// i.e. it's ok to press the down arrow on a radio button to move to the next
// radio. But it's not ok to press the down arrow on a <input type="text"> to
// move away because the down arrow should move the cursor to the end of the
// input.
function checkInputableElement(el) {
return el.matches('input:not([type="radio"]):not([type="checkbox"]), textarea, select, [contenteditable=true]');
}
const RovingTabIndexContext = exports.RovingTabIndexContext = /*#__PURE__*/(0, _react.createContext)({
state: {
refs: [] // list of refs in DOM order
},
dispatch: () => {}
});
RovingTabIndexContext.displayName = "RovingTabIndexContext";
let Type = exports.Type = /*#__PURE__*/function (Type) {
Type["Register"] = "REGISTER";
Type["Unregister"] = "UNREGISTER";
Type["SetFocus"] = "SET_FOCUS";
Type["Update"] = "UPDATE";
return Type;
}({});
const refSorter = (a, b) => {
if (a === b) {
return 0;
}
const position = a.current.compareDocumentPosition(b.current);
if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
return -1;
} else if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
return 1;
} else {
return 0;
}
};
const reducer = (state, action) => {
switch (action.type) {
case Type.Register:
{
if (!state.activeRef) {
// Our list of refs was empty, set activeRef to this first item
state.activeRef = action.payload.ref;
}
// Sadly due to the potential of DOM elements swapping order we can't do anything fancy like a binary insert
state.refs.push(action.payload.ref);
state.refs.sort(refSorter);
return _objectSpread({}, state);
}
case Type.Unregister:
{
const oldIndex = state.refs.findIndex(r => r === action.payload.ref);
if (oldIndex === -1) {
return state; // already removed, this should not happen
}
if (state.refs.splice(oldIndex, 1)[0] === state.activeRef) {
// we just removed the active ref, need to replace it
// pick the ref closest to the index the old ref was in
if (oldIndex >= state.refs.length) {
state.activeRef = findSiblingElement(state.refs, state.refs.length - 1, true);
} else {
state.activeRef = findSiblingElement(state.refs, oldIndex) || findSiblingElement(state.refs, oldIndex, true);
}
if (document.activeElement === document.body) {
// if the focus got reverted to the body then the user was likely focused on the unmounted element
setTimeout(() => state.activeRef?.current?.focus(), 0);
}
}
// update the refs list
return _objectSpread({}, state);
}
case Type.SetFocus:
{
// if the ref doesn't change just return the same object reference to skip a re-render
if (state.activeRef === action.payload.ref) return state;
// update active ref
state.activeRef = action.payload.ref;
return _objectSpread({}, state);
}
case Type.Update:
{
state.refs.sort(refSorter);
return _objectSpread({}, state);
}
default:
return state;
}
};
exports.reducer = reducer;
const findSiblingElement = (refs, startIndex, backwards = false, loop = false) => {
if (backwards) {
for (let i = startIndex; i < refs.length && i >= 0; i--) {
if (refs[i].current?.offsetParent !== null) {
return refs[i];
}
}
if (loop) {
return findSiblingElement(refs.slice(startIndex + 1), refs.length - 1, true, false);
}
} else {
for (let i = startIndex; i < refs.length && i >= 0; i++) {
if (refs[i].current?.offsetParent !== null) {
return refs[i];
}
}
if (loop) {
return findSiblingElement(refs.slice(0, startIndex), 0, false, false);
}
}
};
exports.findSiblingElement = findSiblingElement;
const RovingTabIndexProvider = ({
children,
handleHomeEnd,
handleUpDown,
handleLeftRight,
handleLoop,
handleInputFields,
scrollIntoView,
onKeyDown
}) => {
const [state, dispatch] = (0, _react.useReducer)(reducer, {
refs: []
});
const context = (0, _react.useMemo)(() => ({
state,
dispatch
}), [state]);
const onKeyDownHandler = (0, _react.useCallback)(ev => {
if (onKeyDown) {
onKeyDown(ev, context.state, context.dispatch);
if (ev.defaultPrevented) {
return;
}
}
let handled = false;
const action = (0, _KeyBindingsManager.getKeyBindingsManager)().getAccessibilityAction(ev);
let focusRef;
// Don't interfere with input default keydown behaviour
// but allow people to move focus from it with Tab.
if (!handleInputFields && checkInputableElement(ev.target)) {
switch (action) {
case _KeyboardShortcuts.KeyBindingAction.Tab:
handled = true;
if (context.state.refs.length > 0) {
const idx = context.state.refs.indexOf(context.state.activeRef);
focusRef = findSiblingElement(context.state.refs, idx + (ev.shiftKey ? -1 : 1), ev.shiftKey);
}
break;
}
} else {
// check if we actually have any items
switch (action) {
case _KeyboardShortcuts.KeyBindingAction.Home:
if (handleHomeEnd) {
handled = true;
// move focus to first (visible) item
focusRef = findSiblingElement(context.state.refs, 0);
}
break;
case _KeyboardShortcuts.KeyBindingAction.End:
if (handleHomeEnd) {
handled = true;
// move focus to last (visible) item
focusRef = findSiblingElement(context.state.refs, context.state.refs.length - 1, true);
}
break;
case _KeyboardShortcuts.KeyBindingAction.ArrowDown:
case _KeyboardShortcuts.KeyBindingAction.ArrowRight:
if (action === _KeyboardShortcuts.KeyBindingAction.ArrowDown && handleUpDown || action === _KeyboardShortcuts.KeyBindingAction.ArrowRight && handleLeftRight) {
handled = true;
if (context.state.refs.length > 0) {
const idx = context.state.refs.indexOf(context.state.activeRef);
focusRef = findSiblingElement(context.state.refs, idx + 1, false, handleLoop);
}
}
break;
case _KeyboardShortcuts.KeyBindingAction.ArrowUp:
case _KeyboardShortcuts.KeyBindingAction.ArrowLeft:
if (action === _KeyboardShortcuts.KeyBindingAction.ArrowUp && handleUpDown || action === _KeyboardShortcuts.KeyBindingAction.ArrowLeft && handleLeftRight) {
handled = true;
if (context.state.refs.length > 0) {
const idx = context.state.refs.indexOf(context.state.activeRef);
focusRef = findSiblingElement(context.state.refs, idx - 1, true, handleLoop);
}
}
break;
}
}
if (handled) {
ev.preventDefault();
ev.stopPropagation();
}
if (focusRef) {
focusRef.current?.focus();
// programmatic focus doesn't fire the onFocus handler, so we must do the do ourselves
dispatch({
type: Type.SetFocus,
payload: {
ref: focusRef
}
});
if (scrollIntoView) {
focusRef.current?.scrollIntoView(scrollIntoView);
}
}
}, [context, onKeyDown, handleHomeEnd, handleUpDown, handleLeftRight, handleLoop, handleInputFields, scrollIntoView]);
const onDragEndHandler = (0, _react.useCallback)(() => {
dispatch({
type: Type.Update
});
}, []);
return /*#__PURE__*/_react.default.createElement(RovingTabIndexContext.Provider, {
value: context
}, children({
onKeyDownHandler,
onDragEndHandler
}));
};
// Hook to register a roving tab index
// inputRef parameter specifies the ref to use
// onFocus should be called when the index gained focus in any manner
// isActive should be used to set tabIndex in a manner such as `tabIndex={isActive ? 0 : -1}`
// ref should be passed to a DOM node which will be used for DOM compareDocumentPosition
exports.RovingTabIndexProvider = RovingTabIndexProvider;
const useRovingTabIndex = inputRef => {
const context = (0, _react.useContext)(RovingTabIndexContext);
let ref = (0, _react.useRef)(null);
if (inputRef) {
// if we are given a ref, use it instead of ours
ref = inputRef;
}
// setup (after refs)
(0, _react.useEffect)(() => {
context.dispatch({
type: Type.Register,
payload: {
ref
}
});
// teardown
return () => {
context.dispatch({
type: Type.Unregister,
payload: {
ref
}
});
};
}, []); // eslint-disable-line react-hooks/exhaustive-deps
const onFocus = (0, _react.useCallback)(() => {
context.dispatch({
type: Type.SetFocus,
payload: {
ref
}
});
}, []); // eslint-disable-line react-hooks/exhaustive-deps
const isActive = context.state.activeRef === ref;
return [onFocus, isActive, ref];
};
// re-export the semantic helper components for simplicity
exports.useRovingTabIndex = useRovingTabIndex;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfS2V5QmluZGluZ3NNYW5hZ2VyIiwiX0tleWJvYXJkU2hvcnRjdXRzIiwiX1JvdmluZ1RhYkluZGV4V3JhcHBlciIsIl9Sb3ZpbmdBY2Nlc3NpYmxlQnV0dG9uIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0Iiwib3duS2V5cyIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJvIiwiZmlsdGVyIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiY2hlY2tJbnB1dGFibGVFbGVtZW50IiwiZWwiLCJtYXRjaGVzIiwiUm92aW5nVGFiSW5kZXhDb250ZXh0IiwiZXhwb3J0cyIsImNyZWF0ZUNvbnRleHQiLCJzdGF0ZSIsInJlZnMiLCJkaXNwYXRjaCIsImRpc3BsYXlOYW1lIiwiVHlwZSIsInJlZlNvcnRlciIsImIiLCJwb3NpdGlvbiIsImN1cnJlbnQiLCJjb21wYXJlRG9jdW1lbnRQb3NpdGlvbiIsIk5vZGUiLCJET0NVTUVOVF9QT1NJVElPTl9GT0xMT1dJTkciLCJET0NVTUVOVF9QT1NJVElPTl9DT05UQUlORURfQlkiLCJET0NVTUVOVF9QT1NJVElPTl9QUkVDRURJTkciLCJET0NVTUVOVF9QT1NJVElPTl9DT05UQUlOUyIsInJlZHVjZXIiLCJhY3Rpb24iLCJ0eXBlIiwiUmVnaXN0ZXIiLCJhY3RpdmVSZWYiLCJwYXlsb2FkIiwicmVmIiwic29ydCIsIlVucmVnaXN0ZXIiLCJvbGRJbmRleCIsImZpbmRJbmRleCIsInNwbGljZSIsImZpbmRTaWJsaW5nRWxlbWVudCIsImRvY3VtZW50IiwiYWN0aXZlRWxlbWVudCIsImJvZHkiLCJzZXRUaW1lb3V0IiwiZm9jdXMiLCJTZXRGb2N1cyIsIlVwZGF0ZSIsInN0YXJ0SW5kZXgiLCJiYWNrd2FyZHMiLCJsb29wIiwib2Zmc2V0UGFyZW50Iiwic2xpY2UiLCJSb3ZpbmdUYWJJbmRleFByb3ZpZGVyIiwiY2hpbGRyZW4iLCJoYW5kbGVIb21lRW5kIiwiaGFuZGxlVXBEb3duIiwiaGFuZGxlTGVmdFJpZ2h0IiwiaGFuZGxlTG9vcCIsImhhbmRsZUlucHV0RmllbGRzIiwic2Nyb2xsSW50b1ZpZXciLCJvbktleURvd24iLCJ1c2VSZWR1Y2VyIiwiY29udGV4dCIsInVzZU1lbW8iLCJvbktleURvd25IYW5kbGVyIiwidXNlQ2FsbGJhY2siLCJldiIsImRlZmF1bHRQcmV2ZW50ZWQiLCJoYW5kbGVkIiwiZ2V0S2V5QmluZGluZ3NNYW5hZ2VyIiwiZ2V0QWNjZXNzaWJpbGl0eUFjdGlvbiIsImZvY3VzUmVmIiwidGFyZ2V0IiwiS2V5QmluZGluZ0FjdGlvbiIsIlRhYiIsImlkeCIsImluZGV4T2YiLCJzaGlmdEtleSIsIkhvbWUiLCJFbmQiLCJBcnJvd0Rvd24iLCJBcnJvd1JpZ2h0IiwiQXJyb3dVcCIsIkFycm93TGVmdCIsInByZXZlbnREZWZhdWx0Iiwic3RvcFByb3BhZ2F0aW9uIiwib25EcmFnRW5kSGFuZGxlciIsImNyZWF0ZUVsZW1lbnQiLCJQcm92aWRlciIsInZhbHVlIiwidXNlUm92aW5nVGFiSW5kZXgiLCJpbnB1dFJlZiIsInVzZUNvbnRleHQiLCJ1c2VSZWYiLCJ1c2VFZmZlY3QiLCJvbkZvY3VzIiwiaXNBY3RpdmUiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvYWNjZXNzaWJpbGl0eS9Sb3ZpbmdUYWJJbmRleC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7XG4gICAgY3JlYXRlQ29udGV4dCxcbiAgICB1c2VDYWxsYmFjayxcbiAgICB1c2VDb250ZXh0LFxuICAgIHVzZUVmZmVjdCxcbiAgICB1c2VNZW1vLFxuICAgIHVzZVJlZixcbiAgICB1c2VSZWR1Y2VyLFxuICAgIFJlZHVjZXIsXG4gICAgRGlzcGF0Y2gsXG4gICAgUmVmT2JqZWN0LFxuICAgIFJlYWN0Tm9kZSxcbn0gZnJvbSBcInJlYWN0XCI7XG5cbmltcG9ydCB7IGdldEtleUJpbmRpbmdzTWFuYWdlciB9IGZyb20gXCIuLi9LZXlCaW5kaW5nc01hbmFnZXJcIjtcbmltcG9ydCB7IEtleUJpbmRpbmdBY3Rpb24gfSBmcm9tIFwiLi9LZXlib2FyZFNob3J0Y3V0c1wiO1xuaW1wb3J0IHsgRm9jdXNIYW5kbGVyLCBSZWYgfSBmcm9tIFwiLi9yb3ZpbmcvdHlwZXNcIjtcblxuLyoqXG4gKiBNb2R1bGUgdG8gc2ltcGxpZnkgaW1wbGVtZW50aW5nIHRoZSBSb3ZpbmcgVGFiSW5kZXggYWNjZXNzaWJpbGl0eSB0ZWNobmlxdWVcbiAqXG4gKiBXcmFwIHRoZSBXaWRnZXQgaW4gYW4gUm92aW5nVGFiSW5kZXhDb250ZXh0UHJvdmlkZXJcbiAqIGFuZCB0aGVuIGZvciBhbGwgYnV0dG9ucyBtYWtlIHVzZSBvZiB1c2VSb3ZpbmdUYWJJbmRleCBvciBSb3ZpbmdUYWJJbmRleFdyYXBwZXIuXG4gKiBUaGUgY29kZSB3aWxsIGtlZXAgdHJhY2sgb2Ygd2hpY2ggdGFiSW5kZXggd2FzIG1vc3QgcmVjZW50bHkgZm9jdXNlZCBhbmQgZXhwb3NlIHRoYXQgaW5mb3JtYXRpb24gYXMgYGlzQWN0aXZlYCB3aGljaFxuICogY2FuIHRoZW4gYmUgdXNlZCB0byBvbmx5IHNldCB0aGUgdGFiSW5kZXggdG8gMCBhcyBleHBlY3RlZCBieSB0aGUgcm92aW5nIHRhYmluZGV4IHRlY2huaXF1ZS5cbiAqIFdoZW4gdGhlIGFjdGl2ZSBidXR0b24gZ2V0cyB1bm1vdW50ZWQgdGhlIGNsb3Nlc3QgYnV0dG9uIHdpbGwgYmUgY2hvc2VuIGFzIGV4cGVjdGVkLlxuICogSW5pdGlhbGx5IHRoZSBmaXJzdCBidXR0b24gdG8gbW91bnQgd2lsbCBiZSBnaXZlbiBhY3RpdmUgc3RhdGUuXG4gKlxuICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQWNjZXNzaWJpbGl0eS9LZXlib2FyZC1uYXZpZ2FibGVfSmF2YVNjcmlwdF93aWRnZXRzI1RlY2huaXF1ZV8xX1JvdmluZ190YWJpbmRleFxuICovXG5cbi8vIENoZWNrIGZvciBmb3JtIGVsZW1lbnRzIHdoaWNoIHV0aWxpemUgdGhlIGFycm93IGtleXMgZm9yIG5hdGl2ZSBmdW5jdGlvbnNcbi8vIGxpa2UgbWFueSBvZiB0aGUgdGV4dCBpbnB1dCB2YXJpZXRpZXMuXG4vL1xuLy8gaS5lLiBpdCdzIG9rIHRvIHByZXNzIHRoZSBkb3duIGFycm93IG9uIGEgcmFkaW8gYnV0dG9uIHRvIG1vdmUgdG8gdGhlIG5leHRcbi8vIHJhZGlvLiBCdXQgaXQncyBub3Qgb2sgdG8gcHJlc3MgdGhlIGRvd24gYXJyb3cgb24gYSA8aW5wdXQgdHlwZT1cInRleHRcIj4gdG9cbi8vIG1vdmUgYXdheSBiZWNhdXNlIHRoZSBkb3duIGFycm93IHNob3VsZCBtb3ZlIHRoZSBjdXJzb3IgdG8gdGhlIGVuZCBvZiB0aGVcbi8vIGlucHV0LlxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSW5wdXRhYmxlRWxlbWVudChlbDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWwubWF0Y2hlcygnaW5wdXQ6bm90KFt0eXBlPVwicmFkaW9cIl0pOm5vdChbdHlwZT1cImNoZWNrYm94XCJdKSwgdGV4dGFyZWEsIHNlbGVjdCwgW2NvbnRlbnRlZGl0YWJsZT10cnVlXScpO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgYWN0aXZlUmVmPzogUmVmO1xuICAgIHJlZnM6IFJlZltdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElDb250ZXh0IHtcbiAgICBzdGF0ZTogSVN0YXRlO1xuICAgIGRpc3BhdGNoOiBEaXNwYXRjaDxJQWN0aW9uPjtcbn1cblxuZXhwb3J0IGNvbnN0IFJvdmluZ1RhYkluZGV4Q29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8SUNvbnRleHQ+KHtcbiAgICBzdGF0ZToge1xuICAgICAgICByZWZzOiBbXSwgLy8gbGlzdCBvZiByZWZzIGluIERPTSBvcmRlclxuICAgIH0sXG4gICAgZGlzcGF0Y2g6ICgpID0+IHt9LFxufSk7XG5Sb3ZpbmdUYWJJbmRleENvbnRleHQuZGlzcGxheU5hbWUgPSBcIlJvdmluZ1RhYkluZGV4Q29udGV4dFwiO1xuXG5leHBvcnQgZW51bSBUeXBlIHtcbiAgICBSZWdpc3RlciA9IFwiUkVHSVNURVJcIixcbiAgICBVbnJlZ2lzdGVyID0gXCJVTlJFR0lTVEVSXCIsXG4gICAgU2V0Rm9jdXMgPSBcIlNFVF9GT0NVU1wiLFxuICAgIFVwZGF0ZSA9IFwiVVBEQVRFXCIsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUFjdGlvbiB7XG4gICAgdHlwZTogRXhjbHVkZTxUeXBlLCBUeXBlLlVwZGF0ZT47XG4gICAgcGF5bG9hZDoge1xuICAgICAgICByZWY6IFJlZjtcbiAgICB9O1xufVxuXG5pbnRlcmZhY2UgVXBkYXRlQWN0aW9uIHtcbiAgICB0eXBlOiBUeXBlLlVwZGF0ZTtcbiAgICBwYXlsb2FkPzogdW5kZWZpbmVkO1xufVxuXG50eXBlIEFjdGlvbiA9IElBY3Rpb24gfCBVcGRhdGVBY3Rpb247XG5cbmNvbnN0IHJlZlNvcnRlciA9IChhOiBSZWYsIGI6IFJlZik6IG51bWJlciA9PiB7XG4gICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgY29uc3QgcG9zaXRpb24gPSBhLmN1cnJlbnQhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKGIuY3VycmVudCEpO1xuXG4gICAgaWYgKHBvc2l0aW9uICYgTm9kZS5ET0NVTUVOVF9QT1NJVElPTl9GT0xMT1dJTkcgfHwgcG9zaXRpb24gJiBOb2RlLkRPQ1VNRU5UX1BPU0lUSU9OX0NPTlRBSU5FRF9CWSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbiAmIE5vZGUuRE9DVU1FTlRfUE9TSVRJT05fUFJFQ0VESU5HIHx8IHBvc2l0aW9uICYgTm9kZS5ET0NVTUVOVF9QT1NJVElPTl9DT05UQUlOUykge1xuICAgICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlcjogUmVkdWNlcjxJU3RhdGUsIEFjdGlvbj4gPSAoc3RhdGU6IElTdGF0ZSwgYWN0aW9uOiBBY3Rpb24pID0+IHtcbiAgICBzd2l0Y2ggKGFjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgVHlwZS5SZWdpc3Rlcjoge1xuICAgICAgICAgICAgaWYgKCFzdGF0ZS5hY3RpdmVSZWYpIHtcbiAgICAgICAgICAgICAgICAvLyBPdXIgbGlzdCBvZiByZWZzIHdhcyBlbXB0eSwgc2V0IGFjdGl2ZVJlZiB0byB0aGlzIGZpcnN0IGl0ZW1cbiAgICAgICAgICAgICAgICBzdGF0ZS5hY3RpdmVSZWYgPSBhY3Rpb24ucGF5bG9hZC5yZWY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNhZGx5IGR1ZSB0byB0aGUgcG90ZW50aWFsIG9mIERPTSBlbGVtZW50cyBzd2FwcGluZyBvcmRlciB3ZSBjYW4ndCBkbyBhbnl0aGluZyBmYW5jeSBsaWtlIGEgYmluYXJ5IGluc2VydFxuICAgICAgICAgICAgc3RhdGUucmVmcy5wdXNoKGFjdGlvbi5wYXlsb2FkLnJlZik7XG4gICAgICAgICAgICBzdGF0ZS5yZWZzLnNvcnQocmVmU29ydGVyKTtcblxuICAgICAgICAgICAgcmV0dXJuIHsgLi4uc3RhdGUgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgVHlwZS5VbnJlZ2lzdGVyOiB7XG4gICAgICAgICAgICBjb25zdCBvbGRJbmRleCA9IHN0YXRlLnJlZnMuZmluZEluZGV4KChyKSA9PiByID09PSBhY3Rpb24ucGF5bG9hZC5yZWYpO1xuXG4gICAgICAgICAgICBpZiAob2xkSW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0YXRlOyAvLyBhbHJlYWR5IHJlbW92ZWQsIHRoaXMgc2hvdWxkIG5vdCBoYXBwZW5cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHN0YXRlLnJlZnMuc3BsaWNlKG9sZEluZGV4LCAxKVswXSA9PT0gc3RhdGUuYWN0aXZlUmVmKSB7XG4gICAgICAgICAgICAgICAgLy8gd2UganVzdCByZW1vdmVkIHRoZSBhY3RpdmUgcmVmLCBuZWVkIHRvIHJlcGxhY2UgaXRcbiAgICAgICAgICAgICAgICAvLyBwaWNrIHRoZSByZWYgY2xvc2VzdCB0byB0aGUgaW5kZXggdGhlIG9sZCByZWYgd2FzIGluXG4gICAgICAgICAgICAgICAgaWYgKG9sZEluZGV4ID49IHN0YXRlLnJlZnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlLmFjdGl2ZVJlZiA9IGZpbmRTaWJsaW5nRWxlbWVudChzdGF0ZS5yZWZzLCBzdGF0ZS5yZWZzLmxlbmd0aCAtIDEsIHRydWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlLmFjdGl2ZVJlZiA9XG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5kU2libGluZ0VsZW1lbnQoc3RhdGUucmVmcywgb2xkSW5kZXgpIHx8IGZpbmRTaWJsaW5nRWxlbWVudChzdGF0ZS5yZWZzLCBvbGRJbmRleCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBmb2N1cyBnb3QgcmV2ZXJ0ZWQgdG8gdGhlIGJvZHkgdGhlbiB0aGUgdXNlciB3YXMgbGlrZWx5IGZvY3VzZWQgb24gdGhlIHVubW91bnRlZCBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gc3RhdGUuYWN0aXZlUmVmPy5jdXJyZW50Py5mb2N1cygpLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgcmVmcyBsaXN0XG4gICAgICAgICAgICByZXR1cm4geyAuLi5zdGF0ZSB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSBUeXBlLlNldEZvY3VzOiB7XG4gICAgICAgICAgICAvLyBpZiB0aGUgcmVmIGRvZXNuJ3QgY2hhbmdlIGp1c3QgcmV0dXJuIHRoZSBzYW1lIG9iamVjdCByZWZlcmVuY2UgdG8gc2tpcCBhIHJlLXJlbmRlclxuICAgICAgICAgICAgaWYgKHN0YXRlLmFjdGl2ZVJlZiA9PT0gYWN0aW9uLnBheWxvYWQucmVmKSByZXR1cm4gc3RhdGU7XG4gICAgICAgICAgICAvLyB1cGRhdGUgYWN0aXZlIHJlZlxuICAgICAgICAgICAgc3RhdGUuYWN0aXZlUmVmID0gYWN0aW9uLnBheWxvYWQucmVmO1xuICAgICAgICAgICAgcmV0dXJuIHsgLi4uc3RhdGUgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgVHlwZS5VcGRhdGU6IHtcbiAgICAgICAgICAgIHN0YXRlLnJlZnMuc29ydChyZWZTb3J0ZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHsgLi4uc3RhdGUgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gc3RhdGU7XG4gICAgfVxufTtcblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgaGFuZGxlTG9vcD86IGJvb2xlYW47XG4gICAgaGFuZGxlSG9tZUVuZD86IGJvb2xlYW47XG4gICAgaGFuZGxlVXBEb3duPzogYm9vbGVhbjtcbiAgICBoYW5kbGVMZWZ0UmlnaHQ/OiBib29sZWFuO1xuICAgIGhhbmRsZUlucHV0RmllbGRzPzogYm9vbGVhbjtcbiAgICBzY3JvbGxJbnRvVmlldz86IGJvb2xlYW4gfCBTY3JvbGxJbnRvVmlld09wdGlvbnM7XG4gICAgY2hpbGRyZW4ocmVuZGVyUHJvcHM6IHsgb25LZXlEb3duSGFuZGxlcihldjogUmVhY3QuS2V5Ym9hcmRFdmVudCk6IHZvaWQ7IG9uRHJhZ0VuZEhhbmRsZXIoKTogdm9pZCB9KTogUmVhY3ROb2RlO1xuICAgIG9uS2V5RG93bj8oZXY6IFJlYWN0LktleWJvYXJkRXZlbnQsIHN0YXRlOiBJU3RhdGUsIGRpc3BhdGNoOiBEaXNwYXRjaDxJQWN0aW9uPik6IHZvaWQ7XG59XG5cbmV4cG9ydCBjb25zdCBmaW5kU2libGluZ0VsZW1lbnQgPSAoXG4gICAgcmVmczogUmVmT2JqZWN0PEhUTUxFbGVtZW50PltdLFxuICAgIHN0YXJ0SW5kZXg6IG51bWJlcixcbiAgICBiYWNrd2FyZHMgPSBmYWxzZSxcbiAgICBsb29wID0gZmFsc2UsXG4pOiBSZWZPYmplY3Q8SFRNTEVsZW1lbnQ+IHwgdW5kZWZpbmVkID0+IHtcbiAgICBpZiAoYmFja3dhcmRzKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgcmVmcy5sZW5ndGggJiYgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGlmIChyZWZzW2ldLmN1cnJlbnQ/Lm9mZnNldFBhcmVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWZzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChsb29wKSB7XG4gICAgICAgICAgICByZXR1cm4gZmluZFNpYmxpbmdFbGVtZW50KHJlZnMuc2xpY2Uoc3RhcnRJbmRleCArIDEpLCByZWZzLmxlbmd0aCAtIDEsIHRydWUsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAobGV0IGkgPSBzdGFydEluZGV4OyBpIDwgcmVmcy5sZW5ndGggJiYgaSA+PSAwOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChyZWZzW2ldLmN1cnJlbnQ/Lm9mZnNldFBhcmVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWZzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChsb29wKSB7XG4gICAgICAgICAgICByZXR1cm4gZmluZFNpYmxpbmdFbGVtZW50KHJlZnMuc2xpY2UoMCwgc3RhcnRJbmRleCksIDAsIGZhbHNlLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5leHBvcnQgY29uc3QgUm92aW5nVGFiSW5kZXhQcm92aWRlcjogUmVhY3QuRkM8SVByb3BzPiA9ICh7XG4gICAgY2hpbGRyZW4sXG4gICAgaGFuZGxlSG9tZUVuZCxcbiAgICBoYW5kbGVVcERvd24sXG4gICAgaGFuZGxlTGVmdFJpZ2h0LFxuICAgIGhhbmRsZUxvb3AsXG4gICAgaGFuZGxlSW5wdXRGaWVsZHMsXG4gICAgc2Nyb2xsSW50b1ZpZXcsXG4gICAgb25LZXlEb3duLFxufSkgPT4ge1xuICAgIGNvbnN0IFtzdGF0ZSwgZGlzcGF0Y2hdID0gdXNlUmVkdWNlcjxSZWR1Y2VyPElTdGF0ZSwgQWN0aW9uPj4ocmVkdWNlciwge1xuICAgICAgICByZWZzOiBbXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGNvbnRleHQgPSB1c2VNZW1vPElDb250ZXh0PigoKSA9PiAoeyBzdGF0ZSwgZGlzcGF0Y2ggfSksIFtzdGF0ZV0pO1xuXG4gICAgY29uc3Qgb25LZXlEb3duSGFuZGxlciA9IHVzZUNhbGxiYWNrKFxuICAgICAgICAoZXY6IFJlYWN0LktleWJvYXJkRXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmIChvbktleURvd24pIHtcbiAgICAgICAgICAgICAgICBvbktleURvd24oZXYsIGNvbnRleHQuc3RhdGUsIGNvbnRleHQuZGlzcGF0Y2gpO1xuICAgICAgICAgICAgICAgIGlmIChldi5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBoYW5kbGVkID0gZmFsc2U7XG4gICAgICAgICAgICBjb25zdCBhY3Rpb24gPSBnZXRLZXlCaW5kaW5nc01hbmFnZXIoKS5nZXRBY2Nlc3NpYmlsaXR5QWN0aW9uKGV2KTtcbiAgICAgICAgICAgIGxldCBmb2N1c1JlZjogUmVmT2JqZWN0PEhUTUxFbGVtZW50PiB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIC8vIERvbid0IGludGVyZmVyZSB3aXRoIGlucHV0IGRlZmF1bHQga2V5ZG93biBiZWhhdmlvdXJcbiAgICAgICAgICAgIC8vIGJ1dCBhbGxvdyBwZW9wbGUgdG8gbW92ZSBmb2N1cyBmcm9tIGl0IHdpdGggVGFiLlxuICAgICAgICAgICAgaWYgKCFoYW5kbGVJbnB1dEZpZWxkcyAmJiBjaGVja0lucHV0YWJsZUVsZW1lbnQoZXYudGFyZ2V0IGFzIEhUTUxFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5QmluZGluZ0FjdGlvbi5UYWI6XG4gICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb250ZXh0LnN0YXRlLnJlZnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkeCA9IGNvbnRleHQuc3RhdGUucmVmcy5pbmRleE9mKGNvbnRleHQuc3RhdGUuYWN0aXZlUmVmISk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9jdXNSZWYgPSBmaW5kU2libGluZ0VsZW1lbnQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQuc3RhdGUucmVmcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWR4ICsgKGV2LnNoaWZ0S2V5ID8gLTEgOiAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXYuc2hpZnRLZXksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY2hlY2sgaWYgd2UgYWN0dWFsbHkgaGF2ZSBhbnkgaXRlbXNcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEtleUJpbmRpbmdBY3Rpb24uSG9tZTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoYW5kbGVIb21lRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbW92ZSBmb2N1cyB0byBmaXJzdCAodmlzaWJsZSkgaXRlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvY3VzUmVmID0gZmluZFNpYmxpbmdFbGVtZW50KGNvbnRleHQuc3RhdGUucmVmcywgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICBjYXNlIEtleUJpbmRpbmdBY3Rpb24uRW5kOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhhbmRsZUhvbWVFbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb3ZlIGZvY3VzIHRvIGxhc3QgKHZpc2libGUpIGl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb2N1c1JlZiA9IGZpbmRTaWJsaW5nRWxlbWVudChjb250ZXh0LnN0YXRlLnJlZnMsIGNvbnRleHQuc3RhdGUucmVmcy5sZW5ndGggLSAxLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5QmluZGluZ0FjdGlvbi5BcnJvd0Rvd246XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5QmluZGluZ0FjdGlvbi5BcnJvd1JpZ2h0OlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhY3Rpb24gPT09IEtleUJpbmRpbmdBY3Rpb24uQXJyb3dEb3duICYmIGhhbmRsZVVwRG93bikgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYWN0aW9uID09PSBLZXlCaW5kaW5nQWN0aW9uLkFycm93UmlnaHQgJiYgaGFuZGxlTGVmdFJpZ2h0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnRleHQuc3RhdGUucmVmcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkeCA9IGNvbnRleHQuc3RhdGUucmVmcy5pbmRleE9mKGNvbnRleHQuc3RhdGUuYWN0aXZlUmVmISk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvY3VzUmVmID0gZmluZFNpYmxpbmdFbGVtZW50KGNvbnRleHQuc3RhdGUucmVmcywgaWR4ICsgMSwgZmFsc2UsIGhhbmRsZUxvb3ApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5QmluZGluZ0FjdGlvbi5BcnJvd1VwOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIEtleUJpbmRpbmdBY3Rpb24uQXJyb3dMZWZ0OlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhY3Rpb24gPT09IEtleUJpbmRpbmdBY3Rpb24uQXJyb3dVcCAmJiBoYW5kbGVVcERvd24pIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGFjdGlvbiA9PT0gS2V5QmluZGluZ0FjdGlvbi5BcnJvd0xlZnQgJiYgaGFuZGxlTGVmdFJpZ2h0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnRleHQuc3RhdGUucmVmcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkeCA9IGNvbnRleHQuc3RhdGUucmVmcy5pbmRleE9mKGNvbnRleHQuc3RhdGUuYWN0aXZlUmVmISk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvY3VzUmVmID0gZmluZFNpYmxpbmdFbGVtZW50KGNvbnRleHQuc3RhdGUucmVmcywgaWR4IC0gMSwgdHJ1ZSwgaGFuZGxlTG9vcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaGFuZGxlZCkge1xuICAgICAgICAgICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChmb2N1c1JlZikge1xuICAgICAgICAgICAgICAgIGZvY3VzUmVmLmN1cnJlbnQ/LmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgLy8gcHJvZ3JhbW1hdGljIGZvY3VzIGRvZXNuJ3QgZmlyZSB0aGUgb25Gb2N1cyBoYW5kbGVyLCBzbyB3ZSBtdXN0IGRvIHRoZSBkbyBvdXJzZWx2ZXNcbiAgICAgICAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IFR5cGUuU2V0Rm9jdXMsXG4gICAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZjogZm9jdXNSZWYsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHNjcm9sbEludG9WaWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIGZvY3VzUmVmLmN1cnJlbnQ/LnNjcm9sbEludG9WaWV3KHNjcm9sbEludG9WaWV3KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFtcbiAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICBvbktleURvd24sXG4gICAgICAgICAgICBoYW5kbGVIb21lRW5kLFxuICAgICAgICAgICAgaGFuZGxlVXBEb3duLFxuICAgICAgICAgICAgaGFuZGxlTGVmdFJpZ2h0LFxuICAgICAgICAgICAgaGFuZGxlTG9vcCxcbiAgICAgICAgICAgIGhhbmRsZUlucHV0RmllbGRzLFxuICAgICAgICAgICAgc2Nyb2xsSW50b1ZpZXcsXG4gICAgICAgIF0sXG4gICAgKTtcblxuICAgIGNvbnN0IG9uRHJhZ0VuZEhhbmRsZXIgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6IFR5cGUuVXBkYXRlLFxuICAgICAgICB9KTtcbiAgICB9LCBbXSk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8Um92aW5nVGFiSW5kZXhDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXtjb250ZXh0fT5cbiAgICAgICAgICAgIHtjaGlsZHJlbih7IG9uS2V5RG93bkhhbmRsZXIsIG9uRHJhZ0VuZEhhbmRsZXIgfSl9XG4gICAgICAgIDwvUm92aW5nVGFiSW5kZXhDb250ZXh0LlByb3ZpZGVyPlxuICAgICk7XG59O1xuXG4vLyBIb29rIHRvIHJlZ2lzdGVyIGEgcm92aW5nIHRhYiBpbmRleFxuLy8gaW5wdXRSZWYgcGFyYW1ldGVyIHNwZWNpZmllcyB0aGUgcmVmIHRvIHVzZVxuLy8gb25Gb2N1cyBzaG91bGQgYmUgY2FsbGVkIHdoZW4gdGhlIGluZGV4IGdhaW5lZCBmb2N1cyBpbiBhbnkgbWFubmVyXG4vLyBpc0FjdGl2ZSBzaG91bGQgYmUgdXNlZCB0byBzZXQgdGFiSW5kZXggaW4gYSBtYW5uZXIgc3VjaCBhcyBgdGFiSW5kZXg9e2lzQWN0aXZlID8gMCA6IC0xfWBcbi8vIHJlZiBzaG91bGQgYmUgcGFzc2VkIHRvIGEgRE9NIG5vZGUgd2hpY2ggd2lsbCBiZSB1c2VkIGZvciBET00gY29tcGFyZURvY3VtZW50UG9zaXRpb25cbmV4cG9ydCBjb25zdCB1c2VSb3ZpbmdUYWJJbmRleCA9IDxUIGV4dGVuZHMgSFRNTEVsZW1lbnQ+KFxuICAgIGlucHV0UmVmPzogUmVmT2JqZWN0PFQ+LFxuKTogW0ZvY3VzSGFuZGxlciwgYm9vbGVhbiwgUmVmT2JqZWN0PFQ+XSA9PiB7XG4gICAgY29uc3QgY29udGV4dCA9IHVzZUNvbnRleHQoUm92aW5nVGFiSW5kZXhDb250ZXh0KTtcbiAgICBsZXQgcmVmID0gdXNlUmVmPFQ+KG51bGwpO1xuXG4gICAgaWYgKGlucHV0UmVmKSB7XG4gICAgICAgIC8vIGlmIHdlIGFyZSBnaXZlbiBhIHJlZiwgdXNlIGl0IGluc3RlYWQgb2Ygb3Vyc1xuICAgICAgICByZWYgPSBpbnB1dFJlZjtcbiAgICB9XG5cbiAgICAvLyBzZXR1cCAoYWZ0ZXIgcmVmcylcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBjb250ZXh0LmRpc3BhdGNoKHtcbiAgICAgICAgICAgIHR5cGU6IFR5cGUuUmVnaXN0ZXIsXG4gICAgICAgICAgICBwYXlsb2FkOiB7IHJlZiB9LFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gdGVhcmRvd25cbiAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgIHR5cGU6IFR5cGUuVW5yZWdpc3RlcixcbiAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IHJlZiB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgfSwgW10pOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlYWN0LWhvb2tzL2V4aGF1c3RpdmUtZGVwc1xuXG4gICAgY29uc3Qgb25Gb2N1cyA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICAgICAgY29udGV4dC5kaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiBUeXBlLlNldEZvY3VzLFxuICAgICAgICAgICAgcGF5bG9hZDogeyByZWYgfSxcbiAgICAgICAgfSk7XG4gICAgfSwgW10pOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlYWN0LWhvb2tzL2V4aGF1c3RpdmUtZGVwc1xuXG4gICAgY29uc3QgaXNBY3RpdmUgPSBjb250ZXh0LnN0YXRlLmFjdGl2ZVJlZiA9PT0gcmVmO1xuICAgIHJldHVybiBbb25Gb2N1cywgaXNBY3RpdmUsIHJlZl07XG59O1xuXG4vLyByZS1leHBvcnQgdGhlIHNlbWFudGljIGhlbHBlciBjb21wb25lbnRzIGZvciBzaW1wbGljaXR5XG5leHBvcnQgeyBSb3ZpbmdUYWJJbmRleFdyYXBwZXIgfSBmcm9tIFwiLi9yb3ZpbmcvUm92aW5nVGFiSW5kZXhXcmFwcGVyXCI7XG5leHBvcnQgeyBSb3ZpbmdBY2Nlc3NpYmxlQnV0dG9uIH0gZnJvbSBcIi4vcm92aW5nL1JvdmluZ0FjY2Vzc2libGVCdXR0b25cIjtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRQSxJQUFBQSxNQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFjQSxJQUFBQyxtQkFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsa0JBQUEsR0FBQUYsT0FBQTtBQXVXQSxJQUFBRyxzQkFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksdUJBQUEsR0FBQUosT0FBQTtBQUF5RSxTQUFBSyx5QkFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxtQkFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFBRix3QkFBQSxZQUFBQSxDQUFBQyxDQUFBLFdBQUFBLENBQUEsR0FBQUcsQ0FBQSxHQUFBRCxDQUFBLEtBQUFGLENBQUE7QUFBQSxTQUFBUCx3QkFBQU8sQ0FBQSxFQUFBRSxDQUFBLFNBQUFBLENBQUEsSUFBQUYsQ0FBQSxJQUFBQSxDQUFBLENBQUFJLFVBQUEsU0FBQUosQ0FBQSxlQUFBQSxDQUFBLHVCQUFBQSxDQUFBLHlCQUFBQSxDQUFBLFdBQUFLLE9BQUEsRUFBQUwsQ0FBQSxRQUFBRyxDQUFBLEdBQUFKLHdCQUFBLENBQUFHLENBQUEsT0FBQUMsQ0FBQSxJQUFBQSxDQUFBLENBQUFHLEdBQUEsQ0FBQU4sQ0FBQSxVQUFBRyxDQUFBLENBQUFJLEdBQUEsQ0FBQVAsQ0FBQSxPQUFBUSxDQUFBLEtBQUFDLFNBQUEsVUFBQUMsQ0FBQSxHQUFBQyxNQUFBLENBQUFDLGNBQUEsSUFBQUQsTUFBQSxDQUFBRSx3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