react-native-scroll-to-child
Version:
Scroll a ScrollView's child into the visible viewport
389 lines (378 loc) • 62.8 kB
JavaScript
'use strict';
var React = require('react');
var reactNative = require('react-native');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var React__default = /*#__PURE__*/_interopDefault(React);
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/compute-scroll.tsx
var computeScrollY = /* @__PURE__ */ __name((scrollViewLayout, viewLayout, scrollY, insets, align) => {
const { height: scrollViewHeight, y: scrollViewY } = scrollViewLayout;
const { height: childHeight, y: viewY } = viewLayout;
const viewTopY = viewY - scrollViewY;
const viewBottomY = viewTopY + childHeight;
const computationData = { scrollViewHeight, scrollY, viewTopY, viewBottomY, insets };
const computeFn = alignmentsY[align];
if (!computeFn) throw new Error(`align=${align} not supported`);
return computeFn(computationData);
}, "computeScrollY");
var computeScrollYAuto = /* @__PURE__ */ __name((data) => {
const { scrollY } = data;
const scrollYTop = computeScrollYStart(data);
if (scrollY > scrollYTop) {
return scrollYTop;
}
const scrollYBottom = computeScrollYEnd(data);
if (scrollY < scrollYBottom) {
return scrollYBottom;
}
return scrollY;
}, "computeScrollYAuto");
var computeScrollYStart = /* @__PURE__ */ __name(({ scrollY, viewTopY, insets }) => {
return scrollY + viewTopY - (insets.top || 0);
}, "computeScrollYStart");
var computeScrollYEnd = /* @__PURE__ */ __name(({ scrollViewHeight, scrollY, viewBottomY, insets }) => {
return scrollY + viewBottomY - scrollViewHeight + (insets.bottom || 0);
}, "computeScrollYEnd");
var computeScrollYCenter = /* @__PURE__ */ __name((data) => {
return (computeScrollYStart(data) + computeScrollYEnd(data)) / 2;
}, "computeScrollYCenter");
var alignmentsY = {
auto: computeScrollYAuto,
start: computeScrollYStart,
end: computeScrollYEnd,
center: computeScrollYCenter
};
var computeScrollX = /* @__PURE__ */ __name((scrollViewLayout, viewLayout, scrollX, insets, align) => {
const { width: scrollViewWidth, x: scrollViewX } = scrollViewLayout;
const { width: childWidth, x: viewX } = viewLayout;
const viewLeftX = viewX - scrollViewX;
const viewRightX = viewLeftX + childWidth;
const computationData = { scrollViewWidth, scrollX, viewLeftX, viewRightX, insets };
const computeFn = alignmentsX[align];
if (!computeFn) throw new Error(`align=${align} not supported for horizontal scrolling`);
return computeFn(computationData);
}, "computeScrollX");
var computeScrollXAuto = /* @__PURE__ */ __name((data) => {
const { scrollX } = data;
const scrollXLeft = computeScrollXStart(data);
if (scrollX > scrollXLeft) {
return scrollXLeft;
}
const scrollXRight = computeScrollXEnd(data);
if (scrollX < scrollXRight) {
return scrollXRight;
}
return scrollX;
}, "computeScrollXAuto");
var computeScrollXStart = /* @__PURE__ */ __name(({ scrollX, viewLeftX, insets }) => {
return scrollX + viewLeftX - (insets.left || 0);
}, "computeScrollXStart");
var computeScrollXEnd = /* @__PURE__ */ __name(({ scrollViewWidth, scrollX, viewRightX, insets }) => {
return scrollX + viewRightX - scrollViewWidth + (insets.right || 0);
}, "computeScrollXEnd");
var computeScrollXCenter = /* @__PURE__ */ __name((data) => {
return (computeScrollXStart(data) + computeScrollXEnd(data)) / 2;
}, "computeScrollXCenter");
var alignmentsX = {
auto: computeScrollXAuto,
start: computeScrollXStart,
end: computeScrollXEnd,
center: computeScrollXCenter
};
var measureElement = /* @__PURE__ */ __name((element) => {
const node = reactNative.findNodeHandle(element);
if (!node) return Promise.reject(new Error("Unable to find node handle"));
return new Promise((resolve) => {
reactNative.UIManager.measureInWindow(node, (x, y, width, height) => resolve({ x, y, width, height }));
});
}, "measureElement");
var throttle = /* @__PURE__ */ __name((func, limit) => {
let inThrottle = false;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}, "throttle");
// src/config.tsx
var DefaultOptions = {
align: "auto",
animated: true,
immediate: false,
insets: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
computeScrollY,
computeScrollX,
measureElement
};
var normalizeOptions = /* @__PURE__ */ __name((options = {}, fallbackOptions = DefaultOptions) => ({
...fallbackOptions,
...options,
insets: {
...fallbackOptions.insets,
...options.insets
}
}), "normalizeOptions");
var DefaultHOCConfig = {
// The method to extract the raw ScrollView node from the ref we got, if it's not directly the ScrollView itself
getScrollViewNode: /* @__PURE__ */ __name((scrollView) => {
const rnVersion = reactNative.Platform.constants.reactNativeVersion;
const isPreRN062 = rnVersion ? rnVersion.major === 0 && rnVersion.minor < 62 : false;
if (typeof scrollView.getNode === "function" && isPreRN062) {
return scrollView.getNode();
}
return scrollView;
}, "getScrollViewNode"),
// Default value for throttling, can be overridden by user with props
scrollEventThrottle: 16,
// ScrollIntoView options, can be offered by <ScrollIntoView /> comp or imperative usage
options: DefaultOptions
};
var normalizeHOCConfig = /* @__PURE__ */ __name((config = {}) => ({
...DefaultHOCConfig,
...config,
options: normalizeOptions(config.options, DefaultOptions)
}), "normalizeHOCConfig");
// src/api.tsx
var scrollIntoView = /* @__PURE__ */ __name(async (scrollView, view, scrollY, scrollX, options) => {
if (!scrollView || !view) {
throw new Error("ScrollView and target View must be provided");
}
const { align, animated, computeScrollY: computeScrollY2, computeScrollX: computeScrollX2, measureElement: measureElement2, insets } = normalizeOptions(options);
try {
const [scrollViewLayout, viewLayout] = await Promise.all([measureElement2(scrollView), measureElement2(view)]);
const targetScrollY = computeScrollY2(scrollViewLayout, viewLayout, scrollY, insets, align);
const targetScrollX = computeScrollX2(scrollViewLayout, viewLayout, scrollX, insets, align);
const scrollParams = { x: targetScrollX, y: targetScrollY, animated };
const scrollResponder = scrollView.getScrollResponder();
if (scrollResponder.scrollResponderScrollTo) {
scrollResponder.scrollResponderScrollTo(scrollParams);
} else {
scrollView.scrollTo(scrollParams);
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error";
throw new Error(`Failed to scroll into view: ${errorMessage}`);
}
}, "scrollIntoView");
var _ScrollIntoViewAPI = class _ScrollIntoViewAPI {
constructor(dependencies) {
this.dependencies = dependencies;
this.validateDependencies(dependencies);
}
validateDependencies(deps) {
const requiredDepKeys = [
"getScrollView",
"getScrollY",
"getScrollX",
"getDefaultOptions"
];
for (const key of requiredDepKeys) {
if (typeof deps[key] !== "function") {
throw new Error(`Dependency "${key}" must be a function.`);
}
}
}
getNormalizedOptions = /* @__PURE__ */ __name((options = {}) => normalizeOptions(options, this.dependencies.getDefaultOptions()), "getNormalizedOptions");
scrollIntoView = /* @__PURE__ */ __name((view, options) => {
const normalizedOptions = this.getNormalizedOptions(options);
return normalizedOptions.immediate ? this.scrollIntoViewImmediate(view, normalizedOptions) : this.scrollIntoViewThrottled(view, normalizedOptions);
}, "scrollIntoView");
performScroll = /* @__PURE__ */ __name((view, options) => {
return scrollIntoView(
this.dependencies.getScrollView(),
view,
this.dependencies.getScrollY(),
this.dependencies.getScrollX(),
options
);
}, "performScroll");
scrollIntoViewThrottled = throttle(this.performScroll, 16);
scrollIntoViewImmediate = this.performScroll;
};
__name(_ScrollIntoViewAPI, "ScrollIntoViewAPI");
var ScrollIntoViewAPI = _ScrollIntoViewAPI;
// src/context.tsx
var Context = React__default.default.createContext(null);
var context_default = Context;
var APIConsumer = Context.Consumer;
var ProvideAPI = /* @__PURE__ */ __name(({ dependencies, children }) => {
const api = React__default.default.useMemo(() => new ScrollIntoViewAPI(dependencies), [dependencies]);
return /* @__PURE__ */ React__default.default.createElement(Context.Provider, { value: api }, children);
}, "ProvideAPI");
// src/container.tsx
var showNotInContextWarning = throttle(() => {
console.warn(
"ScrollIntoView API is not provided in React context. Make sure you wrapped your ScrollView component with wrapScrollView(ScrollView)"
);
}, 5e3);
var ContainerBase = React.forwardRef((props, ref) => {
const {
enabled = true,
onMount = true,
onUpdate = true,
scrollIntoViewKey,
scrollIntoViewOptions,
scrollIntoViewAPI,
children,
align,
animated,
immediate,
insets,
measureElement: measureElement2,
computeScrollY: computeScrollY2,
computeScrollX: computeScrollX2,
...rest
} = props;
const containerRef = React.useRef(null);
const unmounted = React.useRef(false);
const prevProps = React.useRef({ enabled, scrollIntoViewKey });
const ensureApiProvided = React.useCallback(() => {
if (!scrollIntoViewAPI) {
showNotInContextWarning();
return false;
}
return true;
}, [scrollIntoViewAPI]);
const getPropsOptions = React.useCallback(() => {
const COMPONENT_DEFAULT_ANIMATED = true;
const COMPONENT_DEFAULT_IMMEDIATE = false;
const mergedOptions = {
animated: COMPONENT_DEFAULT_ANIMATED,
immediate: COMPONENT_DEFAULT_IMMEDIATE,
...scrollIntoViewOptions
};
const optionProps = [
"animated",
"immediate",
"align",
"insets",
"measureElement",
"computeScrollY",
"computeScrollX"
];
const propsToMerge = {
animated,
immediate,
align,
insets,
measureElement: measureElement2,
computeScrollY: computeScrollY2,
computeScrollX: computeScrollX2
};
for (const key of optionProps) {
if (propsToMerge[key] !== void 0) {
mergedOptions[key] = propsToMerge[key];
}
}
return mergedOptions;
}, [scrollIntoViewOptions, animated, immediate, align, insets, measureElement2, computeScrollY2, computeScrollX2]);
const scrollIntoView2 = React.useCallback(
(providedOptions = {}) => {
if (unmounted.current || !ensureApiProvided()) return;
const currentContainerRef = containerRef.current;
if (!currentContainerRef) return;
const options = { ...getPropsOptions(), ...providedOptions };
if (scrollIntoViewAPI) {
scrollIntoViewAPI.scrollIntoView(currentContainerRef, options);
}
},
[ensureApiProvided, getPropsOptions, scrollIntoViewAPI]
);
React.useEffect(() => {
let timerId;
if (onMount && enabled) {
timerId = setTimeout(() => {
if (!unmounted.current) {
scrollIntoView2();
}
}, 0);
}
return () => {
if (timerId) {
clearTimeout(timerId);
}
};
}, [enabled, onMount, scrollIntoView2]);
React.useEffect(() => {
const prevEnabled = prevProps.current.enabled;
const prevKey = prevProps.current.scrollIntoViewKey;
const needsUpdateScroll = onUpdate && enabled && (!prevEnabled || scrollIntoViewKey !== prevKey);
if (needsUpdateScroll) {
scrollIntoView2();
}
if (prevEnabled !== enabled || prevKey !== scrollIntoViewKey) {
prevProps.current = { enabled, scrollIntoViewKey };
}
}, [enabled, onUpdate, scrollIntoViewKey, scrollIntoView2]);
React.useEffect(() => {
return () => {
unmounted.current = true;
};
}, []);
return /* @__PURE__ */ React__default.default.createElement(reactNative.View, { ...rest, ref: ref || containerRef, collapsable: false }, children);
});
ContainerBase.displayName = "ContainerBase";
var Container = React.forwardRef((props, ref) => /* @__PURE__ */ React__default.default.createElement(APIConsumer, null, (apiFromContext) => apiFromContext && /* @__PURE__ */ React__default.default.createElement(ContainerBase, { ref, ...props, scrollIntoViewAPI: apiFromContext })));
var wrapScrollViewHOC = /* @__PURE__ */ __name((ScrollViewComp, config = {}) => {
const { getScrollViewNode, scrollEventThrottle, options } = normalizeHOCConfig(config);
const ScrollViewWrapper = React.forwardRef((props, ref) => {
var _a, _b;
const internalRef = React.useRef(null);
const scrollY = React.useRef(((_a = props.contentOffset) == null ? void 0 : _a.y) || 0);
const scrollX = React.useRef(((_b = props.contentOffset) == null ? void 0 : _b.x) || 0);
const handleScroll = React.useCallback((event) => {
scrollY.current = event.nativeEvent.contentOffset.y;
scrollX.current = event.nativeEvent.contentOffset.x;
}, []);
const dependencies = {
getScrollView: /* @__PURE__ */ __name(() => {
if (!internalRef.current) throw new Error("ScrollView ref is not set");
return getScrollViewNode(internalRef.current);
}, "getScrollView"),
getScrollY: /* @__PURE__ */ __name(() => scrollY.current, "getScrollY"),
getScrollX: /* @__PURE__ */ __name(() => scrollX.current, "getScrollX"),
getDefaultOptions: /* @__PURE__ */ __name(() => normalizeOptions(props.scrollIntoViewOptions, options), "getDefaultOptions")
};
React.useImperativeHandle(ref, () => internalRef.current, []);
const scrollViewProps = {
...props,
ref: internalRef,
scrollEventThrottle: props.scrollEventThrottle || scrollEventThrottle,
onScroll: reactNative.Animated.forkEvent(props.onScroll, handleScroll)
};
return /* @__PURE__ */ React__default.default.createElement(ScrollViewComp, { ...scrollViewProps }, /* @__PURE__ */ React__default.default.createElement(ProvideAPI, { dependencies }, props.children));
});
ScrollViewWrapper.displayName = `ScrollIntoViewWrapper(${ScrollViewComp.displayName || ScrollViewComp.name || "Component"})`;
return ScrollViewWrapper;
}, "wrapScrollViewHOC");
function useScrollIntoViewContext() {
const value = React.useContext(context_default);
if (value === null) {
throw new Error(
"ScrollIntoView context is missing. Ensure your ScrollView is wrapped with wrapScrollView() and is an ancestor in the component tree."
);
}
return value;
}
__name(useScrollIntoViewContext, "useScrollIntoViewContext");
function useScrollIntoView() {
const { scrollIntoView: scrollIntoView2 } = useScrollIntoViewContext();
return scrollIntoView2;
}
__name(useScrollIntoView, "useScrollIntoView");
// src/index.ts
var ScrollIntoView = Container;
var wrapScrollView = /* @__PURE__ */ __name((comp, config) => wrapScrollViewHOC(comp, config), "wrapScrollView");
exports.ScrollIntoView = ScrollIntoView;
exports.useScrollIntoView = useScrollIntoView;
exports.wrapScrollView = wrapScrollView;
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21wdXRlLXNjcm9sbC50c3giLCIuLi9zcmMvdXRpbHMudHN4IiwiLi4vc3JjL2NvbmZpZy50c3giLCIuLi9zcmMvYXBpLnRzeCIsIi4uL3NyYy9jb250ZXh0LnRzeCIsIi4uL3NyYy9jb250YWluZXIudHN4IiwiLi4vc3JjL2hvYy50c3giLCIuLi9zcmMvaG9va3MudHN4IiwiLi4vc3JjL2luZGV4LnRzIl0sIm5hbWVzIjpbImZpbmROb2RlSGFuZGxlIiwiVUlNYW5hZ2VyIiwiUGxhdGZvcm0iLCJjb21wdXRlU2Nyb2xsWSIsImNvbXB1dGVTY3JvbGxYIiwibWVhc3VyZUVsZW1lbnQiLCJSZWFjdCIsImZvcndhcmRSZWYiLCJ1c2VSZWYiLCJ1c2VDYWxsYmFjayIsInNjcm9sbEludG9WaWV3IiwidXNlRWZmZWN0IiwiVmlldyIsInVzZUltcGVyYXRpdmVIYW5kbGUiLCJBbmltYXRlZCIsInVzZUNvbnRleHQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFXTyxJQUFNLGlDQUFpQixNQUFBLENBQUEsQ0FDMUIsZ0JBQUEsRUFDQSxVQUFBLEVBQ0EsT0FBQSxFQUNBLFFBQ0EsS0FBQSxLQUNDO0FBQ0QsRUFBQSxNQUFNLEVBQUUsTUFBQSxFQUFRLGdCQUFBLEVBQWtCLENBQUEsRUFBRyxhQUFZLEdBQUksZ0JBQUE7QUFDckQsRUFBQSxNQUFNLEVBQUUsTUFBQSxFQUFRLFdBQUEsRUFBYSxDQUFBLEVBQUcsT0FBTSxHQUFJLFVBQUE7QUFFMUMsRUFBQSxNQUFNLFdBQVcsS0FBQSxHQUFRLFdBQUE7QUFDekIsRUFBQSxNQUFNLGNBQWMsUUFBQSxHQUFXLFdBQUE7QUFFL0IsRUFBQSxNQUFNLGtCQUFrQixFQUFFLGdCQUFBLEVBQWtCLE9BQUEsRUFBUyxRQUFBLEVBQVUsYUFBYSxNQUFBLEVBQU87QUFFbkYsRUFBQSxNQUFNLFNBQUEsR0FBWSxZQUFZLEtBQUssQ0FBQTtBQUNuQyxFQUFBLElBQUksQ0FBRSxTQUFBLEVBQW1CLE1BQU0sSUFB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MEJBQUEsQ0FBQTtBQVVGLFNBQVMsaUJBQUEsR0FBeUQ7QUFDckUsRUFBQSxNQUFNLEVBQUUsY0FBQSxFQUFBTCxlQUFBQSxFQUFlLEdBQUksd0JBQUEsRUFBeUI7QUFDcEQsRUFBQSxPQUFPQSxlQUFBQTtBQUNYO0FBSGdCLE1BQUEsQ0FBQSxpQkFBQSxFQUFBLG1CQUFBLENBQUE7OztBQ1JULElBQU0sY0FBQSxHQUFpQjtBQUV2QixJQUFNLGlDQUFpQixNQUFBLENBQUEsQ0FBQyxJQUFBLEVBQTJCLFdBQThCLGlCQUFBLENBQWtCLElBQUEsRUFBTSxNQUFNLENBQUEsRUFBeEYsZ0JBQUEiLCJmaWxlIjoiaW5kZXguY2pzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBBbGlnbiwgSW5zZXRzIH0gZnJvbSAnLi9jb25maWcnO1xuaW1wb3J0IHR5cGUgeyBMYXlvdXRSZWN0YW5nbGUgfSBmcm9tICdyZWFjdC1uYXRpdmUnO1xuXG50eXBlIENvbXB1dGF0aW9uRGF0YSA9IHtcbiAgICBzY3JvbGxWaWV3SGVpZ2h0OiBudW1iZXI7XG4gICAgc2Nyb2xsWTogbnVtYmVyO1xuICAgIHZpZXdUb3BZOiBudW1iZXI7XG4gICAgdmlld0JvdHRvbVk6IG51bWJlcjtcbiAgICBpbnNldHM6IEluc2V0cztcbn07XG5cbmV4cG9ydCBjb25zdCBjb21wdXRlU2Nyb2xsWSA9IChcbiAgICBzY3JvbGxWaWV3TGF5b3V0OiBMYXlvdXRSZWN0YW5nbGUsXG4gICAgdmlld0xheW91dDogTGF5b3V0UmVjdGFuZ2xlLFxuICAgIHNjcm9sbFk6IG51bWJlcixcbiAgICBpbnNldHM6IEluc2V0cyxcbiAgICBhbGlnbjogQWxpZ25cbikgPT4ge1xuICAgIGNvbnN0IHsgaGVpZ2h0OiBzY3JvbGxWaWV3SGVpZ2h0LCB5OiBzY3JvbGxWaWV3WSB9ID0gc2Nyb2xsVmlld0xheW91dDtcbiAgICBjb25zdCB7IGhlaWdodDogY2hpbGRIZWlnaHQsIHk6IHZpZXdZIH0gPSB2aWV3TGF5b3V0O1xuXG4gICAgY29uc3Qgdmlld1RvcFkgPSB2aWV3WSAtIHNjcm9sbFZpZXdZO1xuICAgIGNvbnN0IHZpZXdCb3R0b21ZID0gdmlld1RvcFkgKyBjaGlsZEhlaWdodDtcblxuICAgIGNvbnN0IGNvbXB1dGF0aW9uRGF0YSA9IHsgc2Nyb2xsVmlld0hlaWdodCwgc2Nyb2xsWSwgdmlld1RvcFksIHZpZXdCb3R0b21ZLCBpbnNldHMgfTtcblxuICAgIGNvbnN0IGNvbXB1dGVGbiA9IGFsaWdubWVudHNZW2FsaWduXTtcbiAgICBpZiAoIShjb21wdXRlRm4gYXMgYW55KSkgdGhyb3cgbmV3IEVycm9yKGBhbGlnbj0ke2FsaWdufSBub3Qgc3VwcG9ydGVkYCk7XG5cbiAgICByZXR1cm4gY29tcHV0ZUZuKGNvbXB1dGF0aW9uRGF0YSk7XG59O1xuXG5leHBvcnQgY29uc3QgY29tcHV0ZVNjcm9sbFlBdXRvID0gKGRhdGE6IENvbXB1dGF0aW9uRGF0YSk6IG51bWJlciA9PiB7XG4gICAgY29uc3QgeyBzY3JvbGxZIH0gPSBkYXRhO1xuICAgIGNvbnN0IHNjcm9sbFlUb3AgPSBjb21wdXRlU2Nyb2xsWVN0YXJ0KGRhdGEpO1xuICAgIGlmIChzY3JvbGxZID4gc2Nyb2xsWVRvcCkge1xuICAgICAgICByZXR1cm4gc2Nyb2xsWVRvcDtcbiAgICB9XG4gICAgY29uc3Qgc2Nyb2xsWUJvdHRvbSA9IGNvbXB1dGVTY3JvbGxZRW5kKGRhdGEpO1xuICAgIGlmIChzY3JvbGxZIDwgc2Nyb2xsWUJvdHRvbSkge1xuICAgICAgICByZXR1cm4gc2Nyb2xsWUJvdHRvbTtcbiAgICB9XG4gICAgcmV0dXJuIHNjcm9sbFk7XG59O1xuXG5leHBvcnQgY29uc3QgY29tcHV0ZVNjcm9sbFlTdGFydCA9ICh7IHNjcm9sbFksIHZpZXdUb3BZLCBpbnNldHMgfTogQ29tcHV0YXRpb25EYXRhKTogbnVtYmVyID0+IHtcbiAgICByZXR1cm4gc2Nyb2xsWSArIHZpZXdUb3BZIC0gKGluc2V0cy50b3AgfHwgMCk7XG59O1xuXG5leHBvcnQgY29uc3QgY29tcHV0ZVNjcm9sbFlFbmQgPSAoeyBzY3JvbGxWaWV3SGVpZ2h0LCBzY3JvbGxZLCB2aWV3Qm90dG9tWSwgaW5zZXRzIH06IENvbXB1dGF0aW9uRGF0YSk6IG51bWJlciA9PiB7XG4gICAgcmV0dXJuIHNjcm9sbFkgKyB2aWV3Qm90dG9tWSAtIHNjcm9sbFZpZXdIZWlnaHQgKyAoaW5zZXRzLmJvdHRvbSB8fCAwKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb21wdXRlU2Nyb2xsWUNlbnRlciA9IChkYXRhOiBDb21wdXRhdGlvbkRhdGEpOiBudW1iZXIgPT4ge1xuICAgIHJldHVybiAoY29tcHV0ZVNjcm9sbFlTdGFydChkYXRhKSArIGNvbXB1dGVTY3JvbGxZRW5kKGRhdGEpKSAvIDI7XG59O1xuXG5jb25zdCBhbGlnbm1lbnRzWTogUmVjb3JkPEFsaWduLCAoZGF0YTogQ29tcHV0YXRpb25EYXRhKSA9PiBudW1iZXI+ID0ge1xuICAgIGF1dG86IGNvbXB1dGVTY3JvbGxZQXV0byxcbiAgICBzdGFydDogY29tcHV0ZVNjcm9sbFlTdGFydCxcbiAgICBlbmQ6IGNvbXB1dGVTY3JvbGxZRW5kLFxuICAgIGNlbnRlcjogY29tcHV0ZVNjcm9sbFlDZW50ZXJcbn07XG5cbnR5cGUgQ29tcHV0YXRpb25EYXRhWCA9IHtcbiAgICBzY3JvbGxWaWV3V2lkdGg6IG51bWJlcjtcbiAgICBzY3JvbGxYOiBudW1iZXI7XG4gICAgdmlld0xlZnRYOiBudW1iZXI7XG4gICAgdmlld1JpZ2h0WDogbnVtYmVyO1xuICAgIGluc2V0czogSW5zZXRzO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbXB1dGVTY3JvbGxYID0gKFxuICAgIHNjcm9sbFZpZXdMYXlvdXQ6IExheW91dFJlY3RhbmdsZSxcbiAgICB2aWV3TGF5b3V0OiBMYXlvdXRSZWN0YW5nbGUsXG4gICAgc2Nyb2xsWDogbnVtYmVyLFxuICAgIGluc2V0czogSW5zZXRzLFxuICAgIGFsaWduOiBBbGlnblxuKTogbnVtYmVyID0+IHtcbiAgICBjb25zdCB7IHdpZHRoOiBzY3JvbGxWaWV3V2lkdGgsIHg6IHNjcm9sbFZpZXdYIH0gPSBzY3JvbGxWaWV3TGF5b3V0O1xuICAgIGNvbnN0IHsgd2lkdGg6IGNoaWxkV2lkdGgsIHg6IHZpZXdYIH0gPSB2aWV3TGF5b3V0O1xuXG4gICAgY29uc3Qgdmlld0xlZnRYID0gdmlld1ggLSBzY3JvbGxWaWV3WDtcbiAgICBjb25zdCB2aWV3UmlnaHRYID0gdmlld0xlZnRYICsgY2hpbGRXaWR0aDtcblxuICAgIGNvbnN0IGNvbXB1dGF0aW9uRGF0YTogQ29tcHV0YXRpb25EYXRhWCA9IHsgc2Nyb2xsVmlld1dpZHRoLCBzY3JvbGxYLCB2aWV3TGVmdFgsIHZpZXdSaWdodFgsIGluc2V0cyB9O1xuXG4gICAgY29uc3QgY29tcHV0ZUZuID0gYWxpZ25tZW50c1hbYWxpZ25dO1xuICAgIGlmICghKGNvbXB1dGVGbiBhcyBhbnkpKSB0aHJvdyBuZXcgRXJyb3IoYGFsaWduPSR7YWxpZ259IG5vdCBzdXBwb3J0ZWQgZm9yIGhvcml6b250YWwgc2Nyb2xsaW5nYCk7XG5cbiAgICByZXR1cm4gY29tcHV0ZUZuKGNvbXB1dGF0aW9uRGF0YSk7XG59O1xuXG5leHBvcnQgY29uc3QgY29tcHV0ZVNjcm9sbFhBdXRvID0gKGRhdGE6IENvbXB1dGF0aW9uRGF0YVgpOiBudW1iZXIgPT4ge1xuICAgIGNvbnN0IHsgc2Nyb2xsWCB9ID0gZGF0YTtcbiAgICBjb25zdCBzY3JvbGxYTGVmdCA9IGNvbXB1dGVTY3JvbGxYU3RhcnQoZGF0YSk7XG4gICAgaWYgKHNjcm9sbFggPiBzY3JvbGxYTGVmdCkge1xuICAgICAgICByZXR1cm4gc2Nyb2xsWExlZnQ7XG4gICAgfVxuICAgIGNvbnN0IHNjcm9sbFhSaWdodCA9IGNvbXB1dGVTY3JvbGxYRW5kKGRhdGEpO1xuICAgIGlmIChzY3JvbGxYIDwgc2Nyb2xsWFJpZ2h0KSB7XG4gICAgICAgIHJldHVybiBzY3JvbGxYUmlnaHQ7XG4gICAgfVxuICAgIHJldHVybiBzY3JvbGxYO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvbXB1dGVTY3JvbGxYU3RhcnQgPSAoeyBzY3JvbGxYLCB2aWV3TGVmdFgsIGluc2V0cyB9OiBDb21wdXRhdGlvbkRhdGFYKTogbnVtYmVyID0+IHtcbiAgICByZXR1cm4gc2Nyb2xsWCArIHZpZXdMZWZ0WCAtIChpbnNldHMubGVmdCB8fCAwKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb21wdXRlU2Nyb2xsWEVuZCA9ICh7IHNjcm9sbFZpZXdXaWR0aCwgc2Nyb2xsWCwgdmlld1JpZ2h0WCwgaW5zZXRzIH06IENvbXB1dGF0aW9uRGF0YVgpOiBudW1iZXIgPT4ge1xuICAgIHJldHVybiBzY3JvbGxYICsgdmlld1JpZ2h0WCAtIHNjcm9sbFZpZXdXaWR0aCArIChpbnNldHMucmlnaHQgfHwgMCk7XG59O1xuXG5leHBvcnQgY29uc3QgY29tcHV0ZVNjcm9sbFhDZW50ZXIgPSAoZGF0YTogQ29tcHV0YXRpb25EYXRhWCk6IG51bWJlciA9PiB7XG4gICAgcmV0dXJuIChjb21wdXRlU2Nyb2xsWFN0YXJ0KGRhdGEpICsgY29tcHV0ZVNjcm9sbFhFbmQoZGF0YSkpIC8gMjtcbn07XG5cbmNvbnN0IGFsaWdubWVudHNYOiBSZWNvcmQ8QWxpZ24sIChkYXRhOiBDb21wdXRhdGlvbkRhdGFYKSA9PiBudW1iZXI+ID0ge1xuICAgIGF1dG86IGNvbXB1dGVTY3JvbGxYQXV0byxcbiAgICBzdGFydDogY29tcHV0ZVNjcm9sbFhTdGFydCxcbiAgICBlbmQ6IGNvbXB1dGVTY3JvbGxYRW5kLFxuICAgIGNlbnRlcjogY29tcHV0ZVNjcm9sbFhDZW50ZXJcbn07XG4iLCJpbXBvcnQgeyBmaW5kTm9kZUhhbmRsZSwgVUlNYW5hZ2VyIH0gZnJvbSAncmVhY3QtbmF0aXZlJztcblxuaW1wb3J0IHR5cGUgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHR5cGUgeyBMYXlvdXRSZWN0YW5nbGUgfSBmcm9tICdyZWFjdC1uYXRpdmUnO1xuXG50eXBlIEZpbmROb2RlSGFuZGxlQXJnID0gbnVsbCB8IG51bWJlciB8IFJlYWN0LkNvbXBvbmVudDxhbnksIGFueT4gfCBSZWFjdC5Db21wb25lbnRDbGFzczxhbnk+O1xuXG5leHBvcnQgY29uc3QgbWVhc3VyZUVsZW1lbnQgPSAoZWxlbWVudDogRmluZE5vZGVIYW5kbGVBcmcpOiBQcm9taXNlPExheW91dFJlY3RhbmdsZT4gPT4ge1xuICAgIGNvbnN0IG5vZGUgPSBmaW5kTm9kZUhhbmRsZShlbGVtZW50KTtcbiAgICBpZiAoIW5vZGUpIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1VuYWJsZSB0byBmaW5kIG5vZGUgaGFuZGxlJykpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPExheW91dFJlY3RhbmdsZT4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgVUlNYW5hZ2VyLm1lYXN1cmVJbldpbmRvdyhub2RlLCAoeCwgeSwgd2lkdGgsIGhlaWdodCkgPT4gcmVzb2x2ZSh7IHgsIHksIHdpZHRoLCBoZWlnaHQgfSkpO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHRocm90dGxlID0gPFQgZXh0ZW5kcyAoLi4uYXJnczogYW55W10pID0+IHZvaWQ+KGZ1bmM6IFQsIGxpbWl0OiBudW1iZXIpOiBUID0+IHtcbiAgICBsZXQgaW5UaHJvdHRsZSA9IGZhbHNlO1xuICAgIHJldHVybiBmdW5jdGlvbiAodGhpczogdW5rbm93biwgLi4uYXJnczogUGFyYW1ldGVyczxUPikge1xuICAgICAgICBpZiAoIWluVGhyb3R0bGUpIHtcbiAgICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICBpblRocm90dGxlID0gdHJ1ZTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gKGluVGhyb3R0bGUgPSBmYWxzZSksIGxpbWl0KTtcbiAgICAgICAgfVxuICAgIH0gYXMgVDtcbn07XG4iLCJpbXBvcnQgeyBQbGF0Zm9ybSB9IGZyb20gJ3JlYWN0LW5hdGl2ZSc7XG5cbmltcG9ydCB7IGNvbXB1dGVTY3JvbGxYLCBjb21wdXRlU2Nyb2xsWSB9IGZyb20gJy4vY29tcHV0ZS1zY3JvbGwnO1xuaW1wb3J0IHsgbWVhc3VyZUVsZW1lbnQgfSBmcm9tICcuL3V0aWxzJztcblxuaW1wb3J0IHR5cGUgeyBTY3JvbGxWaWV3IH0gZnJvbSAncmVhY3QtbmF0aXZlJztcblxuZXhwb3J0IHR5cGUgSW5zZXRzID0ge1xuICAgIHRvcD86IG51bWJlcjtcbiAgICBib3R0b20/OiBudW1iZXI7XG4gICAgbGVmdD86IG51bWJlcjtcbiAgICByaWdodD86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIEFsaWduID0gJ2F1dG8nIHwgJ3N0YXJ0JyB8ICdlbmQnIHwgJ2NlbnRlcic7XG5cbmV4cG9ydCB0eXBlIEZ1bGxPcHRpb25zID0ge1xuICAgIGFsaWduOiBBbGlnbjtcbiAgICBhbmltYXRlZDogYm9vbGVhbjtcbiAgICBpbW1lZGlhdGU6IGJvb2xlYW47XG4gICAgaW5zZXRzOiBJbnNldHM7XG4gICAgY29tcHV0ZVNjcm9sbFk6IHR5cGVvZiBjb21wdXRlU2Nyb2xsWTtcbiAgICBjb21wdXRlU2Nyb2xsWDogdHlwZW9mIGNvbXB1dGVTY3JvbGxYO1xuICAgIG1lYXN1cmVFbGVtZW50OiB0eXBlb2YgbWVhc3VyZUVsZW1lbnQ7XG59O1xuXG5leHBvcnQgdHlwZSBQYXJ0aWFsT3B0aW9ucyA9IFBhcnRpYWw8RnVsbE9wdGlvbnM+O1xuXG5leHBvcnQgY29uc3QgRGVmYXVsdE9wdGlvbnM6IEZ1bGxPcHRpb25zID0ge1xuICAgIGFsaWduOiAnYXV0bycsXG4gICAgYW5pbWF0ZWQ6IHRydWUsXG4gICAgaW1tZWRpYXRlOiBmYWxzZSxcbiAgICBpbnNldHM6IHtcbiAgICAgICAgdG9wOiAwLFxuICAgICAgICBib3R0b206IDAsXG4gICAgICAgIGxlZnQ6IDAsXG4gICAgICAgIHJpZ2h0OiAwXG4gICAgfSxcbiAgICBjb21wdXRlU2Nyb2xsWSxcbiAgICBjb21wdXRlU2Nyb2xsWCxcbiAgICBtZWFzdXJlRWxlbWVudFxufTtcblxuZXhwb3J0IHR5cGUgT3B0aW9uS2V5ID0ga2V5b2YgRnVsbE9wdGlvbnM7XG5leHBvcnQgY29uc3QgT3B0aW9uS2V5czogT3B0aW9uS2V5W10gPSBPYmplY3Qua2V5cyhEZWZhdWx0T3B0aW9ucykgYXMgT3B0aW9uS2V5W107XG5cbmV4cG9ydCBjb25zdCBub3JtYWxpemVPcHRpb25zID0gKG9wdGlvbnM6IFBhcnRpYWxPcHRpb25zID0ge30sIGZhbGxiYWNrT3B0aW9uczogRnVsbE9wdGlvbnMgPSBEZWZhdWx0T3B0aW9ucykgPT4gKHtcbiAgICAuLi5mYWxsYmFja09wdGlvbnMsXG4gICAgLi4ub3B0aW9ucyxcbiAgICBpbnNldHM6IHtcbiAgICAgICAgLi4uZmFsbGJhY2tPcHRpb25zLmluc2V0cyxcbiAgICAgICAgLi4ub3B0aW9ucy5pbnNldHNcbiAgICB9XG59KTtcblxuZXhwb3J0IHR5cGUgRnVsbEhPQ0NvbmZpZyA9IHtcbiAgICBnZXRTY3JvbGxWaWV3Tm9kZTogKHNjcm9sbFZpZXc6IFNjcm9sbFZpZXcpID0+IFNjcm9sbFZpZXc7XG4gICAgc2Nyb2xsRXZlbnRUaHJvdHRsZTogMTY7XG4gICAgb3B0aW9uczogUGFydGlhbE9wdGlvbnM7XG59O1xuZXhwb3J0IHR5cGUgUGFydGlhbEhPQ0NvbmZpZyA9IFBhcnRpYWw8RnVsbEhPQ0NvbmZpZz47XG5cbmV4cG9ydCBjb25zdCBEZWZhdWx0SE9DQ29uZmlnOiBGdWxsSE9DQ29uZmlnID0ge1xuICAgIC8vIFRoZSBtZXRob2QgdG8gZXh0cmFjdCB0aGUgcmF3IFNjcm9sbFZpZXcgbm9kZSBmcm9tIHRoZSByZWYgd2UgZ290LCBpZiBpdCdzIG5vdCBkaXJlY3RseSB0aGUgU2Nyb2xsVmlldyBpdHNlbGZcbiAgICBnZXRTY3JvbGxWaWV3Tm9kZTogKHNjcm9sbFZpZXc6IFNjcm9sbFZpZXcpID0+IHtcbiAgICAgICAgLy8gc2Nyb2xsVmlldy5nZXROb2RlKCkgd2FzIHVzZWQgZm9yIEFuaW1hdGVkLlNjcm9sbFZpZXcgY29tcG9uZW50cyBidXQgaXMgZGVwcmVjYXRlZCBzaW5jZSBSTiAwLjYyLlxuICAgICAgICAvLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlYm9vay9yZWFjdC1uYXRpdmUvY29tbWl0LzY2ZTcyYmI0ZTAwYWFmYmNiOWY0NTBlZDVkYjI2MWQ5OGY5OWY4MmFcbiAgICAgICAgLy8gV2Ugb25seSBhdHRlbXB0IHRvIGNhbGwgaXQgaWYgaXQgZXhpc3RzIGFuZCB3ZSdyZSBvbiBhbiBvbGRlciBSTiB2ZXJzaW9uLlxuICAgICAgICBjb25zdCByblZlcnNpb24gPSBQbGF0Zm9ybS5jb25zdGFudHMucmVhY3ROYXRpdmVWZXJzaW9uO1xuICAgICAgICBjb25zdCBpc1ByZVJOMDYyID0gKHJuVmVyc2lvbiBhcyBhbnkpID8gcm5WZXJzaW9uLm1ham9yID09PSAwICYmIHJuVmVyc2lvbi5taW5vciA8IDYyIDogZmFsc2U7XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgZ2V0Tm9kZSBleGlzdHMgb24gdGhlIHNjcm9sbFZpZXcgb2JqZWN0IChjb21tb24gZm9yIEFuaW1hdGVkLlNjcm9sbFZpZXcpXG4gICAgICAgIC8vIGFuZCBpZiB3ZSBhcmUgb24gYSBSZWFjdCBOYXRpdmUgdmVyc2lvbiB3aGVyZSBpdCB3YXMgcmVjb21tZW5kZWQuXG4gICAgICAgIGlmICh0eXBlb2YgKHNjcm9sbFZpZXcgYXMgYW55KS5nZXROb2RlID09PSAnZnVuY3Rpb24nICYmIGlzUHJlUk4wNjIpIHtcbiAgICAgICAgICAgIHJldHVybiAoc2Nyb2xsVmlldyBhcyBhbnkpLmdldE5vZGUoKTsgLy8gQ2FsbCBnZXROb2RlIGlmIGFwcGxpY2FibGVcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2Nyb2xsVmlldzsgLy8gT3RoZXJ3aXNlLCByZXR1cm4gdGhlIHNjcm9sbFZpZXcgZGlyZWN0bHlcbiAgICB9LFxuICAgIC8vIERlZmF1bHQgdmFsdWUgZm9yIHRocm90dGxpbmcsIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHVzZXIgd2l0aCBwcm9wc1xuICAgIHNjcm9sbEV2ZW50VGhyb3R0bGU6IDE2LFxuICAgIC8vIFNjcm9sbEludG9WaWV3IG9wdGlvbnMsIGNhbiBiZSBvZmZlcmVkIGJ5IDxTY3JvbGxJbnRvVmlldyAvPiBjb21wIG9yIGltcGVyYXRpdmUgdXNhZ2VcbiAgICBvcHRpb25zOiBEZWZhdWx0T3B0aW9uc1xufTtcblxuZXhwb3J0IGNvbnN0IG5vcm1hbGl6ZUhPQ0NvbmZpZyA9IChjb25maWc6IFBhcnRpYWxIT0NDb25maWcgPSB7fSkgPT4gKHtcbiAgICAuLi5EZWZhdWx0SE9DQ29uZmlnLFxuICAgIC4uLmNvbmZpZyxcbiAgICBvcHRpb25zOiBub3JtYWxpemVPcHRpb25zKGNvbmZpZy5vcHRpb25zLCBEZWZhdWx0T3B0aW9ucylcbn0pO1xuIiwiaW1wb3J0IHsgbm9ybWFsaXplT3B0aW9ucyB9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7IHRocm90dGxlIH0gZnJvbSAnLi91dGlscyc7XG5cbmltcG9ydCB0eXBlIHsgRnVsbE9wdGlvbnMsIFBhcnRpYWxPcHRpb25zIH0gZnJvbSAnLi9jb25maWcnO1xuaW1wb3J0IHR5cGUgeyBTY3JvbGxWaWV3LCBWaWV3IH0gZnJvbSAncmVhY3QtbmF0aXZlJztcblxudHlwZSBTY3JvbGxQYXJhbXMgPSB7IHg6IG51bWJlcjsgeTogbnVtYmVyOyBhbmltYXRlZDogYm9vbGVhbiB9O1xuXG5leHBvcnQgY29uc3Qgc2Nyb2xsSW50b1ZpZXcgPSBhc3luYyAoXG4gICAgc2Nyb2xsVmlldzogU2Nyb2xsVmlldyxcbiAgICB2aWV3OiBWaWV3LFxuICAgIHNjcm9sbFk6IG51bWJlcixcbiAgICBzY3JvbGxYOiBudW1iZXIsXG4gICAgb3B0aW9uczogUGFydGlhbE9wdGlvbnNcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGlmICghKHNjcm9sbFZpZXcgYXMgYW55KSB8fCAhKHZpZXcgYXMgYW55KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Njcm9sbFZpZXcgYW5kIHRhcmdldCBWaWV3IG11c3QgYmUgcHJvdmlkZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IGFsaWduLCBhbmltYXRlZCwgY29tcHV0ZVNjcm9sbFksIGNvbXB1dGVTY3JvbGxYLCBtZWFzdXJlRWxlbWVudCwgaW5zZXRzIH0gPSBub3JtYWxpemVPcHRpb25zKG9wdGlvbnMpO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgW3Njcm9sbFZpZXdMYXlvdXQsIHZpZXdMYXlvdXRdID0gYXdhaXQgUHJvbWlzZS5hbGwoW21lYXN1cmVFbGVtZW50KHNjcm9sbFZpZXcpLCBtZWFzdXJlRWxlbWVudCh2aWV3KV0pO1xuXG4gICAgICAgIGNvbnN0IHRhcmdldFNjcm9sbFkgPSBjb21wdXRlU2Nyb2xsWShzY3JvbGxWaWV3TGF5b3V0LCB2aWV3TGF5b3V0LCBzY3JvbGxZLCBpbnNldHMsIGFsaWduKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0U2Nyb2xsWCA9IGNvbXB1dGVTY3JvbGxYKHNjcm9sbFZpZXdMYXlvdXQsIHZpZXdMYXlvdXQsIHNjcm9sbFgsIGluc2V0cywgYWxpZ24pO1xuICAgICAgICBjb25zdCBzY3JvbGxQYXJhbXM6IFNjcm9sbFBhcmFtcyA9IHsgeDogdGFyZ2V0U2Nyb2xsWCwgeTogdGFyZ2V0U2Nyb2xsWSwgYW5pbWF0ZWQgfTtcblxuICAgICAgICBjb25zdCBzY3JvbGxSZXNwb25kZXIgPSBzY3JvbGxWaWV3LmdldFNjcm9sbFJlc3BvbmRlcigpO1xuICAgICAgICBpZiAoKHNjcm9sbFJlc3BvbmRlciBhcyBhbnkpLnNjcm9sbFJlc3BvbmRlclNjcm9sbFRvKSB7XG4gICAgICAgICAgICBzY3JvbGxSZXNwb25kZXIuc2Nyb2xsUmVzcG9uZGVyU2Nyb2xsVG8oc2Nyb2xsUGFyYW1zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNjcm9sbFZpZXcuc2Nyb2xsVG8oc2Nyb2xsUGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogJ1Vua25vd24gZXJyb3InO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBzY3JvbGwgaW50byB2aWV3OiAke2Vycm9yTWVzc2FnZX1gKTtcbiAgICB9XG59O1xuXG50eXBlIEdldFNjcm9sbFZpZXcgPSAoKSA9PiBTY3JvbGxWaWV3O1xudHlwZSBHZXRTY3JvbGxZID0gKCkgPT4gbnVtYmVyO1xudHlwZSBHZXRTY3JvbGxYID0gKCkgPT4gbnVtYmVyO1xudHlwZSBHZXREZWZhdWx0T3B0aW9ucyA9ICgpID0+IEZ1bGxPcHRpb25zO1xuXG5leHBvcnQgdHlwZSBTY3JvbGxJbnRvVmlld0RlcGVuZGVuY2llcyA9IHtcbiAgICByZWFkb25seSBnZXRTY3JvbGxWaWV3OiBHZXRTY3JvbGxWaWV3O1xuICAgIHJlYWRvbmx5IGdldFNjcm9sbFk6IEdldFNjcm9sbFk7XG4gICAgcmVhZG9ubHkgZ2V0U2Nyb2xsWDogR2V0U2Nyb2xsWDtcbiAgICByZWFkb25seSBnZXREZWZhdWx0T3B0aW9uczogR2V0RGVmYXVsdE9wdGlvbnM7XG59O1xuXG5leHBvcnQgY2xhc3MgU2Nyb2xsSW50b1ZpZXdBUEkge1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgZGVwZW5kZW5jaWVzOiBTY3JvbGxJbnRvVmlld0RlcGVuZGVuY2llcykge1xuICAgICAgICB0aGlzLnZhbGlkYXRlRGVwZW5kZW5jaWVzKGRlcGVuZGVuY2llcyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB2YWxpZGF0ZURlcGVuZGVuY2llcyhkZXBzOiBTY3JvbGxJbnRvVmlld0RlcGVuZGVuY2llcyk6IHZvaWQge1xuICAgICAgICBjb25zdCByZXF1aXJlZERlcEtleXM6IChrZXlvZiBTY3JvbGxJbnRvVmlld0RlcGVuZGVuY2llcylbXSA9IFtcbiAgICAgICAgICAgICdnZXRTY3JvbGxWaWV3JyxcbiAgICAgICAgICAgICdnZXRTY3JvbGxZJyxcbiAgICAgICAgICAgICdnZXRTY3JvbGxYJyxcbiAgICAgICAgICAgICdnZXREZWZhdWx0T3B0aW9ucydcbiAgICAgICAgXTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgcmVxdWlyZWREZXBLZXlzKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGRlcHNba2V5XSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRGVwZW5kZW5jeSBcIiR7a2V5fVwiIG11c3QgYmUgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Tm9ybWFsaXplZE9wdGlvbnMgPSAob3B0aW9uczogUGFydGlhbE9wdGlvbnMgPSB7fSk6IEZ1bGxPcHRpb25zID0+XG4gICAgICAgIG5vcm1hbGl6ZU9wdGlvbnMob3B0aW9ucywgdGhpcy5kZXBlbmRlbmNpZXMuZ2V0RGVmYXVsdE9wdGlvbnMoKSk7XG5cbiAgICBwdWJsaWMgc2Nyb2xsSW50b1ZpZXcgPSAodmlldzogVmlldywgb3B0aW9ucz86IFBhcnRpYWxPcHRpb25zKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRPcHRpb25zID0gdGhpcy5nZXROb3JtYWxpemVkT3B0aW9ucyhvcHRpb25zKTtcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRPcHRpb25zLmltbWVkaWF0ZVxuICAgICAgICAgICAgPyB0aGlzLnNjcm9sbEludG9WaWV3SW1tZWRpYXRlKHZpZXcsIG5vcm1hbGl6ZWRPcHRpb25zKVxuICAgICAgICAgICAgOiB0aGlzLnNjcm9sbEludG9WaWV3VGhyb3R0bGVkKHZpZXcsIG5vcm1hbGl6ZWRPcHRpb25zKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBwZXJmb3JtU2Nyb2xsID0gKHZpZXc6IFZpZXcsIG9wdGlvbnM6IFBhcnRpYWxPcHRpb25zKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIHJldHVybiBzY3JvbGxJbnRvVmlldyhcbiAgICAgICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzLmdldFNjcm9sbFZpZXcoKSxcbiAgICAgICAgICAgIHZpZXcsXG4gICAgICAgICAgICB0aGlzLmRlcGVuZGVuY2llcy5nZXRTY3JvbGxZKCksXG4gICAgICAgICAgICB0aGlzLmRlcGVuZGVuY2llcy5nZXRTY3JvbGxYKCksXG4gICAgICAgICAgICBvcHRpb25zXG4gICAgICAgICk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgc2Nyb2xsSW50b1ZpZXdUaHJvdHRsZWQgPSB0aHJvdHRsZSh0aGlzLnBlcmZvcm1TY3JvbGwsIDE2KTtcblxuICAgIHByaXZhdGUgc2Nyb2xsSW50b1ZpZXdJbW1lZGlhdGUgPSB0aGlzLnBlcmZvcm1TY3JvbGw7XG59XG4iLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5pbXBvcnQgeyBTY3JvbGxJbnRvVmlld0FQSSB9IGZyb20gJy4vYXBpJztcblxuaW1wb3J0IHR5cGUgeyBTY3JvbGxJbnRvVmlld0RlcGVuZGVuY2llcyB9IGZyb20gJy4vYXBpJztcblxuY29uc3QgQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQ8U2Nyb2xsSW50b1ZpZXdBUEkgfCBudWxsPihudWxsKTtcblxuZXhwb3J0IGRlZmF1bHQgQ29udGV4dDtcblxuZXhwb3J0IGNvbnN0IEFQSUNvbnN1bWVyID0gQ29udGV4dC5Db25zdW1lcjtcblxuaW50ZXJmYWNlIFByb3ZpZGVBUElQcm9wcyB7XG4gICAgZGVwZW5kZW5jaWVzOiBTY3JvbGxJbnRvVmlld0RlcGVuZGVuY2llcztcbiAgICBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlO1xufVxuXG5leHBvcnQgY29uc3QgUHJvdmlkZUFQSTogUmVhY3QuRkM8UHJvdmlkZUFQSVByb3BzPiA9ICh7IGRlcGVuZGVuY2llcywgY2hpbGRyZW4gfSkgPT4ge1xuICAgIGNvbnN0