ngx-rumbletalk
Version:
RumbleTalk Angular integration
252 lines • 35.7 kB
JavaScript
import { Input, Component, ViewChild, ChangeDetectionStrategy, } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "./ngx-rumbletalk.service";
import * as i2 from "@angular/common";
const protocol = 'https://';
const baseWebUrl = 'https://rumbletalk.com/';
const serviceRelativeUrl = 'client/service.php?hash=';
let server;
let messageInterval;
export class NgxRumbletalkComponent {
constructor(service) {
this.service = service;
this.floating = false;
this.side = 'right';
this.image = 'https://d1pfint8izqszg.cloudfront.net/images/toolbar/toolbar.png';
this.counter = 'false';
this.cdn = 'https://d1pfint8izqszg.cloudfront.net/';
this.counterTop = 14;
this.counterLeft = 23;
}
ngOnInit() {
const ua = navigator.userAgent.toUpperCase();
this.mobile = ua.indexOf('MOBILE') !== -1 || ua.indexOf('ANDROID') !== -1 || ua.indexOf('IOS') !== -1;
if (this.floating) {
if (!this.width) {
this.width = 700;
}
if (!this.height) {
this.height = 500;
}
if (this.side !== 'right' && this.side !== 'left') {
this.side = 'right';
}
if (this.counter !== 'false') {
const counterArr = this.counter.split(':');
const counterTop = Number(counterArr[0]);
const counterLeft = Number(counterArr[1]);
if (!isNaN(counterTop)) {
this.counterTop = counterTop;
}
if (!isNaN(counterLeft)) {
this.counterLeft = counterLeft;
}
}
}
this.loadIframe();
}
ngOnChanges(changes) {
const hashVal = changes['hash'];
if (hashVal.currentValue !== hashVal.previousValue) {
this.reload();
}
}
ngOnDestroy() {
clearInterval(messageInterval);
}
/**
* Loads the iframe
*/
loadIframe() {
this.service.address(this.hash).subscribe((address) => {
server = address;
if (!this.mobile) {
this.iframeElement.nativeElement.src = `https://${address}/${this.hash}/`;
}
this.addListeners();
});
}
/**
* add the event listeners based on the embed type and device
*/
addListeners() {
window.addEventListener('message', this.info.bind(this), false);
if (!this.mobile && this.floating) {
window.addEventListener('keyup', this.escClose.bind(this), false);
}
}
/**
* hides the chat when the "Esc" key is clicked
* @param {KeyboardEvent} event - the initiating event
*/
escClose(event) {
if (event.key === 'Escape') {
this.toggleFloatingChat(null, true);
}
}
/**
* handles postMessage requests
* @param event - the event object
*/
info(event) {
if (isFinite(event.data)) {
clearInterval(messageInterval);
if (this.counter !== 'false') {
this.counterElement.nativeElement.innerHTML = event.data.toString();
}
}
else if (typeof event.data === 'object') {
if (event.data.reload) {
this.reload();
}
}
}
/**
* reloads the iframe (or parent page) in case of a server request
*/
reload() {
const url = `${baseWebUrl}${serviceRelativeUrl}${this.hash}`;
this.service.reload(url).subscribe((res) => {
if (res.status) {
server = res.address;
const address = `${protocol}${server}/${this.hash}/`;
if (this.iframeElement.nativeElement instanceof HTMLIFrameElement) {
this.iframeElement.nativeElement.src = address;
}
else {
this.iframeElement.nativeElement.location.href = address;
}
}
}, (ignore) => { });
}
/**
* starts [repeatedly] trying to connect to the chat using postMessage
*/
instantiateQuery() {
messageInterval = setInterval(this.query.bind(this), 1000);
}
/**
* instantiate a postppMessage connection with the chat
*/
query() {
try {
let target;
let origin;
if (this.iframeElement.nativeElement instanceof HTMLIFrameElement) {
target = this.iframeElement.nativeElement.contentWindow;
origin = protocol + server;
}
else {
target = this.iframeElement.nativeElement;
origin = baseWebUrl;
}
target.postMessage('toolbar', origin);
}
catch (ignore) { }
}
/**
* checks if the given origin is of a chat service
* @param origin - the URL of the origin
* returns boolean
*/
validateOrigin(origin) {
return /^https:\/\/.+\.rumbletalk\.(net|com)(:4433)?$/.test(origin);
}
handleImageLoad(event) {
/* image element */
const target = event.target;
/* parent div */
const parent = event.currentTarget.parentNode;
/* match the dimensions of the image and the wrapping div */
parent.style.height = `${target.height}px`;
parent.style.width = `${target.width}px`;
/* place the chat div right above the image */
if (!this.mobile) {
this.chatDivElement.nativeElement.style.bottom = `${target.height}px`;
}
}
/**
* hides or shows the floating chat
* @param boolean [esc] - if set to true, will force hide
*/
toggleFloatingChat(event = null, esc = false) {
if (event) {
event.stopPropagation();
}
const chatDiv = this.chatDivElement.nativeElement;
if (chatDiv.classList.contains('chat-div-in')) {
chatDiv.classList.remove('chat-div-in');
chatDiv.classList.add('chat-div-out');
chatDiv.style.overflow = 'hidden';
}
else {
if (esc) {
return;
}
chatDiv.classList.remove('chat-div-out');
chatDiv.classList.add('chat-div-in');
chatDiv.style.overflow = 'visible';
}
}
/**
* attaches the open chat event to the given target
* @param Element target
*/
openChat() {
const link = `${baseWebUrl}client/chat.php?${this.hash}`;
let iframeInterval;
const iframe = this.iframeElement;
if (iframe) {
iframe.nativeElement.focus();
}
else {
const tempIframe = window.open(link);
iframeInterval = setInterval(() => {
if (tempIframe.closed) {
clearInterval(iframeInterval);
}
}, 100);
}
}
handleIframeLoad() {
if (this.iframeElement && this.iframeElement.nativeElement) {
this.service.iframe = this.iframeElement.nativeElement;
this.service.server = server;
this.service.handleResolve();
this.instantiateQuery();
}
}
handleIframeError() {
this.service.handleReject('Iframe could not be loaded');
}
}
NgxRumbletalkComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: NgxRumbletalkComponent, deps: [{ token: i1.NgxRumbletalkService }], target: i0.ɵɵFactoryTarget.Component });
NgxRumbletalkComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.4", type: NgxRumbletalkComponent, selector: "ngx-rumbletalk", inputs: { hash: "hash", width: "width", height: "height", floating: "floating", side: "side", image: "image", counter: "counter" }, viewQueries: [{ propertyName: "iframeElement", first: true, predicate: ["iframe"], descendants: true }, { propertyName: "chatDivElement", first: true, predicate: ["chatDiv"], descendants: true }, { propertyName: "counterElement", first: true, predicate: ["counter"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"rumbletalk-embed\" [style.width.px]=\"width\" [style.height.px]=\"height\" *ngIf=\"!floating\">\n <iframe\n #iframe\n frameBorder=\"0\"\n allow=\"microphone; camera\"\n allowtransparency=\"true\"\n (load)=\"handleIframeLoad()\"\n ></iframe>\n</div>\n\n<div\n class=\"rumbletalk-floating\"\n [ngClass]=\"'rumbletalk-floating-' + side\"\n (click)=\"mobile ? openChat() : toggleFloatingChat()\"\n *ngIf=\"floating\"\n>\n <img\n alt=\"Click to join the conversation\"\n title=\"Click to join the conversation\"\n [src]=\"image\"\n [ngClass]=\"side\"\n (load)=\"handleImageLoad($event)\"\n />\n\n <div\n #counter\n class=\"counter-div\"\n [ngStyle]=\"{ top: counterTop + 'px', left: counterLeft + 'px' }\"\n *ngIf=\"counter !== 'false'\"\n >\n <img alt=\"loading\" [src]=\"cdn + 'images/toolbar/mini_wait.gif'\" *ngIf=\"!mobile\" />\n </div>\n\n <div #chatDiv [ngClass]=\"'chat-div chat-div-out chat-div-' + side\" *ngIf=\"!mobile\">\n <img\n class=\"close-button\"\n alt=\"close\"\n [src]=\"cdn + 'images/c.png'\"\n [ngStyle]=\"side === 'right' ? { left: '-8px' } : { right: '-8px' }\"\n (click)=\"toggleFloatingChat($event)\"\n />\n\n <iframe\n #iframe\n frameBorder=\"0\"\n allow=\"microphone; camera\"\n allowtransparency=\"true\"\n [ngStyle]=\"{\n height: height ? height + 'px' : '500px',\n width: width ? width + 'px' : '700px'\n }\"\n (load)=\"handleIframeLoad()\"\n (error)=\"handleIframeError()\"\n ></iframe>\n </div>\n</div>\n", styles: [".rumbletalk-embed{overflow:hidden}iframe{overflow:hidden;background-color:transparent;height:100%;width:100%}.rumbletalk-floating{position:fixed;bottom:5px;z-index:2147483647;cursor:pointer}.rumbletalk-floating-left{left:5px}.rumbletalk-floating-right{right:5px}.rumbletalk-floating>img{max-width:none;position:absolute;bottom:0}.rumbletalk-floating>img.left{left:0}.rumbletalk-floating>img.right{right:0}.counter-div{position:absolute;width:28px;text-align:center;font:700 12px arial;color:#000;-webkit-user-select:none;user-select:none}.chat-div{position:absolute;overflow:hidden;bottom:75px;padding:0;transition:transform .1s linear;transform-style:preserve-3D}.chat-div-left{left:0;transform-origin:bottom left}.chat-div-right{right:0;transform-origin:bottom right}.chat-div-out{transform:scale(0)}.chat-div-in{transform:scale(1)}.close-button{cursor:pointer;position:absolute;top:-9px;z-index:1000}.rumbletalk-embed-image{text-align:center}.rumbletalk-embed-image img{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: NgxRumbletalkComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-rumbletalk', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"rumbletalk-embed\" [style.width.px]=\"width\" [style.height.px]=\"height\" *ngIf=\"!floating\">\n <iframe\n #iframe\n frameBorder=\"0\"\n allow=\"microphone; camera\"\n allowtransparency=\"true\"\n (load)=\"handleIframeLoad()\"\n ></iframe>\n</div>\n\n<div\n class=\"rumbletalk-floating\"\n [ngClass]=\"'rumbletalk-floating-' + side\"\n (click)=\"mobile ? openChat() : toggleFloatingChat()\"\n *ngIf=\"floating\"\n>\n <img\n alt=\"Click to join the conversation\"\n title=\"Click to join the conversation\"\n [src]=\"image\"\n [ngClass]=\"side\"\n (load)=\"handleImageLoad($event)\"\n />\n\n <div\n #counter\n class=\"counter-div\"\n [ngStyle]=\"{ top: counterTop + 'px', left: counterLeft + 'px' }\"\n *ngIf=\"counter !== 'false'\"\n >\n <img alt=\"loading\" [src]=\"cdn + 'images/toolbar/mini_wait.gif'\" *ngIf=\"!mobile\" />\n </div>\n\n <div #chatDiv [ngClass]=\"'chat-div chat-div-out chat-div-' + side\" *ngIf=\"!mobile\">\n <img\n class=\"close-button\"\n alt=\"close\"\n [src]=\"cdn + 'images/c.png'\"\n [ngStyle]=\"side === 'right' ? { left: '-8px' } : { right: '-8px' }\"\n (click)=\"toggleFloatingChat($event)\"\n />\n\n <iframe\n #iframe\n frameBorder=\"0\"\n allow=\"microphone; camera\"\n allowtransparency=\"true\"\n [ngStyle]=\"{\n height: height ? height + 'px' : '500px',\n width: width ? width + 'px' : '700px'\n }\"\n (load)=\"handleIframeLoad()\"\n (error)=\"handleIframeError()\"\n ></iframe>\n </div>\n</div>\n", styles: [".rumbletalk-embed{overflow:hidden}iframe{overflow:hidden;background-color:transparent;height:100%;width:100%}.rumbletalk-floating{position:fixed;bottom:5px;z-index:2147483647;cursor:pointer}.rumbletalk-floating-left{left:5px}.rumbletalk-floating-right{right:5px}.rumbletalk-floating>img{max-width:none;position:absolute;bottom:0}.rumbletalk-floating>img.left{left:0}.rumbletalk-floating>img.right{right:0}.counter-div{position:absolute;width:28px;text-align:center;font:700 12px arial;color:#000;-webkit-user-select:none;user-select:none}.chat-div{position:absolute;overflow:hidden;bottom:75px;padding:0;transition:transform .1s linear;transform-style:preserve-3D}.chat-div-left{left:0;transform-origin:bottom left}.chat-div-right{right:0;transform-origin:bottom right}.chat-div-out{transform:scale(0)}.chat-div-in{transform:scale(1)}.close-button{cursor:pointer;position:absolute;top:-9px;z-index:1000}.rumbletalk-embed-image{text-align:center}.rumbletalk-embed-image img{cursor:pointer}\n"] }]
}], ctorParameters: function () { return [{ type: i1.NgxRumbletalkService }]; }, propDecorators: { iframeElement: [{
type: ViewChild,
args: ['iframe']
}], chatDivElement: [{
type: ViewChild,
args: ['chatDiv']
}], counterElement: [{
type: ViewChild,
args: ['counter']
}], hash: [{
type: Input
}], width: [{
type: Input
}], height: [{
type: Input
}], floating: [{
type: Input
}], side: [{
type: Input
}], image: [{
type: Input
}], counter: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXJ1bWJsZXRhbGsuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXJ1bWJsZXRhbGsvc3JjL2xpYi9uZ3gtcnVtYmxldGFsay5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcnVtYmxldGFsay9zcmMvbGliL25neC1ydW1ibGV0YWxrLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLEVBSUwsU0FBUyxFQUNULFNBQVMsRUFHVCx1QkFBdUIsR0FDeEIsTUFBTSxlQUFlLENBQUM7Ozs7QUFHdkIsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDO0FBQzVCLE1BQU0sVUFBVSxHQUFHLHlCQUF5QixDQUFDO0FBQzdDLE1BQU0sa0JBQWtCLEdBQUcsMEJBQTBCLENBQUM7QUFDdEQsSUFBSSxNQUFjLENBQUM7QUFDbkIsSUFBSSxlQUFvQixDQUFDO0FBU3pCLE1BQU0sT0FBTyxzQkFBc0I7SUFpQmpDLFlBQW9CLE9BQTZCO1FBQTdCLFlBQU8sR0FBUCxPQUFPLENBQXNCO1FBVmpDLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFDakIsU0FBSSxHQUFHLE9BQU8sQ0FBQztRQUNmLFVBQUssR0FBRyxrRUFBa0UsQ0FBQztRQUMzRSxZQUFPLEdBQUcsT0FBTyxDQUFDO1FBR2xDLFFBQUcsR0FBRyx3Q0FBd0MsQ0FBQztRQUMvQyxlQUFVLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLGdCQUFXLEdBQUcsRUFBRSxDQUFDO0lBRW1DLENBQUM7SUFFckQsUUFBUTtRQUNOLE1BQU0sRUFBRSxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDN0MsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsU0FB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QUFLO3NCQUFwQixLQUFLO2dCQUNVLE1BQU07c0JBQXJCLEtBQUs7Z0JBQ1UsUUFBUTtzQkFBdkIsS0FBSztnQkFDVSxJQUFJO3NCQUFuQixLQUFLO2dCQUNVLEtBQUs7c0JBQXBCLEtBQUs7Z0JBQ1UsT0FBTztzQkFBdEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIElucHV0LFxuICBPbkluaXQsXG4gIE9uRGVzdHJveSxcbiAgT25DaGFuZ2VzLFxuICBDb21wb25lbnQsXG4gIFZpZXdDaGlsZCxcbiAgRWxlbWVudFJlZixcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmd4UnVtYmxldGFsa1NlcnZpY2UgfSBmcm9tICcuL25neC1ydW1ibGV0YWxrLnNlcnZpY2UnO1xuXG5jb25zdCBwcm90b2NvbCA9ICdodHRwczovLyc7XG5jb25zdCBiYXNlV2ViVXJsID0gJ2h0dHBzOi8vcnVtYmxldGFsay5jb20vJztcbmNvbnN0IHNlcnZpY2VSZWxhdGl2ZVVybCA9ICdjbGllbnQvc2VydmljZS5waHA/aGFzaD0nO1xubGV0IHNlcnZlcjogc3RyaW5nO1xubGV0IG1lc3NhZ2VJbnRlcnZhbDogYW55O1xuZGVjbGFyZSBjb25zdCB3aW5kb3c6IGFueTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LXJ1bWJsZXRhbGsnLFxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LXJ1bWJsZXRhbGsuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9uZ3gtcnVtYmxldGFsay5jb21wb25lbnQuY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBOZ3hSdW1ibGV0YWxrQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XG4gIEBWaWV3Q2hpbGQoJ2lmcmFtZScpIGlmcmFtZUVsZW1lbnQ6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGQoJ2NoYXREaXYnKSBjaGF0RGl2RWxlbWVudDogRWxlbWVudFJlZjtcbiAgQFZpZXdDaGlsZCgnY291bnRlcicpIGNvdW50ZXJFbGVtZW50OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBwdWJsaWMgaGFzaDogc3RyaW5nO1xuICBASW5wdXQoKSBwdWJsaWMgd2lkdGg6IG51bWJlcjtcbiAgQElucHV0KCkgcHVibGljIGhlaWdodDogbnVtYmVyO1xuICBASW5wdXQoKSBwdWJsaWMgZmxvYXRpbmcgPSBmYWxzZTtcbiAgQElucHV0KCkgcHVibGljIHNpZGUgPSAncmlnaHQnO1xuICBASW5wdXQoKSBwdWJsaWMgaW1hZ2UgPSAnaHR0cHM6Ly9kMXBmaW50OGl6cXN6Zy5jbG91ZGZyb250Lm5ldC9pbWFnZXMvdG9vbGJhci90b29sYmFyLnBuZyc7XG4gIEBJbnB1dCgpIHB1YmxpYyBjb3VudGVyID0gJ2ZhbHNlJztcblxuICBtb2JpbGU6IGJvb2xlYW47XG4gIGNkbiA9ICdodHRwczovL2QxcGZpbnQ4aXpxc3pnLmNsb3VkZnJvbnQubmV0Lyc7XG4gIGNvdW50ZXJUb3AgPSAxNDtcbiAgY291bnRlckxlZnQgPSAyMztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNlcnZpY2U6IE5neFJ1bWJsZXRhbGtTZXJ2aWNlKSB7fVxuXG4gIG5nT25Jbml0KCkge1xuICAgIGNvbnN0IHVhID0gbmF2aWdhdG9yLnVzZXJBZ2VudC50b1VwcGVyQ2FzZSgpO1xuICAgIHRoaXMubW9iaWxlID0gdWEuaW5kZXhPZignTU9CSUxFJykgIT09IC0xIHx8IHVhLmluZGV4T2YoJ0FORFJPSUQnKSAhPT0gLTEgfHwgdWEuaW5kZXhPZignSU9TJykgIT09IC0xO1xuXG4gICAgaWYgKHRoaXMuZmxvYXRpbmcpIHtcbiAgICAgIGlmICghdGhpcy53aWR0aCkge1xuICAgICAgICB0aGlzLndpZHRoID0gNzAwO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuaGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gNTAwO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zaWRlICE9PSAncmlnaHQnICYmIHRoaXMuc2lkZSAhPT0gJ2xlZnQnKSB7XG4gICAgICAgIHRoaXMuc2lkZSA9ICdyaWdodCc7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmNvdW50ZXIgIT09ICdmYWxzZScpIHtcbiAgICAgICAgY29uc3QgY291bnRlckFyciA9IHRoaXMuY291bnRlci5zcGxpdCgnOicpO1xuICAgICAgICBjb25zdCBjb3VudGVyVG9wID0gTnVtYmVyKGNvdW50ZXJBcnJbMF0pO1xuICAgICAgICBjb25zdCBjb3VudGVyTGVmdCA9IE51bWJlcihjb3VudGVyQXJyWzFdKTtcblxuICAgICAgICBpZiAoIWlzTmFOKGNvdW50ZXJUb3ApKSB7XG4gICAgICAgICAgdGhpcy5jb3VudGVyVG9wID0gY291bnRlclRvcDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNOYU4oY291bnRlckxlZnQpKSB7XG4gICAgICAgICAgdGhpcy5jb3VudGVyTGVmdCA9IGNvdW50ZXJMZWZ0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5sb2FkSWZyYW1lKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgY29uc3QgaGFzaFZhbCA9IGNoYW5nZXNbJ2hhc2gnXTtcblxuICAgIGlmIChoYXNoVmFsLmN1cnJlbnRWYWx1ZSAhPT0gaGFzaFZhbC5wcmV2aW91c1ZhbHVlKSB7XG4gICAgICB0aGlzLnJlbG9hZCgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGNsZWFySW50ZXJ2YWwobWVzc2FnZUludGVydmFsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgaWZyYW1lXG4gICAqL1xuICBsb2FkSWZyYW1lKCk6IHZvaWQge1xuICAgIHRoaXMuc2VydmljZS5hZGRyZXNzKHRoaXMuaGFzaCkuc3Vic2NyaWJlKChhZGRyZXNzKSA9PiB7XG4gICAgICBzZXJ2ZXIgPSBhZGRyZXNzO1xuXG4gICAgICBpZiAoIXRoaXMubW9iaWxlKSB7XG4gICAgICAgIHRoaXMuaWZyYW1lRWxlbWVudC5uYXRpdmVFbGVtZW50LnNyYyA9IGBodHRwczovLyR7YWRkcmVzc30vJHt0aGlzLmhhc2h9L2A7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuYWRkTGlzdGVuZXJzKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogYWRkIHRoZSBldmVudCBsaXN0ZW5lcnMgYmFzZWQgb24gdGhlIGVtYmVkIHR5cGUgYW5kIGRldmljZVxuICAgKi9cbiAgYWRkTGlzdGVuZXJzKCk6IHZvaWQge1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdGhpcy5pbmZvLmJpbmQodGhpcyksIGZhbHNlKTtcblxuICAgIGlmICghdGhpcy5tb2JpbGUgJiYgdGhpcy5mbG9hdGluZykge1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2tleXVwJywgdGhpcy5lc2NDbG9zZS5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIGhpZGVzIHRoZSBjaGF0IHdoZW4gdGhlIFwiRXNjXCIga2V5IGlzIGNsaWNrZWRcbiAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBldmVudCAtIHRoZSBpbml0aWF0aW5nIGV2ZW50XG4gICAqL1xuICBlc2NDbG9zZShldmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudC5rZXkgPT09ICdFc2NhcGUnKSB7XG4gICAgICB0aGlzLnRvZ2dsZUZsb2F0aW5nQ2hhdChudWxsLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogaGFuZGxlcyBwb3N0TWVzc2FnZSByZXF1ZXN0c1xuICAgKiBAcGFyYW0gZXZlbnQgLSB0aGUgZXZlbnQgb2JqZWN0XG4gICAqL1xuICBpbmZvKGV2ZW50KSB7XG4gICAgaWYgKGlzRmluaXRlKGV2ZW50LmRhdGEpKSB7XG4gICAgICBjbGVhckludGVydmFsKG1lc3NhZ2VJbnRlcnZhbCk7XG5cbiAgICAgIGlmICh0aGlzLmNvdW50ZXIgIT09ICdmYWxzZScpIHtcbiAgICAgICAgdGhpcy5jb3VudGVyRWxlbWVudC5uYXRpdmVFbGVtZW50LmlubmVySFRNTCA9IGV2ZW50LmRhdGEudG9TdHJpbmcoKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBldmVudC5kYXRhID09PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKGV2ZW50LmRhdGEucmVsb2FkKSB7XG4gICAgICAgIHRoaXMucmVsb2FkKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHJlbG9hZHMgdGhlIGlmcmFtZSAob3IgcGFyZW50IHBhZ2UpIGluIGNhc2Ugb2YgYSBzZXJ2ZXIgcmVxdWVzdFxuICAgKi9cbiAgcmVsb2FkKCkge1xuICAgIGNvbnN0IHVybCA9IGAke2Jhc2VXZWJVcmx9JHtzZXJ2aWNlUmVsYXRpdmVVcmx9JHt0aGlzLmhhc2h9YDtcblxuICAgIHRoaXMuc2VydmljZS5yZWxvYWQodXJsKS5zdWJzY3JpYmUoXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIGlmIChyZXMuc3RhdHVzKSB7XG4gICAgICAgICAgc2VydmVyID0gcmVzLmFkZHJlc3M7XG4gICAgICAgICAgY29uc3QgYWRkcmVzcyA9IGAke3Byb3RvY29sfSR7c2VydmVyfS8ke3RoaXMuaGFzaH0vYDtcblxuICAgICAgICAgIGlmICh0aGlzLmlmcmFtZUVsZW1lbnQubmF0aXZlRWxlbWVudCBpbnN0YW5jZW9mIEhUTUxJRnJhbWVFbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLmlmcmFtZUVsZW1lbnQubmF0aXZlRWxlbWVudC5zcmMgPSBhZGRyZXNzO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmlmcmFtZUVsZW1lbnQubmF0aXZlRWxlbWVudC5sb2NhdGlvbi5ocmVmID0gYWRkcmVzcztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAoaWdub3JlKSA9PiB7fVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogc3RhcnRzIFtyZXBlYXRlZGx5XSB0cnlpbmcgdG8gY29ubmVjdCB0byB0aGUgY2hhdCB1c2luZyBwb3N0TWVzc2FnZVxuICAgKi9cbiAgaW5zdGFudGlhdGVRdWVyeSgpIHtcbiAgICBtZXNzYWdlSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCh0aGlzLnF1ZXJ5LmJpbmQodGhpcyksIDEwMDApO1xuICB9XG5cbiAgLyoqXG4gICAqIGluc3RhbnRpYXRlIGEgcG9zdHBwTWVzc2FnZSBjb25uZWN0aW9uIHdpdGggdGhlIGNoYXRcbiAgICovXG4gIHF1ZXJ5KCkge1xuICAgIHRyeSB7XG4gICAgICBsZXQgdGFyZ2V0O1xuICAgICAgbGV0IG9yaWdpbjtcblxuICAgICAgaWYgKHRoaXMuaWZyYW1lRWxlbWVudC5uYXRpdmVFbGVtZW50IGluc3RhbmNlb2YgSFRNTElGcmFtZUVsZW1lbnQpIHtcbiAgICAgICAgdGFyZ2V0ID0gdGhpcy5pZnJhbWVFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuY29udGVudFdpbmRvdztcbiAgICAgICAgb3JpZ2luID0gcHJvdG9jb2wgKyBzZXJ2ZXI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0YXJnZXQgPSB0aGlzLmlmcmFtZUVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgICAgb3JpZ2luID0gYmFzZVdlYlVybDtcbiAgICAgIH1cblxuICAgICAgdGFyZ2V0LnBvc3RNZXNzYWdlKCd0b29sYmFyJywgb3JpZ2luKTtcbiAgICB9IGNhdGNoIChpZ25vcmUpIHt9XG4gIH1cblxuICAvKipcbiAgICogY2hlY2tzIGlmIHRoZSBnaXZlbiBvcmlnaW4gaXMgb2YgYSBjaGF0IHNlcnZpY2VcbiAgICogQHBhcmFtIG9yaWdpbiAtIHRoZSBVUkwgb2YgdGhlIG9yaWdpblxuICAgKiByZXR1cm5zIGJvb2xlYW5cbiAgICovXG4gIHZhbGlkYXRlT3JpZ2luKG9yaWdpbik6IGJvb2xlYW4ge1xuICAgIHJldHVybiAvXmh0dHBzOlxcL1xcLy4rXFwucnVtYmxldGFsa1xcLihuZXR8Y29tKSg6NDQzMyk/JC8udGVzdChvcmlnaW4pO1xuICB9XG5cbiAgaGFuZGxlSW1hZ2VMb2FkKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICAvKiBpbWFnZSBlbGVtZW50ICovXG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0O1xuICAgIC8qIHBhcmVudCBkaXYgKi9cbiAgICBjb25zdCBwYXJlbnQgPSBldmVudC5jdXJyZW50VGFyZ2V0LnBhcmVudE5vZGU7XG5cbiAgICAvKiBtYXRjaCB0aGUgZGltZW5zaW9ucyBvZiB0aGUgaW1hZ2UgYW5kIHRoZSB3cmFwcGluZyBkaXYgKi9cbiAgICBwYXJlbnQuc3R5bGUuaGVpZ2h0ID0gYCR7dGFyZ2V0LmhlaWdodH1weGA7XG4gICAgcGFyZW50LnN0eWxlLndpZHRoID0gYCR7dGFyZ2V0LndpZHRofXB4YDtcblxuICAgIC8qIHBsYWNlIHRoZSBjaGF0IGRpdiByaWdodCBhYm92ZSB0aGUgaW1hZ2UgKi9cbiAgICBpZiAoIXRoaXMubW9iaWxlKSB7XG4gICAgICB0aGlzLmNoYXREaXZFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUuYm90dG9tID0gYCR7dGFyZ2V0LmhlaWdodH1weGA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIGhpZGVzIG9yIHNob3dzIHRoZSBmbG9hdGluZyBjaGF0XG4gICAqIEBwYXJhbSBib29sZWFuIFtlc2NdIC0gaWYgc2V0IHRvIHRydWUsIHdpbGwgZm9yY2UgaGlkZVxuICAgKi9cbiAgdG9nZ2xlRmxvYXRpbmdDaGF0KGV2ZW50OiBhbnkgPSBudWxsLCBlc2MgPSBmYWxzZSk6IHZvaWQge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgY29uc3QgY2hhdERpdiA9IHRoaXMuY2hhdERpdkVsZW1lbnQubmF0aXZlRWxlbWVudDtcblxuICAgIGlmIChjaGF0RGl2LmNsYXNzTGlzdC5jb250YWlucygnY2hhdC1kaXYtaW4nKSkge1xuICAgICAgY2hhdERpdi5jbGFzc0xpc3QucmVtb3ZlKCdjaGF0LWRpdi1pbicpO1xuICAgICAgY2hhdERpdi5jbGFzc0xpc3QuYWRkKCdjaGF0LWRpdi1vdXQnKTtcbiAgICAgIGNoYXREaXYuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGVzYykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNoYXREaXYuY2xhc3NMaXN0LnJlbW92ZSgnY2hhdC1kaXYtb3V0Jyk7XG4gICAgICBjaGF0RGl2LmNsYXNzTGlzdC5hZGQoJ2NoYXQtZGl2LWluJyk7XG4gICAgICBjaGF0RGl2LnN0eWxlLm92ZXJmbG93ID0gJ3Zpc2libGUnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBhdHRhY2hlcyB0aGUgb3BlbiBjaGF0IGV2ZW50IHRvIHRoZSBnaXZlbiB0YXJnZXRcbiAgICogQHBhcmFtIEVsZW1lbnQgdGFyZ2V0XG4gICAqL1xuICBvcGVuQ2hhdCgpOiB2b2lkIHtcbiAgICBjb25zdCBsaW5rID0gYCR7YmFzZVdlYlVybH1jbGllbnQvY2hhdC5waHA/JHt0aGlzLmhhc2h9YDtcbiAgICBsZXQgaWZyYW1lSW50ZXJ2YWw7XG4gICAgY29uc3QgaWZyYW1lID0gdGhpcy5pZnJhbWVFbGVtZW50O1xuXG4gICAgaWYgKGlmcmFtZSkge1xuICAgICAgaWZyYW1lLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdGVtcElmcmFtZSA9IHdpbmRvdy5vcGVuKGxpbmspO1xuICAgICAgaWZyYW1lSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgIGlmICh0ZW1wSWZyYW1lLmNsb3NlZCkge1xuICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaWZyYW1lSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICB9LCAxMDApO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZUlmcmFtZUxvYWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaWZyYW1lRWxlbWVudCAmJiB0aGlzLmlmcmFtZUVsZW1lbnQubmF0aXZlRWxlbWVudCkge1xuICAgICAgdGhpcy5zZXJ2aWNlLmlmcmFtZSA9IHRoaXMuaWZyYW1lRWxlbWVudC5uYXRpdmVFbGVtZW50O1xuICAgICAgdGhpcy5zZXJ2aWNlLnNlcnZlciA9IHNlcnZlcjtcbiAgICAgIHRoaXMuc2VydmljZS5oYW5kbGVSZXNvbHZlKCk7XG4gICAgICB0aGlzLmluc3RhbnRpYXRlUXVlcnkoKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVJZnJhbWVFcnJvcigpOiB2b2lkIHtcbiAgICB0aGlzLnNlcnZpY2UuaGFuZGxlUmVqZWN0KCdJZnJhbWUgY291bGQgbm90IGJlIGxvYWRlZCcpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwicnVtYmxldGFsay1lbWJlZFwiIFtzdHlsZS53aWR0aC5weF09XCJ3aWR0aFwiIFtzdHlsZS5oZWlnaHQucHhdPVwiaGVpZ2h0XCIgKm5nSWY9XCIhZmxvYXRpbmdcIj5cbiAgPGlmcmFtZVxuICAgICNpZnJhbWVcbiAgICBmcmFtZUJvcmRlcj1cIjBcIlxuICAgIGFsbG93PVwibWljcm9waG9uZTsgY2FtZXJhXCJcbiAgICBhbGxvd3RyYW5zcGFyZW5jeT1cInRydWVcIlxuICAgIChsb2FkKT1cImhhbmRsZUlmcmFtZUxvYWQoKVwiXG4gID48L2lmcmFtZT5cbjwvZGl2PlxuXG48ZGl2XG4gIGNsYXNzPVwicnVtYmxldGFsay1mbG9hdGluZ1wiXG4gIFtuZ0NsYXNzXT1cIidydW1ibGV0YWxrLWZsb2F0aW5nLScgKyBzaWRlXCJcbiAgKGNsaWNrKT1cIm1vYmlsZSA/IG9wZW5DaGF0KCkgOiB0b2dnbGVGbG9hdGluZ0NoYXQoKVwiXG4gICpuZ0lmPVwiZmxvYXRpbmdcIlxuPlxuICA8aW1nXG4gICAgYWx0PVwiQ2xpY2sgdG8gam9pbiB0aGUgY29udmVyc2F0aW9uXCJcbiAgICB0aXRsZT1cIkNsaWNrIHRvIGpvaW4gdGhlIGNvbnZlcnNhdGlvblwiXG4gICAgW3NyY109XCJpbWFnZVwiXG4gICAgW25nQ2xhc3NdPVwic2lkZVwiXG4gICAgKGxvYWQpPVwiaGFuZGxlSW1hZ2VMb2FkKCRldmVudClcIlxuICAvPlxuXG4gIDxkaXZcbiAgICAjY291bnRlclxuICAgIGNsYXNzPVwiY291bnRlci1kaXZcIlxuICAgIFtuZ1N0eWxlXT1cInsgdG9wOiBjb3VudGVyVG9wICsgJ3B4JywgbGVmdDogY291bnRlckxlZnQgKyAncHgnIH1cIlxuICAgICpuZ0lmPVwiY291bnRlciAhPT0gJ2ZhbHNlJ1wiXG4gID5cbiAgICA8aW1nIGFsdD1cImxvYWRpbmdcIiBbc3JjXT1cImNkbiArICdpbWFnZXMvdG9vbGJhci9taW5pX3dhaXQuZ2lmJ1wiICpuZ0lmPVwiIW1vYmlsZVwiIC8+XG4gIDwvZGl2PlxuXG4gIDxkaXYgI2NoYXREaXYgW25nQ2xhc3NdPVwiJ2NoYXQtZGl2IGNoYXQtZGl2LW91dCBjaGF0LWRpdi0nICsgc2lkZVwiICpuZ0lmPVwiIW1vYmlsZVwiPlxuICAgIDxpbWdcbiAgICAgIGNsYXNzPVwiY2xvc2UtYnV0dG9uXCJcbiAgICAgIGFsdD1cImNsb3NlXCJcbiAgICAgIFtzcmNdPVwiY2RuICsgJ2ltYWdlcy9jLnBuZydcIlxuICAgICAgW25nU3R5bGVdPVwic2lkZSA9PT0gJ3JpZ2h0JyA/IHsgbGVmdDogJy04cHgnIH0gOiB7IHJpZ2h0OiAnLThweCcgfVwiXG4gICAgICAoY2xpY2spPVwidG9nZ2xlRmxvYXRpbmdDaGF0KCRldmVudClcIlxuICAgIC8+XG5cbiAgICA8aWZyYW1lXG4gICAgICAjaWZyYW1lXG4gICAgICBmcmFtZUJvcmRlcj1cIjBcIlxuICAgICAgYWxsb3c9XCJtaWNyb3Bob25lOyBjYW1lcmFcIlxuICAgICAgYWxsb3d0cmFuc3BhcmVuY3k9XCJ0cnVlXCJcbiAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgaGVpZ2h0OiBoZWlnaHQgPyBoZWlnaHQgKyAncHgnIDogJzUwMHB4JyxcbiAgICAgICAgd2lkdGg6IHdpZHRoID8gd2lkdGggKyAncHgnIDogJzcwMHB4J1xuICAgICAgfVwiXG4gICAgICAobG9hZCk9XCJoYW5kbGVJZnJhbWVMb2FkKClcIlxuICAgICAgKGVycm9yKT1cImhhbmRsZUlmcmFtZUVycm9yKClcIlxuICAgID48L2lmcmFtZT5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==