ngx-plyr-mg
Version:
Angular 9+ bindings for [plyr video and audio player](https://github.com/sampotts/plyr). Supports everything that original library supports.
236 lines • 30.3 kB
JavaScript
import { Component, ElementRef, Input, NgZone, Output, Renderer2, ViewChild } from '@angular/core';
import * as Plyr from 'plyr';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter, first, switchMap } from 'rxjs/operators';
import { DefaultPlyrDriver } from '../plyr-driver/default-plyr-driver';
import * as i0 from "@angular/core";
export class PlyrComponent {
get player() {
return this.playerChange.getValue();
}
constructor(elementRef, ngZone, renderer) {
this.elementRef = elementRef;
this.ngZone = ngZone;
this.renderer = renderer;
this.playerChange = new BehaviorSubject(null);
this.events = new Map();
this.plyrType = 'video';
// ngx-plyr events
this.plyrInit = this.playerChange.pipe(filter(player => !!player));
// standard media events
this.plyrProgress = this.createLazyEvent('progress');
this.plyrPlaying = this.createLazyEvent('playing');
this.plyrPlay = this.createLazyEvent('play');
this.plyrPause = this.createLazyEvent('pause');
this.plyrTimeUpdate = this.createLazyEvent('timeupdate');
this.plyrVolumeChange = this.createLazyEvent('volumechange');
this.plyrSeeking = this.createLazyEvent('seeking');
this.plyrSeeked = this.createLazyEvent('seeked');
this.plyrRateChange = this.createLazyEvent('ratechange');
this.plyrEnded = this.createLazyEvent('ended');
this.plyrEnterFullScreen = this.createLazyEvent('enterfullscreen');
this.plyrExitFullScreen = this.createLazyEvent('exitfullscreen');
this.plyrCaptionsEnabled = this.createLazyEvent('captionsenabled');
this.plyrCaptionsDisabled = this.createLazyEvent('captionsdisabled');
this.plyrLanguageChange = this.createLazyEvent('languagechange');
this.plyrControlsHidden = this.createLazyEvent('controlshidden');
this.plyrControlsShown = this.createLazyEvent('controlsshown');
this.plyrReady = this.createLazyEvent('ready');
// HTML5 events
this.plyrLoadStart = this.createLazyEvent('loadstart');
this.plyrLoadedData = this.createLazyEvent('loadeddata');
this.plyrLoadedMetadata = this.createLazyEvent('loadedmetadata');
this.plyrQualityChange = this.createLazyEvent('qualitychange');
this.plyrCanPlay = this.createLazyEvent('canplay');
this.plyrCanPlayThrough = this.createLazyEvent('canplaythrough');
this.plyrStalled = this.createLazyEvent('stalled');
this.plyrWaiting = this.createLazyEvent('waiting');
this.plyrEmptied = this.createLazyEvent('emptied');
this.plyrCueChange = this.createLazyEvent('cuechange');
this.plyrError = this.createLazyEvent('error');
// YouTube events
this.plyrStateChange = this.createLazyEvent('statechange');
this.subscriptions = [];
}
ngOnChanges(changes) {
this.subscriptions.push(this.plyrInit.pipe(first()).subscribe((player) => {
const reinitTriggers = [changes.plyrOptions, changes.plyrPlaysInline, changes.plyrCrossOrigin].filter(t => !!t);
if (reinitTriggers.length) {
if (reinitTriggers.some(t => !t.firstChange)) {
this.initPlyr(true);
}
}
else {
this.updatePlyrSource(player);
}
}));
}
ngOnDestroy() {
this.destroyPlayer();
this.subscriptions.forEach(s => s.unsubscribe());
}
ngAfterViewInit() {
this.initPlyr();
}
initPlyr(force = false) {
if (force || !this.player) {
this.ngZone.runOutsideAngular(() => {
this.destroyPlayer();
this.driver = this.plyrDriver || new DefaultPlyrDriver();
this.ensureVideoElement();
const newPlayer = this.driver.create({
videoElement: this.videoElement,
options: this.plyrOptions,
});
this.updatePlyrSource(newPlayer);
this.playerChange.next(newPlayer);
});
}
}
updatePlyrSource(plyr) {
this.driver.updateSource({
videoElement: this.videoElement,
plyr,
source: {
type: this.plyrType,
title: this.plyrTitle,
sources: this.plyrSources,
poster: this.plyrPoster,
tracks: this.plyrTracks,
},
});
}
// see https://stackoverflow.com/a/53704102/1990451
createLazyEvent(name) {
return this.plyrInit.pipe(switchMap(() => new Observable(observer => this.on(name, (data) => this.ngZone.run(() => observer.next(data))))));
}
destroyPlayer() {
if (this.player) {
Array.from(this.events.keys()).forEach(name => this.off(name));
this.driver.destroy({
plyr: this.player,
});
this.videoElement = null;
}
}
get hostElement() {
return this.elementRef.nativeElement;
}
// this method is required because the plyr inserts clone of the original element on destroy
// so we catch the clone element right here and reuse it
ensureVideoElement() {
const videoElement = this.hostElement.querySelector('video');
if (videoElement) {
this.videoElement = videoElement;
}
else {
this.videoElement = this.renderer.createElement('video');
this.videoElement.controls = true;
if (this.plyrCrossOrigin) {
this.videoElement.setAttribute('crossorigin', '');
}
if (this.plyrPlaysInline) {
this.videoElement.setAttribute('playsinline', '');
}
this.renderer.appendChild(this.hostElement, this.videoElement);
}
}
on(name, handler) {
this.events.set(name, handler);
this.player.on(name, handler);
}
off(name) {
this.player.off(name, this.events.get(name));
this.events.delete(name);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PlyrComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: PlyrComponent, selector: "plyr, [plyr]", inputs: { plyrDriver: "plyrDriver", plyrType: "plyrType", plyrTitle: "plyrTitle", plyrPoster: "plyrPoster", plyrSources: "plyrSources", plyrTracks: "plyrTracks", plyrOptions: "plyrOptions", plyrCrossOrigin: "plyrCrossOrigin", plyrPlaysInline: "plyrPlaysInline" }, outputs: { plyrInit: "plyrInit", plyrProgress: "plyrProgress", plyrPlaying: "plyrPlaying", plyrPlay: "plyrPlay", plyrPause: "plyrPause", plyrTimeUpdate: "plyrTimeUpdate", plyrVolumeChange: "plyrVolumeChange", plyrSeeking: "plyrSeeking", plyrSeeked: "plyrSeeked", plyrRateChange: "plyrRateChange", plyrEnded: "plyrEnded", plyrEnterFullScreen: "plyrEnterFullScreen", plyrExitFullScreen: "plyrExitFullScreen", plyrCaptionsEnabled: "plyrCaptionsEnabled", plyrCaptionsDisabled: "plyrCaptionsDisabled", plyrLanguageChange: "plyrLanguageChange", plyrControlsHidden: "plyrControlsHidden", plyrControlsShown: "plyrControlsShown", plyrReady: "plyrReady", plyrLoadStart: "plyrLoadStart", plyrLoadedData: "plyrLoadedData", plyrLoadedMetadata: "plyrLoadedMetadata", plyrQualityChange: "plyrQualityChange", plyrCanPlay: "plyrCanPlay", plyrCanPlayThrough: "plyrCanPlayThrough", plyrStalled: "plyrStalled", plyrWaiting: "plyrWaiting", plyrEmptied: "plyrEmptied", plyrCueChange: "plyrCueChange", plyrError: "plyrError", plyrStateChange: "plyrStateChange" }, viewQueries: [{ propertyName: "vr", first: true, predicate: ["v"], descendants: true }], exportAs: ["plyr"], usesOnChanges: true, ngImport: i0, template: "", styles: [""] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: PlyrComponent, decorators: [{
type: Component,
args: [{ selector: 'plyr, [plyr]', exportAs: 'plyr', template: "" }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Renderer2 }]; }, propDecorators: { plyrDriver: [{
type: Input
}], plyrType: [{
type: Input
}], plyrTitle: [{
type: Input
}], plyrPoster: [{
type: Input
}], plyrSources: [{
type: Input
}], plyrTracks: [{
type: Input
}], plyrOptions: [{
type: Input
}], plyrCrossOrigin: [{
type: Input
}], plyrPlaysInline: [{
type: Input
}], vr: [{
type: ViewChild,
args: ['v']
}], plyrInit: [{
type: Output
}], plyrProgress: [{
type: Output
}], plyrPlaying: [{
type: Output
}], plyrPlay: [{
type: Output
}], plyrPause: [{
type: Output
}], plyrTimeUpdate: [{
type: Output
}], plyrVolumeChange: [{
type: Output
}], plyrSeeking: [{
type: Output
}], plyrSeeked: [{
type: Output
}], plyrRateChange: [{
type: Output
}], plyrEnded: [{
type: Output
}], plyrEnterFullScreen: [{
type: Output
}], plyrExitFullScreen: [{
type: Output
}], plyrCaptionsEnabled: [{
type: Output
}], plyrCaptionsDisabled: [{
type: Output
}], plyrLanguageChange: [{
type: Output
}], plyrControlsHidden: [{
type: Output
}], plyrControlsShown: [{
type: Output
}], plyrReady: [{
type: Output
}], plyrLoadStart: [{
type: Output
}], plyrLoadedData: [{
type: Output
}], plyrLoadedMetadata: [{
type: Output
}], plyrQualityChange: [{
type: Output
}], plyrCanPlay: [{
type: Output
}], plyrCanPlayThrough: [{
type: Output
}], plyrStalled: [{
type: Output
}], plyrWaiting: [{
type: Output
}], plyrEmptied: [{
type: Output
}], plyrCueChange: [{
type: Output
}], plyrError: [{
type: Output
}], plyrStateChange: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx5ci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcGx5ci9zcmMvbGliL3BseXIvcGx5ci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcGx5ci9zcmMvbGliL3BseXIvcGx5ci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWlCLFNBQVMsRUFBRSxVQUFVLEVBQWdCLEtBQUssRUFBRSxNQUFNLEVBQXdCLE1BQU0sRUFBRSxTQUFTLEVBQWdCLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwSyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDakUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7O0FBU3ZFLE1BQU0sT0FBTyxhQUFhO0lBSXhCLElBQUksTUFBTTtRQUNSLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN0QyxDQUFDO0lBcUVELFlBQ1UsVUFBc0MsRUFDdEMsTUFBYyxFQUNkLFFBQW1CO1FBRm5CLGVBQVUsR0FBVixVQUFVLENBQTRCO1FBQ3RDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBNUVyQixpQkFBWSxHQUFHLElBQUksZUFBZSxDQUFPLElBQUksQ0FBQyxDQUFDO1FBTS9DLFdBQU0sR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBSWxCLGFBQVEsR0FBbUIsT0FBTyxDQUFDO1FBa0I1QyxrQkFBa0I7UUFDUixhQUFRLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJ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LFVBQVU7c0JBQW5CLE1BQU07Z0JBQ0csY0FBYztzQkFBdkIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNO2dCQUNHLG1CQUFtQjtzQkFBNUIsTUFBTTtnQkFDRyxrQkFBa0I7c0JBQTNCLE1BQU07Z0JBQ0csbUJBQW1CO3NCQUE1QixNQUFNO2dCQUNHLG9CQUFvQjtzQkFBN0IsTUFBTTtnQkFDRyxrQkFBa0I7c0JBQTNCLE1BQU07Z0JBQ0csa0JBQWtCO3NCQUEzQixNQUFNO2dCQUNHLGlCQUFpQjtzQkFBMUIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNO2dCQUdHLGFBQWE7c0JBQXRCLE1BQU07Z0JBQ0csY0FBYztzQkFBdkIsTUFBTTtnQkFDRyxrQkFBa0I7c0JBQTNCLE1BQU07Z0JBQ0csaUJBQWlCO3NCQUExQixNQUFNO2dCQUNHLFdBQVc7c0JBQXBCLE1BQU07Z0JBQ0csa0JBQWtCO3NCQUEzQixNQUFNO2dCQUNHLFdBQVc7c0JBQXBCLE1BQU07Z0JBQ0csV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxXQUFXO3NCQUFwQixNQUFNO2dCQUNHLGFBQWE7c0JBQXRCLE1BQU07Z0JBQ0csU0FBUztzQkFBbEIsTUFBTTtnQkFHRyxlQUFlO3NCQUF4QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIElucHV0LCBOZ1pvbmUsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPdXRwdXQsIFJlbmRlcmVyMiwgU2ltcGxlQ2hhbmdlLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0ICogYXMgUGx5ciBmcm9tICdwbHlyJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZmlsdGVyLCBmaXJzdCwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBEZWZhdWx0UGx5ckRyaXZlciB9IGZyb20gJy4uL3BseXItZHJpdmVyL2RlZmF1bHQtcGx5ci1kcml2ZXInO1xyXG5pbXBvcnQgeyBQbHlyRHJpdmVyIH0gZnJvbSAnLi4vcGx5ci1kcml2ZXIvcGx5ci1kcml2ZXInO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdwbHlyLCBbcGx5cl0nLCAvLyB0c2xpbnQ6ZGlzYWJsZS1saW5lXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3BseXIuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3BseXIuY29tcG9uZW50LmNzcyddLFxyXG4gIGV4cG9ydEFzOiAncGx5cidcclxufSlcclxuZXhwb3J0IGNsYXNzIFBseXJDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XHJcblxyXG4gIHByaXZhdGUgcGxheWVyQ2hhbmdlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxQbHlyPihudWxsKTtcclxuXHJcbiAgZ2V0IHBsYXllcigpOiBQbHlyIHtcclxuICAgIHJldHVybiB0aGlzLnBsYXllckNoYW5nZS5nZXRWYWx1ZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBldmVudHMgPSBuZXcgTWFwKCk7XHJcblxyXG4gIEBJbnB1dCgpIHBseXJEcml2ZXI6IFBseXJEcml2ZXI7XHJcblxyXG4gIEBJbnB1dCgpIHBseXJUeXBlOiBQbHlyLk1lZGlhVHlwZSA9ICd2aWRlbyc7XHJcblxyXG4gIEBJbnB1dCgpIHBseXJUaXRsZTogc3RyaW5nO1xyXG5cclxuICBASW5wdXQoKSBwbHlyUG9zdGVyOiBzdHJpbmc7XHJcblxyXG4gIEBJbnB1dCgpIHBseXJTb3VyY2VzOiBQbHlyLlNvdXJjZVtdO1xyXG5cclxuICBASW5wdXQoKSBwbHlyVHJhY2tzOiBQbHlyLlRyYWNrW107XHJcblxyXG4gIEBJbnB1dCgpIHBseXJPcHRpb25zOiBQbHlyLk9wdGlvbnM7XHJcblxyXG4gIEBJbnB1dCgpIHBseXJDcm9zc09yaWdpbjogYm9vbGVhbjtcclxuXHJcbiAgQElucHV0KCkgcGx5clBsYXlzSW5saW5lOiBib29sZWFuO1xyXG5cclxuICBAVmlld0NoaWxkKCd2JykgcHJpdmF0ZSB2cjogRWxlbWVudFJlZjtcclxuXHJcbiAgLy8gbmd4LXBseXIgZXZlbnRzXHJcbiAgQE91dHB1dCgpIHBseXJJbml0ID0gdGhpcy5wbGF5ZXJDaGFuZ2UucGlwZShmaWx0ZXIocGxheWVyID0+ICEhcGxheWVyKSkgYXMgRXZlbnRFbWl0dGVyPFBseXI+O1xyXG5cclxuICAvLyBzdGFuZGFyZCBtZWRpYSBldmVudHNcclxuICBAT3V0cHV0KCkgcGx5clByb2dyZXNzID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ3Byb2dyZXNzJyk7XHJcbiAgQE91dHB1dCgpIHBseXJQbGF5aW5nID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ3BsYXlpbmcnKTtcclxuICBAT3V0cHV0KCkgcGx5clBsYXkgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgncGxheScpO1xyXG4gIEBPdXRwdXQoKSBwbHlyUGF1c2UgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgncGF1c2UnKTtcclxuICBAT3V0cHV0KCkgcGx5clRpbWVVcGRhdGUgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgndGltZXVwZGF0ZScpO1xyXG4gIEBPdXRwdXQoKSBwbHlyVm9sdW1lQ2hhbmdlID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ3ZvbHVtZWNoYW5nZScpO1xyXG4gIEBPdXRwdXQoKSBwbHlyU2Vla2luZyA9IHRoaXMuY3JlYXRlTGF6eUV2ZW50KCdzZWVraW5nJyk7XHJcbiAgQE91dHB1dCgpIHBseXJTZWVrZWQgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnc2Vla2VkJyk7XHJcbiAgQE91dHB1dCgpIHBseXJSYXRlQ2hhbmdlID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ3JhdGVjaGFuZ2UnKTtcclxuICBAT3V0cHV0KCkgcGx5ckVuZGVkID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ2VuZGVkJyk7XHJcbiAgQE91dHB1dCgpIHBseXJFbnRlckZ1bGxTY3JlZW4gPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnZW50ZXJmdWxsc2NyZWVuJyk7XHJcbiAgQE91dHB1dCgpIHBseXJFeGl0RnVsbFNjcmVlbiA9IHRoaXMuY3JlYXRlTGF6eUV2ZW50KCdleGl0ZnVsbHNjcmVlbicpO1xyXG4gIEBPdXRwdXQoKSBwbHlyQ2FwdGlvbnNFbmFibGVkID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ2NhcHRpb25zZW5hYmxlZCcpO1xyXG4gIEBPdXRwdXQoKSBwbHlyQ2FwdGlvbnNEaXNhYmxlZCA9IHRoaXMuY3JlYXRlTGF6eUV2ZW50KCdjYXB0aW9uc2Rpc2FibGVkJyk7XHJcbiAgQE91dHB1dCgpIHBseXJMYW5ndWFnZUNoYW5nZSA9IHRoaXMuY3JlYXRlTGF6eUV2ZW50KCdsYW5ndWFnZWNoYW5nZScpO1xyXG4gIEBPdXRwdXQoKSBwbHlyQ29udHJvbHNIaWRkZW4gPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnY29udHJvbHNoaWRkZW4nKTtcclxuICBAT3V0cHV0KCkgcGx5ckNvbnRyb2xzU2hvd24gPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnY29udHJvbHNzaG93bicpO1xyXG4gIEBPdXRwdXQoKSBwbHlyUmVhZHkgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgncmVhZHknKTtcclxuXHJcbiAgLy8gSFRNTDUgZXZlbnRzXHJcbiAgQE91dHB1dCgpIHBseXJMb2FkU3RhcnQgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnbG9hZHN0YXJ0Jyk7XHJcbiAgQE91dHB1dCgpIHBseXJMb2FkZWREYXRhID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ2xvYWRlZGRhdGEnKTtcclxuICBAT3V0cHV0KCkgcGx5ckxvYWRlZE1ldGFkYXRhID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ2xvYWRlZG1ldGFkYXRhJyk7XHJcbiAgQE91dHB1dCgpIHBseXJRdWFsaXR5Q2hhbmdlID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ3F1YWxpdHljaGFuZ2UnKTtcclxuICBAT3V0cHV0KCkgcGx5ckNhblBsYXkgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnY2FucGxheScpO1xyXG4gIEBPdXRwdXQoKSBwbHlyQ2FuUGxheVRocm91Z2ggPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnY2FucGxheXRocm91Z2gnKTtcclxuICBAT3V0cHV0KCkgcGx5clN0YWxsZWQgPSB0aGlzLmNyZWF0ZUxhenlFdmVudCgnc3RhbGxlZCcpO1xyXG4gIEBPdXRwdXQoKSBwbHlyV2FpdGluZyA9IHRoaXMuY3JlYXRlTGF6eUV2ZW50KCd3YWl0aW5nJyk7XHJcbiAgQE91dHB1dCgpIHBseXJFbXB0aWVkID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ2VtcHRpZWQnKTtcclxuICBAT3V0cHV0KCkgcGx5ckN1ZUNoYW5nZSA9IHRoaXMuY3JlYXRlTGF6eUV2ZW50KCdjdWVjaGFuZ2UnKTtcclxuICBAT3V0cHV0KCkgcGx5ckVycm9yID0gdGhpcy5jcmVhdGVMYXp5RXZlbnQoJ2Vycm9yJyk7XHJcblxyXG4gIC8vIFlvdVR1YmUgZXZlbnRzXHJcbiAgQE91dHB1dCgpIHBseXJTdGF0ZUNoYW5nZSA9IHRoaXMuY3JlYXRlTGF6eUV2ZW50KCdzdGF0ZWNoYW5nZScpO1xyXG5cclxuICBwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XHJcblxyXG4gIHByaXZhdGUgZHJpdmVyOiBQbHlyRHJpdmVyO1xyXG5cclxuICBwcml2YXRlIHZpZGVvRWxlbWVudDogSFRNTFZpZGVvRWxlbWVudDtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+LFxyXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcclxuICAgIHByaXZhdGUgcmVuZGVyZXI6IFJlbmRlcmVyMixcclxuICApIHtcclxuICB9XHJcblxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IHsgW3AgaW4ga2V5b2YgUGx5ckNvbXBvbmVudF0/OiBTaW1wbGVDaGFuZ2U7IH0pIHtcclxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKHRoaXMucGx5ckluaXQucGlwZShmaXJzdCgpKS5zdWJzY3JpYmUoKHBsYXllcjogUGx5cikgPT4ge1xyXG4gICAgICBjb25zdCByZWluaXRUcmlnZ2VycyA9IFtjaGFuZ2VzLnBseXJPcHRpb25zLCBjaGFuZ2VzLnBseXJQbGF5c0lubGluZSwgY2hhbmdlcy5wbHlyQ3Jvc3NPcmlnaW5dLmZpbHRlcih0ID0+ICEhdCk7XHJcblxyXG4gICAgICBpZiAocmVpbml0VHJpZ2dlcnMubGVuZ3RoKSB7XHJcbiAgICAgICAgaWYgKHJlaW5pdFRyaWdnZXJzLnNvbWUodCA9PiAhdC5maXJzdENoYW5nZSkpIHtcclxuICAgICAgICAgIHRoaXMuaW5pdFBseXIodHJ1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudXBkYXRlUGx5clNvdXJjZShwbGF5ZXIpO1xyXG4gICAgICB9XHJcbiAgICB9KSk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpIHtcclxuICAgIHRoaXMuZGVzdHJveVBsYXllcigpO1xyXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2gocyA9PiBzLnVuc3Vic2NyaWJlKCkpO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgdGhpcy5pbml0UGx5cigpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpbml0UGx5cihmb3JjZSA9IGZhbHNlKSB7XHJcbiAgICBpZiAoZm9yY2UgfHwgIXRoaXMucGxheWVyKSB7XHJcbiAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgICB0aGlzLmRlc3Ryb3lQbGF5ZXIoKTtcclxuXHJcbiAgICAgICAgdGhpcy5kcml2ZXIgPSB0aGlzLnBseXJEcml2ZXIgfHwgbmV3IERlZmF1bHRQbHlyRHJpdmVyKCk7XHJcblxyXG4gICAgICAgIHRoaXMuZW5zdXJlVmlkZW9FbGVtZW50KCk7XHJcblxyXG4gICAgICAgIGNvbnN0IG5ld1BsYXllciA9IHRoaXMuZHJpdmVyLmNyZWF0ZSh7XHJcbiAgICAgICAgICB2aWRlb0VsZW1lbnQ6IHRoaXMudmlkZW9FbGVtZW50LFxyXG4gICAgICAgICAgb3B0aW9uczogdGhpcy5wbHlyT3B0aW9ucyxcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy51cGRhdGVQbHlyU291cmNlKG5ld1BsYXllcik7XHJcblxyXG4gICAgICAgIHRoaXMucGxheWVyQ2hhbmdlLm5leHQobmV3UGxheWVyKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVBseXJTb3VyY2UocGx5cjogUGx5cikge1xyXG4gICAgdGhpcy5kcml2ZXIudXBkYXRlU291cmNlKHtcclxuICAgICAgdmlkZW9FbGVtZW50OiB0aGlzLnZpZGVvRWxlbWVudCxcclxuICAgICAgcGx5cixcclxuICAgICAgc291cmNlOiB7XHJcbiAgICAgICAgdHlwZTogdGhpcy5wbHlyVHlwZSxcclxuICAgICAgICB0aXRsZTogdGhpcy5wbHlyVGl0bGUsXHJcbiAgICAgICAgc291cmNlczogdGhpcy5wbHlyU291cmNlcyxcclxuICAgICAgICBwb3N0ZXI6IHRoaXMucGx5clBvc3RlcixcclxuICAgICAgICB0cmFja3M6IHRoaXMucGx5clRyYWNrcyxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8gc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS81MzcwNDEwMi8xOTkwNDUxXHJcbiAgcHJpdmF0ZSBjcmVhdGVMYXp5RXZlbnQ8VCBleHRlbmRzIFBseXIuUGx5ckV2ZW50PihuYW1lOiBQbHlyLlN0YW5kYXJkRXZlbnQgfCBQbHlyLkh0bWw1RXZlbnQgfCBQbHlyLllvdXR1YmVFdmVudCk6IEV2ZW50RW1pdHRlcjxUPiB7XHJcbiAgICByZXR1cm4gdGhpcy5wbHlySW5pdC5waXBlKFxyXG4gICAgICBzd2l0Y2hNYXAoKCkgPT4gbmV3IE9ic2VydmFibGUob2JzZXJ2ZXIgPT4gdGhpcy5vbihuYW1lLCAoZGF0YTogVCkgPT4gdGhpcy5uZ1pvbmUucnVuKCgpID0+IG9ic2VydmVyLm5leHQoZGF0YSkpKSkpXHJcbiAgICApIGFzIEV2ZW50RW1pdHRlcjxUPjtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZGVzdHJveVBsYXllcigpIHtcclxuICAgIGlmICh0aGlzLnBsYXllcikge1xyXG4gICAgICBBcnJheS5mcm9tKHRoaXMuZXZlbnRzLmtleXMoKSkuZm9yRWFjaChuYW1lID0+IHRoaXMub2ZmKG5hbWUpKTtcclxuXHJcbiAgICAgIHRoaXMuZHJpdmVyLmRlc3Ryb3koe1xyXG4gICAgICAgIHBseXI6IHRoaXMucGxheWVyLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHRoaXMudmlkZW9FbGVtZW50ID0gbnVsbDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0IGhvc3RFbGVtZW50KCkge1xyXG4gICAgcmV0dXJuIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xyXG4gIH1cclxuXHJcbiAgLy8gdGhpcyBtZXRob2QgaXMgcmVxdWlyZWQgYmVjYXVzZSB0aGUgcGx5ciBpbnNlcnRzIGNsb25lIG9mIHRoZSBvcmlnaW5hbCBlbGVtZW50IG9uIGRlc3Ryb3lcclxuICAvLyBzbyB3ZSBjYXRjaCB0aGUgY2xvbmUgZWxlbWVudCByaWdodCBoZXJlIGFuZCByZXVzZSBpdFxyXG4gIHByaXZhdGUgZW5zdXJlVmlkZW9FbGVtZW50KCkge1xyXG4gICAgY29uc3QgdmlkZW9FbGVtZW50ID0gdGhpcy5ob3N0RWxlbWVudC5xdWVyeVNlbGVjdG9yKCd2aWRlbycpO1xyXG5cclxuICAgIGlmICh2aWRlb0VsZW1lbnQpIHtcclxuICAgICAgdGhpcy52aWRlb0VsZW1lbnQgPSB2aWRlb0VsZW1lbnQ7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnZpZGVvRWxlbWVudCA9IHRoaXMucmVuZGVyZXIuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcclxuICAgICAgdGhpcy52aWRlb0VsZW1lbnQuY29udHJvbHMgPSB0cnVlO1xyXG5cclxuICAgICAgaWYgKHRoaXMucGx5ckNyb3NzT3JpZ2luKSB7XHJcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKCdjcm9zc29yaWdpbicsICcnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHRoaXMucGx5clBsYXlzSW5saW5lKSB7XHJcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKCdwbGF5c2lubGluZScsICcnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5yZW5kZXJlci5hcHBlbmRDaGlsZCh0aGlzLmhvc3RFbGVtZW50LCB0aGlzLnZpZGVvRWxlbWVudCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIG9uKG5hbWU6IHN0cmluZywgaGFuZGxlcjogYW55KSB7XHJcbiAgICB0aGlzLmV2ZW50cy5zZXQobmFtZSwgaGFuZGxlcik7XHJcbiAgICB0aGlzLnBsYXllci5vbihuYW1lIGFzIGFueSwgaGFuZGxlcik7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIG9mZihuYW1lOiBzdHJpbmcpIHtcclxuICAgIHRoaXMucGxheWVyLm9mZihuYW1lIGFzIGFueSwgdGhpcy5ldmVudHMuZ2V0KG5hbWUpKTtcclxuICAgIHRoaXMuZXZlbnRzLmRlbGV0ZShuYW1lKTtcclxuICB9XHJcblxyXG59XHJcbiIsIiJdfQ==