theme-lib
Version:
This is a simple example Angular Library published to npm.
748 lines • 65.4 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/*
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
import { Component, ElementRef, HostBinding, HostListener, Input, Renderer2, ViewChild, ViewContainerRef, Inject, PLATFORM_ID, forwardRef, } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { BehaviorSubject } from 'rxjs';
import { filter, takeWhile } from 'rxjs/operators';
import { convertToBoolProperty } from '../helpers';
import { NbThemeService } from '../../services/theme.service';
import { NbSpinnerService } from '../../services/spinner.service';
import { NbLayoutDirectionService } from '../../services/direction.service';
import { NbRestoreScrollTopHelper } from './restore-scroll-top.service';
import { NbLayoutScrollService } from '../../services/scroll.service';
import { NbLayoutRulerService } from '../../services/ruler.service';
import { NB_WINDOW, NB_DOCUMENT } from '../../theme.options';
import { NbOverlayContainerAdapter } from '../cdk/adapter/overlay-container-adapter';
/*
* A container component which determines a content position inside of the layout.
* The layout could contain unlimited columns (not including the sidebars).
*
* By default the columns are ordered from the left to the right,
* but it's also possible to overwrite this behavior by setting a `left` attribute to the column,
* moving it to the very first position:
*
* @stacked-example(Column Left, layout/layout-column-left.component)
*/
export class NbLayoutColumnComponent {
/*
* Move the column to the very left position in the layout.
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set left(val) {
this.leftValue = convertToBoolProperty(val);
this.startValue = false;
}
/*
* Make columnt first in the layout.
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set start(val) {
this.startValue = convertToBoolProperty(val);
this.leftValue = false;
}
}
NbLayoutColumnComponent.decorators = [
{ type: Component, args: [{
selector: 'nb-layout-column',
template: `
<ng-content></ng-content>
`
}] }
];
NbLayoutColumnComponent.propDecorators = {
leftValue: [{ type: HostBinding, args: ['class.left',] }],
startValue: [{ type: HostBinding, args: ['class.start',] }],
left: [{ type: Input }],
start: [{ type: Input }]
};
if (false) {
/** @type {?} */
NbLayoutColumnComponent.prototype.leftValue;
/** @type {?} */
NbLayoutColumnComponent.prototype.startValue;
}
/*
* Page header component.
* Located on top of the page above the layout columns and sidebars.
* Could be made `fixed` by setting the corresponding property. In the fixed mode the header becomes
* sticky to the top of the nb-layout (to of the page). Here's an example:
*
* @stacked-example(Fixed Header, layout/layout-fixed-header.component)
*
* In a pair with sidebar it is possible to setup a configuration when header is placed on a side of the sidebar
* and not on top of it. To achieve this simply put a `subheader` property to the header like this:
* ```html
* <nb-layout-header subheader></nb-layout-header>
* ```
* @stacked-example(Subheader, layout/layout-sidebar-subheader.component)
* Note that in such configuration sidebar shadow is removed and header cannot be make `fixed`.
*
* Same way you can put both `fixed` and `clipped` headers adding creating a sub-header for your app:
*
* @stacked-example(Subheader, layout/layout-subheader.component)
*
* @styles
*
* header-font-family
* header-line-height
* header-fg
* header-bg
* header-height
* header-padding
* header-shadow
*/
export class NbLayoutHeaderComponent {
// tslint:disable-next-line
/**
* @param {?} layout
*/
constructor(layout) {
this.layout = layout;
}
/*
* Makes the header sticky to the top of the nb-layout.
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set fixed(val) {
this.fixedValue = convertToBoolProperty(val);
}
/*
* Places header on a side of the sidebar, and not above.
* Disables fixed mode for this header and remove a shadow from the sidebar.
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set subheader(val) {
this.subheaderValue = convertToBoolProperty(val);
this.fixedValue = false;
this.layout.withSubheader = this.subheaderValue;
}
}
NbLayoutHeaderComponent.decorators = [
{ type: Component, args: [{
selector: 'nb-layout-header',
template: `
<nav [class.fixed]="fixedValue">
<ng-content></ng-content>
</nav>
`
}] }
];
/** @nocollapse */
NbLayoutHeaderComponent.ctorParameters = () => [
{ type: NbLayoutComponent, decorators: [{ type: Inject, args: [forwardRef(() => NbLayoutComponent),] }] }
];
NbLayoutHeaderComponent.propDecorators = {
fixedValue: [{ type: HostBinding, args: ['class.fixed',] }],
subheaderValue: [{ type: HostBinding, args: ['class.subheader',] }],
fixed: [{ type: Input }],
subheader: [{ type: Input }]
};
if (false) {
/** @type {?} */
NbLayoutHeaderComponent.prototype.fixedValue;
/** @type {?} */
NbLayoutHeaderComponent.prototype.subheaderValue;
/**
* @type {?}
* @private
*/
NbLayoutHeaderComponent.prototype.layout;
}
/*
* Page footer.
* Located under the nb-layout content (specifically, under the columns).
* Could be made `fixed`, becoming sticky to the bottom of the view port (window).
*
* @styles
*
* footer-height
* footer-padding
* footer-fg
* footer-bg
* footer-separator
* footer-shadow
*/
export class NbLayoutFooterComponent {
/*
* Makes the footer sticky to the bottom of the window.
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set fixed(val) {
this.fixedValue = convertToBoolProperty(val);
}
}
NbLayoutFooterComponent.decorators = [
{ type: Component, args: [{
selector: 'nb-layout-footer',
template: `
<nav [class.fixed]="fixedValue">
<ng-content></ng-content>
</nav>
`
}] }
];
NbLayoutFooterComponent.propDecorators = {
fixedValue: [{ type: HostBinding, args: ['class.fixed',] }],
fixed: [{ type: Input }]
};
if (false) {
/** @type {?} */
NbLayoutFooterComponent.prototype.fixedValue;
}
/*
* Layout container component.
* When using with Nebular Theme System it is required that all child components should be placed inside.
*
* Basic example of two column layout with header:
*
* @stacked-example(Showcase, layout/layout-showcase.component)
*
* Can contain the following components inside:
*
* ```html
* <nb-layout>
* <nb-layout-header></nb-layout-header>
* <nb-layout-footer></nb-layout-column>
* <nb-layout-column></nb-layout-column>
* <nb-sidebar></nb-sidebar>
* </nb-layout>
* ```
* ### Installation
*
* Import `NbLayoutModule.forRoot()` to your app module.
* ```ts
* @NgModule({
* imports: [
* // ...
* NbLayoutModule.forRoot(),
* ],
* })
* export class AppModule { }
* ```
* and `NbLayoutModule` to your feature module where the component should be shown:
* ```ts
* @NgModule({
* imports: [
* // ...
* NbLayoutModule,
* ],
* })
* export class PageModule { }
* ```
* ### Usage
* By default the layout fills up the whole view-port.
* The window scrollbars are disabled on the body and moved inside of the nb-layout, so that the scrollbars
* won't mess with the fixed nb-header.
*
* The child components are projected into a flexible layout structure allowing to adjust the layout behavior
* based on the settings provided.
*
* The layout content (columns) becomes centered when the window width is more than
* the value specified in the theme variable `layout-content-width`.
*
* The layout also contains the area on the very top (the first child of the nb-layout), which could be used
* to dynamically append some components like modals or spinners/loaders
* so that they are located on top of the elements hierarchy.
* More details are under the `ThemeService` section.
*
* The layout component is also responsible for changing application themes.
* It listens to the `themeChange` event and change a theme CSS class appended to body.
* Based on the class appended, specific CSS-theme is applied to the application.
* More details of the Theme System could be found here [Enabling Theme System](#/docs/concepts/theme-system)
*
* A simple layout with footer:
*
* @stacked-example(Layout With Footer, layout/layout-w-footer.component)
*
* It is possible to ask the layout to center the columns (notice: we added a `center` attribute
* to the layout:
*
* ```html
* <nb-layout center>
* <nb-layout-header>Awesome Company</nb-layout-header>
*
* <nb-layout-column>
* Hello World!
* </nb-layout-column>
*
* <nb-layout-footer>Contact us</nb-layout-footer>
* </nb-layout>
* ```
*
* @styles
*
* layout-font-family
* layout-font-size
* layout-line-height
* layout-fg
* layout-bg
* layout-min-height
* layout-content-width
* layout-window-mode-min-width
* layout-window-mode-max-width: window mode only, after this value layout turns into a floating window
* layout-window-mode-bg: window mode only, background
* layout-window-mode-padding-top: window mode only, max padding from top
* layout-window-shadow: window mode shadow
* layout-padding
* layout-medium-padding
* layout-small-padding
*/
export class NbLayoutComponent {
/**
* @param {?} themeService
* @param {?} spinnerService
* @param {?} elementRef
* @param {?} renderer
* @param {?} window
* @param {?} document
* @param {?} platformId
* @param {?} layoutDirectionService
* @param {?} scrollService
* @param {?} rulerService
* @param {?} scrollTop
* @param {?} overlayContainer
*/
constructor(themeService, spinnerService, elementRef, renderer, window, document, platformId, layoutDirectionService, scrollService, rulerService, scrollTop, overlayContainer) {
this.themeService = themeService;
this.spinnerService = spinnerService;
this.elementRef = elementRef;
this.renderer = renderer;
this.window = window;
this.document = document;
this.platformId = platformId;
this.layoutDirectionService = layoutDirectionService;
this.scrollService = scrollService;
this.rulerService = rulerService;
this.scrollTop = scrollTop;
this.overlayContainer = overlayContainer;
this.centerValue = false;
this.restoreScrollTopValue = true;
this.windowModeValue = false;
this.withScrollValue = false;
this.withSubheader = false;
this.afterViewInit$ = new BehaviorSubject(null);
this.alive = true;
this.registerAsOverlayContainer();
this.themeService.onThemeChange()
.pipe(takeWhile(() => this.alive))
.subscribe((theme) => {
/** @type {?} */
const body = this.document.getElementsByTagName('body')[0];
if (theme.previous) {
this.renderer.removeClass(body, `nb-theme-${theme.previous}`);
}
this.renderer.addClass(body, `nb-theme-${theme.name}`);
});
this.themeService.onAppendLayoutClass()
.pipe(takeWhile(() => this.alive))
.subscribe((className) => {
this.renderer.addClass(this.elementRef.nativeElement, className);
});
this.themeService.onRemoveLayoutClass()
.pipe(takeWhile(() => this.alive))
.subscribe((className) => {
this.renderer.removeClass(this.elementRef.nativeElement, className);
});
this.spinnerService.registerLoader(new Promise((resolve, reject) => {
this.afterViewInit$
.pipe(takeWhile(() => this.alive))
.subscribe((_) => resolve());
}));
this.spinnerService.load();
this.rulerService.onGetDimensions()
.pipe(takeWhile(() => this.alive))
.subscribe(({ listener }) => {
listener.next(this.getDimensions());
listener.complete();
});
this.scrollService.onGetPosition()
.pipe(takeWhile(() => this.alive))
.subscribe(({ listener }) => {
listener.next(this.getScrollPosition());
listener.complete();
});
this.scrollTop
.shouldRestore()
.pipe(filter(() => this.restoreScrollTopValue), takeWhile(() => this.alive))
.subscribe(() => {
this.scroll(0, 0);
});
if (isPlatformBrowser(this.platformId)) {
// trigger first time so that after the change we have the initial value
this.themeService.changeWindowWidth(this.window.innerWidth);
}
}
/*
* Defines whether the layout columns will be centered after some width
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set center(val) {
this.centerValue = convertToBoolProperty(val);
}
/*
* Defines whether the layout enters a 'window' mode, when the layout content (including sidebars and fixed header)
* becomes centered by width with a margin from the top of the screen, like a floating window.
* Automatically enables `withScroll` mode, as in the window mode scroll must be inside the layout and cannot be on
* window. (TODO: check this)
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set windowMode(val) {
this.windowModeValue = convertToBoolProperty(val);
this.withScroll = this.windowModeValue;
}
/*
* Defines whether to move the scrollbars to layout or leave it at the body level.
* Automatically set to true when `windowMode` is enabled.
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set withScroll(val) {
this.withScrollValue = convertToBoolProperty(val);
// TODO: is this the best way of doing it? as we don't have access to body from theme styles
// TODO: add e2e test
/** @type {?} */
const body = this.document.getElementsByTagName('body')[0];
if (this.withScrollValue) {
this.renderer.setStyle(body, 'overflow', 'hidden');
}
else {
this.renderer.setStyle(body, 'overflow', 'initial');
}
}
/*
* Restores scroll to the top of the page after navigation
* @param {boolean} val
*/
/**
* @param {?} val
* @return {?}
*/
set restoreScrollTop(val) {
this.restoreScrollTopValue = convertToBoolProperty(val);
}
/**
* @return {?}
*/
ngAfterViewInit() {
this.layoutDirectionService.onDirectionChange()
.pipe(takeWhile(() => this.alive))
.subscribe(direction => {
this.renderer.setProperty(this.document, 'dir', direction);
});
this.scrollService.onManualScroll()
.pipe(takeWhile(() => this.alive))
.subscribe(({ x, y }) => this.scroll(x, y));
this.afterViewInit$.next(true);
}
/**
* @return {?}
*/
ngOnDestroy() {
this.alive = false;
this.unregisterAsOverlayContainer();
}
/**
* @param {?} $event
* @return {?}
*/
onScroll($event) {
this.scrollService.fireScrollChange($event);
}
/**
* @param {?} event
* @return {?}
*/
onResize(event) {
this.themeService.changeWindowWidth(event.target.innerWidth);
}
/*
* Returns scroll and client height/width
*
* Depending on the current scroll mode (`withScroll=true`) returns sizes from the body element
* or from the `.scrollable-container`
* @returns {NbLayoutDimensions}
*/
/**
* @return {?}
*/
getDimensions() {
/** @type {?} */
let clientWidth;
/** @type {?} */
let clientHeight;
/** @type {?} */
let scrollWidth;
/** @type {?} */
let scrollHeight = 0;
if (this.withScrollValue) {
/** @type {?} */
const container = this.scrollableContainerRef.nativeElement;
clientWidth = container.clientWidth;
clientHeight = container.clientHeight;
scrollWidth = container.scrollWidth;
scrollHeight = container.scrollHeight;
}
else {
const { documentElement, body } = this.document;
clientWidth = documentElement.clientWidth || body.clientWidth;
clientHeight = documentElement.clientHeight || body.clientHeight;
scrollWidth = documentElement.scrollWidth || body.scrollWidth;
scrollHeight = documentElement.scrollHeight || body.scrollHeight;
}
return {
clientWidth,
clientHeight,
scrollWidth,
scrollHeight,
};
}
/*
* Returns scroll position of current scroll container.
*
* If `withScroll` = true, returns scroll position of the `.scrollable-container` element,
* otherwise - of the scrollable element of the window (which may be different depending of a browser)
*
* @returns {NbScrollPosition}
*/
/**
* @return {?}
*/
getScrollPosition() {
if (this.withScrollValue) {
/** @type {?} */
const container = this.scrollableContainerRef.nativeElement;
return { x: container.scrollLeft, y: container.scrollTop };
}
/** @type {?} */
const documentRect = this.document.documentElement.getBoundingClientRect();
/** @type {?} */
const x = -documentRect.left || this.document.body.scrollLeft || this.window.scrollX ||
this.document.documentElement.scrollLeft || 0;
/** @type {?} */
const y = -documentRect.top || this.document.body.scrollTop || this.window.scrollY ||
this.document.documentElement.scrollTop || 0;
return { x, y };
}
/**
* @protected
* @return {?}
*/
registerAsOverlayContainer() {
if (this.overlayContainer.setContainer) {
this.overlayContainer.setContainer(this.elementRef.nativeElement);
}
}
/**
* @protected
* @return {?}
*/
unregisterAsOverlayContainer() {
if (this.overlayContainer.clearContainer) {
this.overlayContainer.clearContainer();
}
}
/**
* @private
* @param {?=} x
* @param {?=} y
* @return {?}
*/
scroll(x = null, y = null) {
const { x: currentX, y: currentY } = this.getScrollPosition();
x = x == null ? currentX : x;
y = y == null ? currentY : y;
if (!isPlatformBrowser(this.platformId)) {
return;
}
if (this.withScrollValue) {
/** @type {?} */
const scrollable = this.scrollableContainerRef.nativeElement;
if (scrollable.scrollTo) {
scrollable.scrollTo(x, y);
}
else {
scrollable.scrollLeft = x;
scrollable.scrollTop = y;
}
}
else {
this.window.scrollTo(x, y);
}
}
}
NbLayoutComponent.decorators = [
{ type: Component, args: [{
selector: 'nb-layout',
template: `
<div class="scrollable-container" #scrollableContainer (scroll)="onScroll($event)">
<div class="layout">
<ng-content select="nb-layout-header:not([subheader])"></ng-content>
<div class="layout-container">
<ng-content select="nb-sidebar"></ng-content>
<div class="content" [class.center]="centerValue">
<ng-content select="nb-layout-header[subheader]"></ng-content>
<div class="columns">
<ng-content select="nb-layout-column"></ng-content>
</div>
<ng-content select="nb-layout-footer"></ng-content>
</div>
</div>
</div>
</div>
`,
styles: [":host{-webkit-font-smoothing:antialiased}[dir=ltr] :host{text-align:left}[dir=rtl] :host{text-align:right}:host .layout{display:flex;flex-direction:column}:host /deep/ nb-layout-header{display:block}:host /deep/ nb-layout-header nav{align-items:center;justify-content:flex-start;display:flex}:host /deep/ nb-layout-header.fixed{position:fixed;left:0;right:0;z-index:1040}:host .layout-container{display:flex;flex:1;-ms-flex:1 1 auto;flex-direction:row}[dir=ltr] :host .layout-container /deep/ nb-sidebar.left{order:0}[dir=rtl] :host .layout-container /deep/ nb-sidebar.left{order:2}[dir=ltr] :host .layout-container /deep/ nb-sidebar.right{order:2}[dir=rtl] :host .layout-container /deep/ nb-sidebar.right{order:0}:host .layout-container /deep/ nb-sidebar.end{order:2}:host .layout-container /deep/ nb-sidebar .fixed{position:fixed;width:100%;overflow-y:auto;height:100%}:host .layout-container .content{display:flex;flex:1;-ms-flex:1 1 auto;flex-direction:column;min-width:0}:host .layout-container .content.center{max-width:100%;position:relative;margin-left:auto;margin-right:auto}:host .layout-container .content .columns{display:flex;flex:1;-ms-flex:1 1 auto;flex-direction:row;width:100%}:host .layout-container .content .columns /deep/ nb-layout-column{order:1;flex:1 0;min-width:0}[dir=ltr] :host .layout-container .content .columns /deep/ nb-layout-column.left{order:0}[dir=rtl] :host .layout-container .content .columns /deep/ nb-layout-column.left{order:2}:host .layout-container .content .columns /deep/ nb-layout-column.start{order:0}:host .layout-container .content /deep/ nb-layout-footer{display:block;margin-top:auto}:host .layout-container .content /deep/ nb-layout-footer nav{justify-content:center;display:flex}"]
}] }
];
/** @nocollapse */
NbLayoutComponent.ctorParameters = () => [
{ type: NbThemeService },
{ type: NbSpinnerService },
{ type: ElementRef },
{ type: Renderer2 },
{ type: undefined, decorators: [{ type: Inject, args: [NB_WINDOW,] }] },
{ type: undefined, decorators: [{ type: Inject, args: [NB_DOCUMENT,] }] },
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] },
{ type: NbLayoutDirectionService },
{ type: NbLayoutScrollService },
{ type: NbLayoutRulerService },
{ type: NbRestoreScrollTopHelper },
{ type: NbOverlayContainerAdapter }
];
NbLayoutComponent.propDecorators = {
windowModeValue: [{ type: HostBinding, args: ['class.window-mode',] }],
withScrollValue: [{ type: HostBinding, args: ['class.with-scroll',] }],
withSubheader: [{ type: HostBinding, args: ['class.with-subheader',] }],
center: [{ type: Input }],
windowMode: [{ type: Input }],
withScroll: [{ type: Input }],
restoreScrollTop: [{ type: Input }],
veryTopRef: [{ type: ViewChild, args: ['layoutTopDynamicArea', { read: ViewContainerRef },] }],
scrollableContainerRef: [{ type: ViewChild, args: ['scrollableContainer', { read: ElementRef },] }],
onScroll: [{ type: HostListener, args: ['window:scroll', ['$event'],] }],
onResize: [{ type: HostListener, args: ['window:resize', ['$event'],] }]
};
if (false) {
/** @type {?} */
NbLayoutComponent.prototype.centerValue;
/** @type {?} */
NbLayoutComponent.prototype.restoreScrollTopValue;
/** @type {?} */
NbLayoutComponent.prototype.windowModeValue;
/** @type {?} */
NbLayoutComponent.prototype.withScrollValue;
/** @type {?} */
NbLayoutComponent.prototype.withSubheader;
/** @type {?} */
NbLayoutComponent.prototype.veryTopRef;
/** @type {?} */
NbLayoutComponent.prototype.scrollableContainerRef;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.afterViewInit$;
/**
* @type {?}
* @private
*/
NbLayoutComponent.prototype.alive;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.themeService;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.spinnerService;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.elementRef;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.renderer;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.window;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.document;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.platformId;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.layoutDirectionService;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.scrollService;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.rulerService;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.scrollTop;
/**
* @type {?}
* @protected
*/
NbLayoutComponent.prototype.overlayContainer;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3RoZW1lLWxpYi8iLCJzb3VyY2VzIjpbImxpYi9jb21wb25lbnRzL2xheW91dC9sYXlvdXQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQU1BLE9BQU8sRUFDVSxTQUFTLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUN0RSxTQUFTLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsVUFBVSxHQUN4RSxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbkQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUM1RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN4RSxPQUFPLEVBQW9CLHFCQUFxQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDeEYsT0FBTyxFQUFzQixvQkFBb0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3hGLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDN0QsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sMENBQTBDLENBQUM7Ozs7Ozs7Ozs7O0FBa0JyRixNQUFNLE9BQU8sdUJBQXVCOzs7Ozs7Ozs7SUFT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IjpbIi8qXHJcbiAqIEBsaWNlbnNlXHJcbiAqIENvcHlyaWdodCBBa3Zlby4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgTGljZW5zZS50eHQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSBpbmZvcm1hdGlvbi5cclxuICovXHJcblxyXG5pbXBvcnQge1xyXG4gIEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE9uRGVzdHJveSxcclxuICBSZW5kZXJlcjIsIFZpZXdDaGlsZCwgVmlld0NvbnRhaW5lclJlZiwgSW5qZWN0LCBQTEFURk9STV9JRCwgZm9yd2FyZFJlZixcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZmlsdGVyLCB0YWtlV2hpbGUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5pbXBvcnQgeyBjb252ZXJ0VG9Cb29sUHJvcGVydHkgfSBmcm9tICcuLi9oZWxwZXJzJztcclxuaW1wb3J0IHsgTmJUaGVtZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy90aGVtZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTmJTcGlubmVyU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3NwaW5uZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IE5iTGF5b3V0RGlyZWN0aW9uU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2RpcmVjdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTmJSZXN0b3JlU2Nyb2xsVG9wSGVscGVyIH0gZnJvbSAnLi9yZXN0b3JlLXNjcm9sbC10b3Auc2VydmljZSc7XHJcbmltcG9ydCB7IE5iU2Nyb2xsUG9zaXRpb24sIE5iTGF5b3V0U2Nyb2xsU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3Njcm9sbC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTmJMYXlvdXREaW1lbnNpb25zLCBOYkxheW91dFJ1bGVyU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3J1bGVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBOQl9XSU5ET1csIE5CX0RPQ1VNRU5UIH0gZnJvbSAnLi4vLi4vdGhlbWUub3B0aW9ucyc7XHJcbmltcG9ydCB7IE5iT3ZlcmxheUNvbnRhaW5lckFkYXB0ZXIgfSBmcm9tICcuLi9jZGsvYWRhcHRlci9vdmVybGF5LWNvbnRhaW5lci1hZGFwdGVyJztcclxuXHJcbi8qXHJcbiAqIEEgY29udGFpbmVyIGNvbXBvbmVudCB3aGljaCBkZXRlcm1pbmVzIGEgY29udGVudCBwb3NpdGlvbiBpbnNpZGUgb2YgdGhlIGxheW91dC5cclxuICogVGhlIGxheW91dCBjb3VsZCBjb250YWluIHVubGltaXRlZCBjb2x1bW5zIChub3QgaW5jbHVkaW5nIHRoZSBzaWRlYmFycykuXHJcbiAqXHJcbiAqIEJ5IGRlZmF1bHQgdGhlIGNvbHVtbnMgYXJlIG9yZGVyZWQgZnJvbSB0aGUgbGVmdCB0byB0aGUgcmlnaHQsXHJcbiAqIGJ1dCBpdCdzIGFsc28gcG9zc2libGUgdG8gb3ZlcndyaXRlIHRoaXMgYmVoYXZpb3IgYnkgc2V0dGluZyBhIGBsZWZ0YCBhdHRyaWJ1dGUgdG8gdGhlIGNvbHVtbixcclxuICogbW92aW5nIGl0IHRvIHRoZSB2ZXJ5IGZpcnN0IHBvc2l0aW9uOlxyXG4gKlxyXG4gKiBAc3RhY2tlZC1leGFtcGxlKENvbHVtbiBMZWZ0LCBsYXlvdXQvbGF5b3V0LWNvbHVtbi1sZWZ0LmNvbXBvbmVudClcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmItbGF5b3V0LWNvbHVtbicsXHJcbiAgdGVtcGxhdGU6IGBcclxuICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cclxuICBgLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmJMYXlvdXRDb2x1bW5Db21wb25lbnQge1xyXG5cclxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmxlZnQnKSBsZWZ0VmFsdWU6IGJvb2xlYW47XHJcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5zdGFydCcpIHN0YXJ0VmFsdWU6IGJvb2xlYW47XHJcblxyXG4gIC8qXHJcbiAgICogTW92ZSB0aGUgY29sdW1uIHRvIHRoZSB2ZXJ5IGxlZnQgcG9zaXRpb24gaW4gdGhlIGxheW91dC5cclxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZhbFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IGxlZnQodmFsOiBib29sZWFuKSB7XHJcbiAgICB0aGlzLmxlZnRWYWx1ZSA9IGNvbnZlcnRUb0Jvb2xQcm9wZXJ0eSh2YWwpO1xyXG4gICAgdGhpcy5zdGFydFZhbHVlID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIE1ha2UgY29sdW1udCBmaXJzdCBpbiB0aGUgbGF5b3V0LlxyXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gdmFsXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBzZXQgc3RhcnQodmFsOiBib29sZWFuKSB7XHJcbiAgICB0aGlzLnN0YXJ0VmFsdWUgPSBjb252ZXJ0VG9Cb29sUHJvcGVydHkodmFsKTtcclxuICAgIHRoaXMubGVmdFZhbHVlID0gZmFsc2U7XHJcbiAgfVxyXG59XHJcblxyXG4vKlxyXG4gKiBQYWdlIGhlYWRlciBjb21wb25lbnQuXHJcbiAqIExvY2F0ZWQgb24gdG9wIG9mIHRoZSBwYWdlIGFib3ZlIHRoZSBsYXlvdXQgY29sdW1ucyBhbmQgc2lkZWJhcnMuXHJcbiAqIENvdWxkIGJlIG1hZGUgYGZpeGVkYCBieSBzZXR0aW5nIHRoZSBjb3JyZXNwb25kaW5nIHByb3BlcnR5LiBJbiB0aGUgZml4ZWQgbW9kZSB0aGUgaGVhZGVyIGJlY29tZXNcclxuICogc3RpY2t5IHRvIHRoZSB0b3Agb2YgdGhlIG5iLWxheW91dCAodG8gb2YgdGhlIHBhZ2UpLiBIZXJlJ3MgYW4gZXhhbXBsZTpcclxuICpcclxuICogQHN0YWNrZWQtZXhhbXBsZShGaXhlZCBIZWFkZXIsIGxheW91dC9sYXlvdXQtZml4ZWQtaGVhZGVyLmNvbXBvbmVudClcclxuICpcclxuICogSW4gYSBwYWlyIHdpdGggc2lkZWJhciBpdCBpcyBwb3NzaWJsZSB0byBzZXR1cCBhIGNvbmZpZ3VyYXRpb24gd2hlbiBoZWFkZXIgaXMgcGxhY2VkIG9uIGEgc2lkZSBvZiB0aGUgc2lkZWJhclxyXG4gKiBhbmQgbm90IG9uIHRvcCBvZiBpdC4gVG8gYWNoaWV2ZSB0aGlzIHNpbXBseSBwdXQgYSBgc3ViaGVhZGVyYCBwcm9wZXJ0eSB0byB0aGUgaGVhZGVyIGxpa2UgdGhpczpcclxuICogYGBgaHRtbFxyXG4gKiA8bmItbGF5b3V0LWhlYWRlciBzdWJoZWFkZXI+PC9uYi1sYXlvdXQtaGVhZGVyPlxyXG4gKiBgYGBcclxuICogQHN0YWNrZWQtZXhhbXBsZShTdWJoZWFkZXIsIGxheW91dC9sYXlvdXQtc2lkZWJhci1zdWJoZWFkZXIuY29tcG9uZW50KVxyXG4gKiBOb3RlIHRoYXQgaW4gc3VjaCBjb25maWd1cmF0aW9uIHNpZGViYXIgc2hhZG93IGlzIHJlbW92ZWQgYW5kIGhlYWRlciBjYW5ub3QgYmUgbWFrZSBgZml4ZWRgLlxyXG4gKlxyXG4gKiBTYW1lIHdheSB5b3UgY2FuIHB1dCBib3RoIGBmaXhlZGAgYW5kIGBjbGlwcGVkYCBoZWFkZXJzIGFkZGluZyBjcmVhdGluZyBhIHN1Yi1oZWFkZXIgZm9yIHlvdXIgYXBwOlxyXG4gKlxyXG4gKiBAc3RhY2tlZC1leGFtcGxlKFN1YmhlYWRlciwgbGF5b3V0L2xheW91dC1zdWJoZWFkZXIuY29tcG9uZW50KVxyXG4gKlxyXG4gKiBAc3R5bGVzXHJcbiAqXHJcbiAqIGhlYWRlci1mb250LWZhbWlseVxyXG4gKiBoZWFkZXItbGluZS1oZWlnaHRcclxuICogaGVhZGVyLWZnXHJcbiAqIGhlYWRlci1iZ1xyXG4gKiBoZWFkZXItaGVpZ2h0XHJcbiAqIGhlYWRlci1wYWRkaW5nXHJcbiAqIGhlYWRlci1zaGFkb3dcclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmItbGF5b3V0LWhlYWRlcicsXHJcbiAgdGVtcGxhdGU6IGBcclxuICAgIDxuYXYgW2NsYXNzLmZpeGVkXT1cImZpeGVkVmFsdWVcIj5cclxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG4gICAgPC9uYXY+XHJcbiAgYCxcclxufSlcclxuZXhwb3J0IGNsYXNzIE5iTGF5b3V0SGVhZGVyQ29tcG9uZW50IHtcclxuXHJcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5maXhlZCcpIGZpeGVkVmFsdWU6IGJvb2xlYW47XHJcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5zdWJoZWFkZXInKSBzdWJoZWFkZXJWYWx1ZTogYm9vbGVhbjtcclxuXHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lXHJcbiAgY29uc3RydWN0b3IoQEluamVjdChmb3J3YXJkUmVmKCgpID0+IE5iTGF5b3V0Q29tcG9uZW50KSkgcHJpdmF0ZSBsYXlvdXQ6IE5iTGF5b3V0Q29tcG9uZW50KSB7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIE1ha2VzIHRoZSBoZWFkZXIgc3RpY2t5IHRvIHRoZSB0b3Agb2YgdGhlIG5iLWxheW91dC5cclxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZhbFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IGZpeGVkKHZhbDogYm9vbGVhbikge1xyXG4gICAgdGhpcy5maXhlZFZhbHVlID0gY29udmVydFRvQm9vbFByb3BlcnR5KHZhbCk7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFBsYWNlcyBoZWFkZXIgb24gYSBzaWRlIG9mIHRoZSBzaWRlYmFyLCBhbmQgbm90IGFib3ZlLlxyXG4gICAqIERpc2FibGVzIGZpeGVkIG1vZGUgZm9yIHRoaXMgaGVhZGVyIGFuZCByZW1vdmUgYSBzaGFkb3cgZnJvbSB0aGUgc2lkZWJhci5cclxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZhbFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IHN1YmhlYWRlcih2YWw6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuc3ViaGVhZGVyVmFsdWUgPSBjb252ZXJ0VG9Cb29sUHJvcGVydHkodmFsKTtcclxuICAgIHRoaXMuZml4ZWRWYWx1ZSA9IGZhbHNlO1xyXG4gICAgdGhpcy5sYXlvdXQud2l0aFN1YmhlYWRlciA9IHRoaXMuc3ViaGVhZGVyVmFsdWU7XHJcbiAgfVxyXG59XHJcblxyXG4vKlxyXG4gKiBQYWdlIGZvb3Rlci5cclxuICogTG9jYXRlZCB1bmRlciB0aGUgbmItbGF5b3V0IGNvbnRlbnQgKHNwZWNpZmljYWxseSwgdW5kZXIgdGhlIGNvbHVtbnMpLlxyXG4gKiBDb3VsZCBiZSBtYWRlIGBmaXhlZGAsIGJlY29taW5nIHN0aWNreSB0byB0aGUgYm90dG9tIG9mIHRoZSB2aWV3IHBvcnQgKHdpbmRvdykuXHJcbiAqXHJcbiAqIEBzdHlsZXNcclxuICpcclxuICogZm9vdGVyLWhlaWdodFxyXG4gKiBmb290ZXItcGFkZGluZ1xyXG4gKiBmb290ZXItZmdcclxuICogZm9vdGVyLWJnXHJcbiAqIGZvb3Rlci1zZXBhcmF0b3JcclxuICogZm9vdGVyLXNoYWRvd1xyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduYi1sYXlvdXQtZm9vdGVyJyxcclxuICB0ZW1wbGF0ZTogYFxyXG4gICAgPG5hdiBbY2xhc3MuZml4ZWRdPVwiZml4ZWRWYWx1ZVwiPlxyXG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XHJcbiAgICA8L25hdj5cclxuICBgLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmJMYXlvdXRGb290ZXJDb21wb25lbnQge1xyXG5cclxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmZpeGVkJykgZml4ZWRWYWx1ZTogYm9vbGVhbjtcclxuXHJcbiAgLypcclxuICAgKiBNYWtlcyB0aGUgZm9vdGVyIHN0aWNreSB0byB0aGUgYm90dG9tIG9mIHRoZSB3aW5kb3cuXHJcbiAgICogQHBhcmFtIHtib29sZWFufSB2YWxcclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHNldCBmaXhlZCh2YWw6IGJvb2xlYW4pIHtcclxuICAgIHRoaXMuZml4ZWRWYWx1ZSA9IGNvbnZlcnRUb0Jvb2xQcm9wZXJ0eSh2YWwpO1xyXG4gIH1cclxuXHJcbn1cclxuXHJcbi8qXHJcbiAqIExheW91dCBjb250YWluZXIgY29tcG9uZW50LlxyXG4gKiBXaGVuIHVzaW5nIHdpdGggTmVidWxhciBUaGVtZSBTeXN0ZW0gaXQgaXMgcmVxdWlyZWQgdGhhdCBhbGwgY2hpbGQgY29tcG9uZW50cyBzaG91bGQgYmUgcGxhY2VkIGluc2lkZS5cclxuICpcclxuICogQmFzaWMgZXhhbXBsZSBvZiB0d28gY29sdW1uIGxheW91dCB3aXRoIGhlYWRlcjpcclxuICpcclxuICogQHN0YWNrZWQtZXhhbXBsZShTaG93Y2FzZSwgbGF5b3V0L2xheW91dC1zaG93Y2FzZS5jb21wb25lbnQpXHJcbiAqXHJcbiAqIENhbiBjb250YWluIHRoZSBmb2xsb3dpbmcgY29tcG9uZW50cyBpbnNpZGU6XHJcbiAqXHJcbiAqIGBgYGh0bWxcclxuICogPG5iLWxheW91dD5cclxuICogIDxuYi1sYXlvdXQtaGVhZGVyPjwvbmItbGF5b3V0LWhlYWRlcj5cclxuICogIDxuYi1sYXlvdXQtZm9vdGVyPjwvbmItbGF5b3V0LWNvbHVtbj5cclxuICogIDxuYi1sYXlvdXQtY29sdW1uPjwvbmItbGF5b3V0LWNvbHVtbj5cclxuICogIDxuYi1zaWRlYmFyPjwvbmItc2lkZWJhcj5cclxuICogPC9uYi1sYXlvdXQ+XHJcbiAqIGBgYFxyXG4gKiAjIyMgSW5zdGFsbGF0aW9uXHJcbiAqXHJcbiAqIEltcG9ydCBgTmJMYXlvdXRNb2R1bGUuZm9yUm9vdCgpYCB0byB5b3VyIGFwcCBtb2R1bGUuXHJcbiAqIGBgYHRzXHJcbiAqIEBOZ01vZHVsZSh7XHJcbiAqICAgaW1wb3J0czogW1xyXG4gKiAgIFx0Ly8gLi4uXHJcbiAqICAgICBOYkxheW91dE1vZHVsZS5mb3JSb290KCksXHJcbiAqICAgXSxcclxuICogfSlcclxuICogZXhwb3J0IGNsYXNzIEFwcE1vZHVsZSB7IH1cclxuICogYGBgXHJcbiAqIGFuZCBgTmJMYXlvdXRNb2R1bGVgIHRvIHlvdXIgZmVhdHVyZSBtb2R1bGUgd2hlcmUgdGhlIGNvbXBvbmVudCBzaG91bGQgYmUgc2hvd246XHJcbiAqIGBgYHRzXHJcbiAqIEBOZ01vZHVsZSh7XHJcbiAqICAgaW1wb3J0czogW1xyXG4gKiAgIFx0Ly8gLi4uXHJcbiAqICAgICBOYkxheW91dE1vZHVsZSxcclxuICogICBdLFxyXG4gKiB9KVxyXG4gKiBleHBvcnQgY2xhc3MgUGFnZU1vZHVsZSB7IH1cclxuICogYGBgXHJcbiAqICMjIyBVc2FnZVxyXG4gKiBCeSBkZWZhdWx0IHRoZSBsYXlvdXQgZmlsbHMgdXAgdGhlIHdob2xlIHZpZXctcG9ydC5cclxuICogVGhlIHdpbmRvdyBzY3JvbGxiYXJzIGFyZSBkaXNhYmxlZCBvbiB0aGUgYm9keSBhbmQgbW92ZWQgaW5zaWRlIG9mIHRoZSBuYi1sYXlvdXQsIHNvIHRoYXQgdGhlIHNjcm9sbGJhcnNcclxuICogd29uJ3QgbWVzcyB3aXRoIHRoZSBmaXhlZCBuYi1oZWFkZXIuXHJcbiAqXHJcbiAqIFRoZSBjaGlsZCBjb21wb25lbnRzIGFyZSBwcm9qZWN0ZWQgaW50byBhIGZsZXhpYmxlIGxheW91dCBzdHJ1Y3R1cmUgYWxsb3dpbmcgdG8gYWRqdXN0IHRoZSBsYXlvdXQgYmVoYXZpb3JcclxuICogYmFzZWQgb24gdGhlIHNldHRpbmdzIHByb3ZpZGVkLlxyXG4gKlxyXG4gKiBUaGUgbGF5b3V0IGNvbnRlbnQgKGNvbHVtbnMpIGJlY29tZXMgY2VudGVyZWQgd2hlbiB0aGUgd2luZG93IHdpZHRoIGlzIG1vcmUgdGhhblxyXG4gKiB0aGUgdmFsdWUgc3BlY2lmaWVkIGluIHRoZSB0aGVtZSB2YXJpYWJsZSBgbGF5b3V0LWNvbnRlbnQtd2lkdGhgLlxyXG4gKlxyXG4gKiBUaGUgbGF5b3V0IGFsc28gY29udGFpbnMgdGhlIGFyZWEgb24gdGhlIHZlcnkgdG9wICh0aGUgZmlyc3QgY2hpbGQgb2YgdGhlIG5iLWxheW91dCksIHdoaWNoIGNvdWxkIGJlIHVzZWRcclxuICogdG8gZHluYW1pY2FsbHkgYXBwZW5kIHNvbWUgY29tcG9uZW50cyBsaWtlIG1vZGFscyBvciBzcGlubmVycy9sb2FkZXJzXHJcbiAqIHNvIHRoYXQgdGhleSBhcmUgbG9jYXRlZCBvbiB0b3Agb2YgdGhlIGVsZW1lbnRzIGhpZXJhcmNoeS5cclxuICogTW9yZSBkZXRhaWxzIGFyZSB1bmRlciB0aGUgYFRoZW1lU2VydmljZWAgc2VjdGlvbi5cclxuICpcclxuICogVGhlIGxheW91dCBjb21wb25lbnQgaXMgYWxzbyByZXNwb25zaWJsZSBmb3IgY2hhbmdpbmcgYXBwbGljYXRpb24gdGhlbWVzLlxyXG4gKiBJdCBsaXN0ZW5zIHRvIHRo