UNPKG

hm-ng-video

Version:

(1)引入 npm 包,在==package.json==里面添加:

595 lines 56.5 kB
/** * @fileoverview added by tsickle * Generated from: lib/hm-ng-video.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, ViewChild, Input, ElementRef, ViewEncapsulation, EventEmitter, Output, Renderer2, } from "@angular/core"; // import videojs from "hm-videojs"; import videojs from "video.js"; export class HmNgVideoComponent { // 监听全屏 /** * @param {?} el * @param {?} renderer */ constructor(el, renderer) { this.el = el; this.renderer = renderer; this.PauseEventListener = new EventEmitter(); // 暂停回调 // 暂停回调 this.PlayingEventListener = new EventEmitter(); // 开始播放回调 // 开始播放回调 this.WaitingEventListener = new EventEmitter(); // 缓冲回调 // 缓冲回调 this.ErrorEventListener = new EventEmitter(); // 错误回调 // 错误回调 this.DataLoadedEventListener = new EventEmitter(); // 数据加载完成回调 // 数据加载完成回调 this.CanPlayEventListener = new EventEmitter(); // 可以播放回调 // 可以播放回调 this.ReLoadVideoEventListener = new EventEmitter(); // 重新加载 // 重新加载 this.FullScreenToggeleEventListener = new EventEmitter(); // 切换全屏 // 切换全屏 this.liveLoaded = false; } /** * @param {?} type * @return {?} */ createDom(type) { if (type === "file") { this.fileVideo.nativeElement.innerHTML = `<video id='${this.className}-fileVideo' class='video-js vjs-big-play-centered' controls muted preload='none' x-webkit-airplay='true' webkit-playsinline='isiPhoneShowPlaysinline' playsinline='isiPhoneShowPlaysinline' x5-playsinline='true' x5-video-player-type='h5'></video>`; } else { /** @type {?} */ const guide = `<div class='loading ${this.className}-loading'><img src='` + (this.loadingSrc || "") + `' alt='' ></div>`; /** @type {?} */ const error = `<div class='error ${this.className}-error'><span>` + (this.errorContent || "") + `</span></div>`; this.liveVideo.nativeElement.innerHTML = `<video id='${this.className}-liveVideo' class='video-js vjs-big-play-centered' controls muted preload='none' x-webkit-airplay='true' webkit-playsinline='isiPhoneShowPlaysinline' playsinline='isiPhoneShowPlaysinline' x5-playsinline='true' x5-video-player-type='h5'></video>` + guide + error; this.el.nativeElement .querySelector(`.${this.className}-error`) .addEventListener("click", (/** * @return {?} */ () => { this.setBgVisible("error", false); this.createLivePlayer(true); })); } } /** * @return {?} */ init() { this.liveLoaded = false; // 只播放其中一种就传一种类型的option if (this.fileOptions) { this.createDom("file"); /** @type {?} */ const fileVideoEl = this.el.nativeElement.querySelector(`#${this.className}-fileVideo`); this.filePlayer = videojs(fileVideoEl, Object.assign(this.fileOptions, { autoplay: this.autoplay, errorDisplay: false, controlBar: { playToggle: true, volumePanel: false, // 不需要静音按钮 pictureInPictureToggle: false, // 不需要画中画 fullscreenToggle: false, }, })); this.setDefaultProperty(this.filePlayer); this.filePlayer.on("error", (/** * @param {?} $event * @return {?} */ ($event) => { this.ErrorEventListener.emit($event); console.log("文件流出错了!"); this.dispose(this.filePlayer); this.fileOptions = null; this.createLivePlayer(true, true); })); this.filePlayer.on("playing", (/** * @param {?} $event * @return {?} */ ($event) => { this.PlayingEventListener.emit($event); if (!this.livePlayer) { this.createLivePlayer(true); // 文件流和直播流都存在的情况下,如果不是自动播放,则强行创造自动播放的直播流 } })); this.filePlayer.on("pause", (/** * @param {?} $event * @return {?} */ ($event) => { this.PauseEventListener.emit($event); })); } else { this.createLivePlayer(); // 如果没有文件流,则按照设置的是否自动播放执行 } } // 创建直播流 ,内部传就按照内部传的,不传则根据调用的决定 /** * @param {?=} isAutoPlay * @param {?=} isLoading * @return {?} */ createLivePlayer(isAutoPlay, isLoading) { if (!this.liveOptions) { return; } this.createDom("live"); if (isLoading) { this.setBgVisible("loading", true); } /** @type {?} */ const liveVideoEl = this.el.nativeElement.querySelector(`#${this.className}-liveVideo`); /** @type {?} */ let startTime = 0; /** @type {?} */ let endTime = 0; this.livePlayer = videojs(liveVideoEl, Object.assign(this.liveOptions, { autoplay: isAutoPlay ? isAutoPlay : this.autoplay, errorDisplay: false, liveui: true, controlBar: { playToggle: true, volumePanel: false, // 不需要静音按钮 pictureInPictureToggle: false, // 不需要画中画 fullscreenToggle: false, }, })); this.addFullScreen(); this.setDefaultProperty(this.livePlayer); this.livePlayer.on("loadstart", (/** * @param {?} $event * @return {?} */ ($event) => { console.log("直播流开始load"); startTime = new Date().getTime(); // this.setBgVisible("loading", true); if (!this.isVideoLoadingTimeout) { this.isVideoLoadingTimeout = setTimeout((/** * @return {?} */ () => { if (this.livePlayer && this.livePlayer.readyState() !== 3 && this.livePlayer.readyState() !== 4) { this.openModal(); this.ErrorEventListener.emit("overtime"); console.log("加载超时!"); } }), this.maxLoadTime || 15000); } })); this.livePlayer.on("loadedmetadata", (/** * @param {?} $event * @return {?} */ ($event) => { endTime = new Date().getTime(); console.log("直播流加载成功"); this.setBgVisible("loading", false); this.DataLoadedEventListener.emit(Object.assign($event, { bufferTime: endTime - startTime })); })); this.livePlayer.on("canplaythrough", (/** * @param {?} $event * @return {?} */ ($event) => { if (this.livePlayer.readyState() === 3 || this.livePlayer.readyState() === 4) { setTimeout((/** * @return {?} */ () => { if (this.filePlayer) { this.dispose(this.filePlayer); } this.liveLoaded = true; this.setBgVisible("loading", false); }), 1000); this.CanPlayEventListener.emit($event); } console.log(this.livePlayer.readyState(), "canplaythrough"); })); this.livePlayer.on("playing", (/** * @param {?} $event * @return {?} */ ($event) => { console.log("直播流正在播放!"); this.destroyTimeout(); this.setBgVisible("loading", false); this.PlayingEventListener.emit($event); })); this.livePlayer.on("error", (/** * @param {?} $event * @return {?} */ ($event) => { this.ErrorEventListener.emit($event); console.log("直播流出错了!"); this.openModal(); })); this.livePlayer.on("pause", (/** * @param {?} $event * @return {?} */ ($event) => { this.PauseEventListener.emit($event); })); this.livePlayer.on("timeupdate", (/** * @param {?} $event * @return {?} */ ($event) => { if (!this.isVideoBreak) { if (this.livePlayer.readyState() !== 3 && this.livePlayer.readyState() !== 4) { this.WaitingEventListener.emit($event); this.isVideoBreak = setTimeout((/** * @return {?} */ () => { if (this.livePlayer && this.livePlayer.readyState() !== 3 && this.livePlayer.readyState() !== 4) { this.openModal(); this.ErrorEventListener.emit("overtime"); console.log("缓冲超时!"); } }), this.maxLoadTime || 15000); } } })); } // 获取player实例 /** * @return {?} */ getFilePlayer() { return this.filePlayer || undefined; } /** * @return {?} */ getLivePlayer() { return this.livePlayer || undefined; } // 默认配置 /** * @param {?} player * @return {?} */ setDefaultProperty(player) { player.playsinline(true); //player.crossOrigin("anonymous"); } // 销毁 /** * @param {?} player * @return {?} */ dispose(player) { if (!player) { return; } if (!player.isDisposed()) { player.dispose(); player = undefined; } } // 销毁定时器 /** * @return {?} */ destroyTimeout() { clearTimeout(this.isVideoBreak); clearTimeout(this.isVideoLoadingTimeout); clearInterval(this.fullScreenTimer); this.isVideoBreak = undefined; this.isVideoLoadingTimeout = undefined; this.fullScreenTimer = undefined; } // 全部销毁 /** * @return {?} */ destroy() { this.destroyTimeout(); this.dispose(this.filePlayer); this.dispose(this.livePlayer); } // 绑定错误事件 // 自定义错误显示方式 // 0,1,2,3,4,5 // MEDIA_ERR_CUSTOM、 // MEDIA_ERR_ABORTED、取回过程被用户中止 // MEDIA_ERR_NETWORK、当下载时发生错误 // MEDIA_ERR_DECODE、当解码时发生错误 // MEDIA_ERR_SRC_NOT_SUPPORTED、不支持音频/视频 // MEDIA_ERR_ENCRYPTED // 被加密 // 错误弹窗 /** * @return {?} */ openModal() { this.fileOptions = null; this.destroy(); this.setBgVisible("loading", false); this.setBgVisible("error", true); } // 设置加载背景/错误背景显示隐藏 /** * @param {?} type * @param {?} isShow * @return {?} */ setBgVisible(type, isShow) { /** @type {?} */ const el = type === "loading" ? this.el.nativeElement.querySelector(`.${this.className}-loading`) : this.el.nativeElement.querySelector(`.${this.className}-error`); this.renderer.setStyle(el, "display", isShow ? "block" : "none"); } // 判断是ios设备 /** * @return {?} */ isIOS() { /** @type {?} */ const u = navigator.userAgent; /** @type {?} */ const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); console.log("ios", isIOS); return isIOS; } // 添加自定义全屏和播放按钮 /** * @return {?} */ addFullScreen() { /** @type {?} */ const vjsButtonComponent = videojs.getComponent("Button"); videojs.registerComponent("FullScreenButton", videojs.extend(vjsButtonComponent, { handleClick: (/** * @return {?} */ () => { if (!this.livePlayer.isFullscreen()) { try { this.toFullScreen(); if (this.isIOS()) { this.fullScreenTimer = setInterval((/** * @return {?} */ () => { if (!this.livePlayer.isFullscreen()) { // 退出了全屏 this.FullScreenToggeleEventListener.emit(false); this.destroy(); this.createLivePlayer(true); // clearInterval(this.fullScreenTimer); // setTimeout(() => { // this.livePlayer.play(); // }, 1000); } }), 1000); } } catch (error) { console.warn(error); } } else { this.FullScreenToggeleEventListener.emit(false); this.livePlayer.exitFullscreen(); } }), buildCSSClass: (/** * @return {?} */ () => { return "my_fullscreen"; }), })); this.livePlayer.getChild("controlBar").addChild("FullScreenButton", {}); } // 自定义全屏 /** * @return {?} */ toFullScreen() { this.FullScreenToggeleEventListener.emit(true); if (this.livePlayer.requestFullscreen) { return this.livePlayer.requestFullscreen(); } else if (this.livePlayer.webkitRequestFullScreen) { return this.livePlayer.webkitRequestFullScreen(); } else if (this.livePlayer.mozRequestFullScreen) { return this.livePlayer.mozRequestFullScreen(); } else { return this.livePlayer.msRequestFullscreen(); } } /** * @return {?} */ ngOnInit() { console.log("hm-ng-video 1.5.6"); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (this.exitFullScreen) { console.log("按返回键退出全屏"); this.FullScreenToggeleEventListener.emit(false); this.livePlayer.exitFullscreen(); } if ((changes.fileOptions && changes.fileOptions.firstChange && changes.fileOptions.currentValue) || (changes.liveOptions && changes.liveOptions.firstChange && changes.liveOptions.currentValue)) { this.init(); } if ((changes.fileOptions && changes.fileOptions.currentValue && !changes.fileOptions.firstChange) || (changes.liveOptions && changes.liveOptions.currentValue && !changes.liveOptions.firstChange)) { this.destroy(); setTimeout((/** * @return {?} */ () => { this.init(); }), 1000); } } /** * @return {?} */ ngOnDestroy() { this.destroy(); } } HmNgVideoComponent.decorators = [ { type: Component, args: [{ selector: "hm-ng-video", template: "<!--\r\n * @Descripttion:\r\n * @version:\r\n * @Author: yding\r\n * @Date: 2020-05-08 19:05:06\r\n * @LastEditors: yding\r\n * @LastEditTime: 2020-06-19 10:44:58\r\n-->\r\n<!-- <button\r\n class=\"button\"\r\n style=\"background: red;\"\r\n (click)=\"fullScreen()\"\r\n value=\"\u5168\u5C4F\"\r\n>\r\n \u5168\u5C4F\r\n</button> -->\r\n<div\r\n class=\"vjs-video\"\r\n #fileVideoEl\r\n [ngStyle]=\"{\r\n height: videoHeight + 'px',\r\n width: videoWidth + 'px',\r\n position: 'relative'\r\n }\"\r\n [hidden]=\"(liveLoaded && liveOptions && fileOptions) || !fileOptions\"\r\n></div>\r\n<div\r\n class=\"vjs-video\"\r\n #liveVideoEl\r\n [ngStyle]=\"{\r\n height: videoHeight + 'px',\r\n width: videoWidth + 'px',\r\n position: 'relative'\r\n }\"\r\n [hidden]=\"(!liveLoaded && liveOptions && fileOptions) || !liveOptions\"\r\n></div>\r\n", encapsulation: ViewEncapsulation.None, styles: [".video-js{width:100%;height:100%}.retry:focus,.vjs-big-play-button:focus,video:focus{outline:0}.vjs-paused .vjs-big-play-button,.vjs-paused.vjs-has-started .vjs-big-play-button{display:none}.video-js .vjs-big-play-button{font-size:2.5em;line-height:2.3em;height:2.5em;width:2.5em;border-radius:2.5em;background-color:rgba(115,133,159,.5);border-width:.15em;margin-top:-1.25em;margin-left:-1.75em}.vjs-big-play-button .vjs-icon-placeholder{font-size:1.63em}.vjs-progress-control.vjs-control,.vjs-remaining-time.vjs-time-control.vjs-control{display:none}.vjs-loading-spinner{border:none;visibility:visible;border-radius:0}.vjs-waiting .vjs-loading-spinner{-webkit-animation:none!important;animation:none!important}.video-js .vjs-control.vjs-close-button{display:none}.loading{width:100%;height:100%;top:0;left:0;position:absolute;pointer-events:none;z-index:71;background:#000;display:none}.loading img{width:35px;height:35px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.error{width:100%;height:100%;top:0;left:0;position:absolute;background:#000;cursor:pointer;z-index:70;display:none}.error span{display:block;text-align:center;padding-top:30%;color:#fff}.vjs-control-bar>button.my_fullscreen::before{display:block!important;content:\"\u5168\u5C4F/\u9000\u51FA\";cursor:pointer}"] }] } ]; /** @nocollapse */ HmNgVideoComponent.ctorParameters = () => [ { type: ElementRef }, { type: Renderer2 } ]; HmNgVideoComponent.propDecorators = { fileVideo: [{ type: ViewChild, args: ["fileVideoEl",] }], liveVideo: [{ type: ViewChild, args: ["liveVideoEl",] }], fileOptions: [{ type: Input }], liveOptions: [{ type: Input }], autoplay: [{ type: Input }], videoHeight: [{ type: Input }], videoWidth: [{ type: Input }], className: [{ type: Input }], loadingSrc: [{ type: Input }], maxReloadTimes: [{ type: Input }], errorContent: [{ type: Input }], maxLoadTime: [{ type: Input }], exitFullScreen: [{ type: Input }], PauseEventListener: [{ type: Output }], PlayingEventListener: [{ type: Output }], WaitingEventListener: [{ type: Output }], ErrorEventListener: [{ type: Output }], DataLoadedEventListener: [{ type: Output }], CanPlayEventListener: [{ type: Output }], ReLoadVideoEventListener: [{ type: Output }], FullScreenToggeleEventListener: [{ type: Output }] }; if (false) { /** @type {?} */ HmNgVideoComponent.prototype.fileVideo; /** @type {?} */ HmNgVideoComponent.prototype.liveVideo; /** @type {?} */ HmNgVideoComponent.prototype.fileOptions; /** @type {?} */ HmNgVideoComponent.prototype.liveOptions; /** @type {?} */ HmNgVideoComponent.prototype.autoplay; /** @type {?} */ HmNgVideoComponent.prototype.videoHeight; /** @type {?} */ HmNgVideoComponent.prototype.videoWidth; /** @type {?} */ HmNgVideoComponent.prototype.className; /** @type {?} */ HmNgVideoComponent.prototype.loadingSrc; /** @type {?} */ HmNgVideoComponent.prototype.maxReloadTimes; /** @type {?} */ HmNgVideoComponent.prototype.errorContent; /** @type {?} */ HmNgVideoComponent.prototype.maxLoadTime; /** @type {?} */ HmNgVideoComponent.prototype.exitFullScreen; /** @type {?} */ HmNgVideoComponent.prototype.PauseEventListener; /** @type {?} */ HmNgVideoComponent.prototype.PlayingEventListener; /** @type {?} */ HmNgVideoComponent.prototype.WaitingEventListener; /** @type {?} */ HmNgVideoComponent.prototype.ErrorEventListener; /** @type {?} */ HmNgVideoComponent.prototype.DataLoadedEventListener; /** @type {?} */ HmNgVideoComponent.prototype.CanPlayEventListener; /** @type {?} */ HmNgVideoComponent.prototype.ReLoadVideoEventListener; /** @type {?} */ HmNgVideoComponent.prototype.FullScreenToggeleEventListener; /** @type {?} */ HmNgVideoComponent.prototype.liveLoaded; /** * @type {?} * @private */ HmNgVideoComponent.prototype.filePlayer; /** * @type {?} * @private */ HmNgVideoComponent.prototype.livePlayer; /** * @type {?} * @private */ HmNgVideoComponent.prototype.isVideoBreak; /** * @type {?} * @private */ HmNgVideoComponent.prototype.isVideoLoadingTimeout; /** * @type {?} * @private */ HmNgVideoComponent.prototype.fullScreenTimer; /** * @type {?} * @private */ HmNgVideoComponent.prototype.el; /** @type {?} */ HmNgVideoComponent.prototype.renderer; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG0tbmctdmlkZW8uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vaG0tbmctdmlkZW8vIiwic291cmNlcyI6WyJsaWIvaG0tbmctdmlkZW8uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFFVCxTQUFTLEVBQ1QsS0FBSyxFQUNMLFVBQVUsRUFDVixpQkFBaUIsRUFFakIsWUFBWSxFQUNaLE1BQU0sRUFHTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7O0FBRXZCLE9BQU8sT0FBTyxNQUFNLFVBQVUsQ0FBQztBQU8vQixNQUFNLE9BQU8sa0JBQWtCOzs7Ozs7SUFtRDdCLFlBQW9CLEVBQWMsRUFBUyxRQUFtQjtRQUExQyxPQUFFLEdBQUYsRUFBRSxDQUFZO1FBQVMsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQWxCcEQsdUJBQWtCLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQyxDQUFDLE9BQU87O1FBQ3hELHlCQUFvQixHQUFHLElBQUksWUFBWSxFQUFVLENBQUMsQ0FBQyxTQUFTOztRQUM1RCx5QkFBb0IsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDLENBQUMsT0FBTzs7UUFDMUQsdUJBQWtCLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQyxDQUFDLE9BQU87O1FBQ3hELDRCQUF1QixHQUFHLElBQUksWUFBWSxFQUFVLENBQUMsQ0FBQyxXQUFXOztRQUNqRSx5QkFBb0IsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDLENBQUMsU0FBUzs7UUFDNUQsNkJBQXdCLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQyxDQUFDLE9BQU87O1FBRTlELG1DQUE4QixHQUFHLElBQUksWUFBWSxFQUFXLENBQUMsQ0FBQyxPQUFPOztRQUV4RSxlQUFVLEdBQUcsS0FBSyxDQUFDO0lBUXVDLENBQUM7Ozs7O0lBRTNELFNBQVMsQ0FBQyxJQUFxQjtRQUNwQyxJQUFJLElBQUksS0FBSyxNQUFNLEVBQUU7WUFDbkIsSUFB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QUM3Qix3Q0FBNEI7O0lBQzVCLHVDQUEyQjs7SUFDM0Isd0NBQTRCOztJQUM1Qiw0Q0FBaUM7O0lBQ2pDLDBDQUErQjs7SUFDL0IseUNBQThCOztJQUU5Qiw0Q0FBa0M7O0lBRWxDLGdEQUEwRDs7SUFDMUQsa0RBQTREOztJQUM1RCxrREFBNEQ7O0lBQzVELGdEQUEwRDs7SUFDMUQscURBQStEOztJQUMvRCxrREFBNEQ7O0lBQzVELHNEQUFnRTs7SUFFaEUsNERBQXVFOztJQUV2RSx3Q0FBMEI7Ozs7O0lBQzFCLHdDQUFtQzs7Ozs7SUFDbkMsd0NBQW1DOzs7OztJQUNuQywwQ0FBMEI7Ozs7O0lBQzFCLG1EQUFtQzs7Ozs7SUFFbkMsNkNBQTZCOzs7OztJQUVqQixnQ0FBc0I7O0lBQUUsc0NBQTBCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBPbkluaXQsXG4gIFZpZXdDaGlsZCxcbiAgSW5wdXQsXG4gIEVsZW1lbnRSZWYsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxuICBPbkRlc3Ryb3ksXG4gIEV2ZW50RW1pdHRlcixcbiAgT3V0cHV0LFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFJlbmRlcmVyMixcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbi8vIGltcG9ydCB2aWRlb2pzIGZyb20gXCJobS12aWRlb2pzXCI7XG5pbXBvcnQgdmlkZW9qcyBmcm9tIFwidmlkZW8uanNcIjtcbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJobS1uZy12aWRlb1wiLFxuICB0ZW1wbGF0ZVVybDogXCIuL2htLW5nLXZpZGVvLmNvbXBvbmVudC5odG1sXCIsXG4gIHN0eWxlVXJsczogW1wiLi9obS1uZy12aWRlby5jb21wb25lbnQuY3NzXCJdLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxufSlcbmV4cG9ydCBjbGFzcyBIbU5nVmlkZW9Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzIHtcbiAgQFZpZXdDaGlsZChcImZpbGVWaWRlb0VsXCIpIGZpbGVWaWRlbzogRWxlbWVudFJlZjtcbiAgQFZpZXdDaGlsZChcImxpdmVWaWRlb0VsXCIpIGxpdmVWaWRlbzogRWxlbWVudFJlZjtcbiAgQElucHV0KCkgZmlsZU9wdGlvbnM/OiB7XG4gICAgbG9vcDogYm9vbGVhbjtcbiAgICBjb250cm9sczogYm9vbGVhbjtcbiAgICBwb3N0ZXI6IHN0cmluZztcbiAgICBwcmVsb2FkOiBcImF1dG9cIiB8IFwibWV0YWRhdGFcIiB8IFwibm9uZVwiO1xuICAgIHNvdXJjZXM6IHtcbiAgICAgIHNyYzogc3RyaW5nO1xuICAgICAgdHlwZTogc3RyaW5nO1xuICAgIH1bXTtcbiAgfTtcbiAgQElucHV0KCkgbGl2ZU9wdGlvbnM/OiB7XG4gICAgY29udHJvbHM6IGJvb2xlYW47XG4gICAgcG9zdGVyOiBzdHJpbmc7XG4gICAgcHJlbG9hZDogXCJhdXRvXCIgfCBcIm1ldGFkYXRhXCIgfCBcIm5vbmVcIjtcbiAgICBzb3VyY2VzOiB7XG4gICAgICBzcmM6IHN0cmluZztcbiAgICAgIHR5cGU6IHN0cmluZztcbiAgICB9W107XG4gIH07XG4gIEBJbnB1dCgpIGF1dG9wbGF5OiBib29sZWFuO1xuICBASW5wdXQoKSB2aWRlb0hlaWdodDogbnVtYmVyO1xuICBASW5wdXQoKSB2aWRlb1dpZHRoOiBudW1iZXI7XG4gIEBJbnB1dCgpIGNsYXNzTmFtZTogc3RyaW5nO1xuICBASW5wdXQoKSBsb2FkaW5nU3JjOiBzdHJpbmc7XG4gIEBJbnB1dCgpIG1heFJlbG9hZFRpbWVzPzogbnVtYmVyO1xuICBASW5wdXQoKSBlcnJvckNvbnRlbnQ/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIG1heExvYWRUaW1lPzogbnVtYmVyO1xuXG4gIEBJbnB1dCgpIGV4aXRGdWxsU2NyZWVuPzogYm9vbGVhbjtcblxuICBAT3V0cHV0KCkgUGF1c2VFdmVudExpc3RlbmVyID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7IC8vIOaaguWBnOWbnuiwg1xuICBAT3V0cHV0KCkgUGxheWluZ0V2ZW50TGlzdGVuZXIgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTsgLy8g5byA5aeL5pKt5pS+5Zue6LCDXG4gIEBPdXRwdXQoKSBXYWl0aW5nRXZlbnRMaXN0ZW5lciA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpOyAvLyDnvJPlhrLlm57osINcbiAgQE91dHB1dCgpIEVycm9yRXZlbnRMaXN0ZW5lciA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpOyAvLyDplJnor6/lm57osINcbiAgQE91dHB1dCgpIERhdGFMb2FkZWRFdmVudExpc3RlbmVyID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7IC8vIOaVsOaNruWKoOi9veWujOaIkOWbnuiwg1xuICBAT3V0cHV0KCkgQ2FuUGxheUV2ZW50TGlzdGVuZXIgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTsgLy8g5Y+v5Lul5pKt5pS+5Zue6LCDXG4gIEBPdXRwdXQoKSBSZUxvYWRWaWRlb0V2ZW50TGlzdGVuZXIgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTsgLy8g6YeN5paw5Yqg6L29XG5cbiAgQE91dHB1dCgpIEZ1bGxTY3JlZW5Ub2dnZWxlRXZlbnRMaXN0ZW5lciA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTsgLy8g5YiH5o2i5YWo5bGPXG5cbiAgcHVibGljIGxpdmVMb2FkZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBmaWxlUGxheWVyOiB2aWRlb2pzLlBsYXllcjtcbiAgcHJpdmF0ZSBsaXZlUGxheWVyOiB2aWRlb2pzLlBsYXllcjtcbiAgcHJpdmF0ZSBpc1ZpZGVvQnJlYWs6IGFueTtcbiAgcHJpdmF0ZSBpc1ZpZGVvTG9hZGluZ1RpbWVvdXQ6IGFueTtcblxuICBwcml2YXRlIGZ1bGxTY3JlZW5UaW1lcjogYW55OyAvLyDnm5HlkKzlhajlsY9cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsOiBFbGVtZW50UmVmLCBwdWJsaWMgcmVuZGVyZXI6IFJlbmRlcmVyMikge31cblxuICBwdWJsaWMgY3JlYXRlRG9tKHR5cGU6IFwiZmlsZVwiIHwgXCJsaXZlXCIpIHtcbiAgICBpZiAodHlwZSA9PT0gXCJmaWxlXCIpIHtcbiAgICAgIHRoaXMuZmlsZVZpZGVvLm5hdGl2ZUVsZW1lbnQuaW5uZXJIVE1MID0gYDx2aWRlbyBpZD0nJHt0aGlzLmNsYXNzTmFtZX0tZmlsZVZpZGVvJyBjbGFzcz0ndmlkZW8tanMgdmpzLWJpZy1wbGF5LWNlbnRlcmVkJyAgY29udHJvbHMgbXV0ZWQgcHJlbG9hZD0nbm9uZScgeC13ZWJraXQtYWlycGxheT0ndHJ1ZScgd2Via2l0LXBsYXlzaW5saW5lPSdpc2lQaG9uZVNob3dQbGF5c2lubGluZScgcGxheXNpbmxpbmU9J2lzaVBob25lU2hvd1BsYXlzaW5saW5lJyB4NS1wbGF5c2lubGluZT0ndHJ1ZScgeDUtdmlkZW8tcGxheWVyLXR5cGU9J2g1Jz48L3ZpZGVvPmA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGd1aWRlID1cbiAgICAgICAgYDxkaXYgY2xhc3M9J2xvYWRpbmcgJHt0aGlzLmNsYXNzTmFtZX0tbG9hZGluZyc+PGltZyBzcmM9J2AgK1xuICAgICAgICAodGhpcy5sb2FkaW5nU3JjIHx8IFwiXCIpICtcbiAgICAgICAgYCcgYWx0PScnID48L2Rpdj5gO1xuICAgICAgY29uc3QgZXJyb3IgPVxuICAgICAgICBgPGRpdiBjbGFzcz0nZXJyb3IgJHt0aGlzLmNsYXNzTmFtZX0tZXJyb3InPjxzcGFuPmAgK1xuICAgICAgICAodGhpcy5lcnJvckNvbnRlbnQgfHwgXCJcIikgK1xuICAgICAgICBgPC9zcGFuPjwvZGl2PmA7XG4gICAgICB0aGlzLmxpdmVWaWRlby5uYXRpdmVFbGVtZW50LmlubmVySFRNTCA9XG4gICAgICAgIGA8dmlkZW8gaWQ9JyR7dGhpcy5jbGFzc05hbWV9LWxpdmVWaWRlbycgY2xhc3M9J3ZpZGVvLWpzIHZqcy1iaWctcGxheS1jZW50ZXJlZCcgIGNvbnRyb2xzIG11dGVkIHByZWxvYWQ9J25vbmUnIHgtd2Via2l0LWFpcnBsYXk9J3RydWUnIHdlYmtpdC1wbGF5c2lubGluZT0naXNpUGhvbmVTaG93UGxheXNpbmxpbmUnIHBsYXlzaW5saW5lPSdpc2lQaG9uZVNob3dQbGF5c2lubGluZScgeDUtcGxheXNpbmxpbmU9J3RydWUnIHg1LXZpZGVvLXBsYXllci10eXBlPSdoNSc+PC92aWRlbz5gICtcbiAgICAgICAgZ3VpZGUgK1xuICAgICAgICBlcnJvcjtcbiAgICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudFxuICAgICAgICAucXVlcnlTZWxlY3RvcihgLiR7dGhpcy5jbGFzc05hbWV9LWVycm9yYClcbiAgICAgICAgLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5zZXRCZ1Zpc2libGUoXCJlcnJvclwiLCBmYWxzZSk7XG4gICAgICAgICAgdGhpcy5jcmVhdGVMaXZlUGxheWVyKHRydWUpO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH1cbiAgcHVibGljIGluaXQoKSB7XG4gICAgdGhpcy5saXZlTG9hZGVkID0gZmFsc2U7XG4gICAgLy8g5Y+q5pKt5pS+5YW25Lit5LiA56eN5bCx5Lyg5LiA56eN57G75Z6L55qEb3B0aW9uXG4gICAgaWYgKHRoaXMuZmlsZU9wdGlvbnMpIHtcbiAgICAgIHRoaXMuY3JlYXRlRG9tKFwiZmlsZVwiKTtcbiAgICAgIGNvbnN0IGZpbGVWaWRlb0VsID0gdGhpcy5lbC5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoXG4gICAgICAgIGAjJHt0aGlzLmNsYXNzTmFtZX0tZmlsZVZpZGVvYFxuICAgICAgKTtcbiAgICAgIHRoaXMuZmlsZVBsYXllciA9IHZpZGVvanMoXG4gICAgICAgIGZpbGVWaWRlb0VsLFxuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMuZmlsZU9wdGlvbnMsIHtcbiAgICAgICAgICBhdXRvcGxheTogdGhpcy5hdXRvcGxheSxcbiAgICAgICAgICBlcnJvckRpc3BsYXk6IGZhbHNlLFxuICAgICAgICAgIGNvbnRyb2xCYXI6IHtcbiAgICAgICAgICAgIHBsYXlUb2dnbGU6IHRydWUsXG4gICAgICAgICAgICB2b2x1bWVQYW5lbDogZmFsc2UsIC8vIOS4jemcgOimgemdmemfs+aMiemSrlxuICAgICAgICAgICAgcGljdHVyZUluUGljdHVyZVRvZ2dsZTogZmFsc2UsIC8vIOS4jemcgOimgeeUu+S4reeUu1xuICAgICAgICAgICAgZnVsbHNjcmVlblRvZ2dsZTogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICAgIHRoaXMuc2V0RGVmYXVsdFByb3BlcnR5KHRoaXMuZmlsZVBsYXllcik7XG4gICAgICB0aGlzLmZpbGVQbGF5ZXIub24oXCJlcnJvclwiLCAoJGV2ZW50KSA9PiB7XG4gICAgICAgIHRoaXMuRXJyb3JFdmVudExpc3RlbmVyLmVtaXQoJGV2ZW50KTtcbiAgICAgICAgY29uc29sZS5sb2coXCLmlofku7bmtYHlh7rplJnkuobvvIFcIik7XG4gICAgICAgIHRoaXMuZGlzcG9zZSh0aGlzLmZpbGVQbGF5ZXIpO1xuICAgICAgICB0aGlzLmZpbGVPcHRpb25zID0gbnVsbDtcbiAgICAgICAgdGhpcy5jcmVhdGVMaXZlUGxheWVyKHRydWUsIHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuZmlsZVBsYXllci5vbihcInBsYXlpbmdcIiwgKCRldmVudCkgPT4ge1xuICAgICAgICB0aGlzLlBsYXlpbmdFdmVudExpc3RlbmVyLmVtaXQoJGV2ZW50KTtcbiAgICAgICAgaWYgKCF0aGlzLmxpdmVQbGF5ZXIpIHtcbiAgICAgICAgICB0aGlzLmNyZWF0ZUxpdmVQbGF5ZXIodHJ1ZSk7IC8vIOaWh+S7tua1geWSjOebtOaSrea1gemDveWtmOWcqOeahOaDheWGteS4i++8jOWmguaenOS4jeaYr+iHquWKqOaSreaUvu+8jOWImeW8uuihjOWIm+mAoOiHquWKqOaSreaUvueahOebtOaSrea1gVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuZmlsZVBsYXllci5vbihcInBhdXNlXCIsICgkZXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy5QYXVzZUV2ZW50TGlzdGVuZXIuZW1pdCgkZXZlbnQpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY3JlYXRlTGl2ZVBsYXllcigpOyAvLyDlpoLmnpzmsqHmnInmlofku7bmtYHvvIzliJnmjInnhaforr7nva7nmoTmmK/lkKboh6rliqjmkq3mlL7miafooYxcbiAgICB9XG4gIH1cblxuICAvLyDliJvlu7rnm7Tmkq3mtYEgLOWGhemDqOS8oOWwseaMieeFp+WGhemDqOS8oOeahO+8jOS4jeS8oOWImeagueaNruiwg+eUqOeahOWGs+WumlxuICBwdWJsaWMgY3JlYXRlTGl2ZVBsYXllcihpc0F1dG9QbGF5PywgaXNMb2FkaW5nPykge1xuICAgIGlmICghdGhpcy5saXZlT3B0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmNyZWF0ZURvbShcImxpdmVcIik7XG4gICAgaWYgKGlzTG9hZGluZykge1xuICAgICAgdGhpcy5zZXRCZ1Zpc2libGUoXCJsb2FkaW5nXCIsIHRydWUpO1xuICAgIH1cbiAgICBjb25zdCBsaXZlVmlkZW9FbCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFxuICAgICAgYCMke3RoaXMuY2xhc3NOYW1lfS1saXZlVmlkZW9gXG4gICAgKTtcbiAgICBsZXQgc3RhcnRUaW1lID0gMCxcbiAgICAgIGVuZFRpbWUgPSAwO1xuICAgIHRoaXMubGl2ZVBsYXllciA9IHZpZGVvanMoXG4gICAgICBsaXZlVmlkZW9FbCxcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5saXZlT3B0aW9ucywge1xuICAgICAgICBhdXRvcGxheTogaXNBdXRvUGxheSA/IGlzQXV0b1BsYXkgOiB0aGlzLmF1dG9wbGF5LFxuICAgICAgICBlcnJvckRpc3BsYXk6IGZhbHNlLFxuICAgICAgICBsaXZldWk6IHRydWUsXG4gICAgICAgIGNvbnRyb2xCYXI6IHtcbiAgICAgICAgICBwbGF5VG9nZ2xlOiB0cnVlLFxuICAgICAgICAgIHZvbHVtZVBhbmVsOiBmYWxzZSwgLy8g5LiN6ZyA6KaB6Z2Z6Z+z5oyJ6ZKuXG4gICAgICAgICAgcGljdHVyZUluUGljdHVyZVRvZ2dsZTogZmFsc2UsIC8vIOS4jemcgOimgeeUu+S4reeUu1xuICAgICAgICAgIGZ1bGxzY3JlZW5Ub2dnbGU6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgfSlcbiAgICApO1xuICAgIHRoaXMuYWRkRnVsbFNjcmVlbigpO1xuICAgIHRoaXMuc2V0RGVmYXVsdFByb3BlcnR5KHRoaXMubGl2ZVBsYXllcik7XG4gICAgdGhpcy5saXZlUGxheWVyLm9uKFwibG9hZHN0YXJ0XCIsICgkZXZlbnQpID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKFwi55u05pKt5rWB5byA5aeLbG9hZFwiKTtcbiAgICAgIHN0YXJ0VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgLy8gdGhpcy5zZXRCZ1Zpc2libGUoXCJsb2FkaW5nXCIsIHRydWUpO1xuICAgICAgaWYgKCF0aGlzLmlzVmlkZW9Mb2FkaW5nVGltZW91dCkge1xuICAgICAgICB0aGlzLmlzVmlkZW9Mb2FkaW5nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMubGl2ZVBsYXllciAmJlxuICAgICAgICAgICAgdGhpcy5saXZlUGxheWVyLnJlYWR5U3RhdGUoKSAhPT0gMyAmJlxuICAgICAgICAgICAgdGhpcy5saXZlUGxheWVyLnJlYWR5U3RhdGUoKSAhPT0gNFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5vcGVuTW9kYWwoKTtcbiAgICAgICAgICAgIHRoaXMuRXJyb3JFdmVudExpc3RlbmVyLmVtaXQoXCJvdmVydGltZVwiKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwi5Yqg6L296LaF5pe277yBXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgdGhpcy5tYXhMb2FkVGltZSB8fCAxNTAwMCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5saXZlUGxheWVyLm9uKFwibG9hZGVkbWV0YWRhdGFcIiwgKCRldmVudCkgPT4ge1xuICAgICAgZW5kVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgY29uc29sZS5sb2coXCLnm7Tmkq3mtYHliqDovb3miJDlip9cIik7XG4gICAgICB0aGlzLnNldEJnVmlzaWJsZShcImxvYWRpbmdcIiwgZmFsc2UpO1xuICAgICAgdGhpcy5EYXRhTG9hZGVkRXZlbnRMaXN0ZW5lci5lbWl0KFxuICAgICAgICBPYmplY3QuYXNzaWduKCRldmVudCwgeyBidWZmZXJUaW1lOiBlbmRUaW1lIC0gc3RhcnRUaW1lIH0pXG4gICAgICApO1xuICAgIH0pO1xuICAgIHRoaXMubGl2ZVBsYXllci5vbihcImNhbnBsYXl0aHJvdWdoXCIsICgkZXZlbnQpID0+IHtcbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5saXZlUGxheWVyLnJlYWR5U3RhdGUoKSA9PT0gMyB8fFxuICAgICAgICB0aGlzLmxpdmVQbGF5ZXIucmVhZHlTdGF0ZSgpID09PSA0XG4gICAgICApIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuZmlsZVBsYXllcikge1xuICAgICAgICAgICAgdGhpcy5kaXNwb3NlKHRoaXMuZmlsZVBsYXllcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMubGl2ZUxvYWRlZCA9IHRydWU7XG4gICAgICAgICAgdGhpcy5zZXRCZ1Zpc2libGUoXCJsb2FkaW5nXCIsIGZhbHNlKTtcbiAgICAgICAgfSwgMTAwMCk7XG5cbiAgICAgICAgdGhpcy5DYW5QbGF5RXZlbnRMaXN0ZW5lci5lbWl0KCRldmVudCk7XG4gICAgICB9XG4gICAgICBjb25zb2xlLmxvZyh0aGlzLmxpdmVQbGF5ZXIucmVhZHlTdGF0ZSgpLCBcImNhbnBsYXl0aHJvdWdoXCIpO1xuICAgIH0pO1xuICAgIHRoaXMubGl2ZVBsYXllci5vbihcInBsYXlpbmdcIiwgKCRldmVudCkgPT4ge1xuICAgICAgY29uc29sZS5sb2coXCLnm7Tmkq3mtYHmraPlnKjmkq3mlL7vvIFcIik7XG4gICAgICB0aGlzLmRlc3Ryb3lUaW1lb3V0KCk7XG4gICAgICB0aGlzLnNldEJnVmlzaWJsZShcImxvYWRpbmdcIiwgZmFsc2UpO1xuICAgICAgdGhpcy5QbGF5aW5nRXZlbnRMaXN0ZW5lci5lbWl0KCRldmVudCk7XG4gICAgfSk7XG4gICAgdGhpcy5saXZlUGxheWVyLm9uKFwiZXJyb3JcIiwgKCRldmVudCkgPT4ge1xuICAgICAgdGhpcy5FcnJvckV2ZW50TGlzdGVuZXIuZW1pdCgkZXZlbnQpO1xuICAgICAgY29uc29sZS5sb2coXCLnm7Tmkq3mtYHlh7rplJnkuobvvIFcIik7XG4gICAgICB0aGlzLm9wZW5Nb2RhbCgpO1xuICAgIH0pO1xuICAgIHRoaXMubGl2ZVBsYXllci5vbihcInBhdXNlXCIsICgkZXZlbnQpID0+IHtcbiAgICAgIHRoaXMuUGF1c2VFdmVudExpc3RlbmVyLmVtaXQoJGV2ZW50KTtcbiAgICB9KTtcbiAgICB0aGlzLmxpdmVQbGF5ZXIub24oXCJ0aW1ldXBkYXRlXCIsICgkZXZlbnQpID0+IHtcbiAgICAgIGlmICghdGhpcy5pc1ZpZGVvQnJlYWspIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMubGl2ZVBsYXllci5yZWFkeVN0YXRlKCkgIT09IDMgJiZcbiAgICAgICAgICB0aGlzLmxpdmVQbGF5ZXIucmVhZHlTdGF0ZSgpICE9PSA0XG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMuV2FpdGluZ0V2ZW50TGlzdGVuZXIuZW1pdCgkZXZlbnQpO1xuICAgICAgICAgIHRoaXMuaXNWaWRlb0JyZWFrID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIHRoaXMubGl2ZVBsYXllciAmJlxuICAgICAgICAgICAgICB0aGlzLmxpdmVQbGF5ZXIucmVhZHlTdGF0ZSgpICE9PSAzICYmXG4gICAgICAgICAgICAgIHRoaXMubGl2ZVBsYXllci5yZWFkeVN0YXRlKCkgIT09IDRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICB0aGlzLm9wZW5Nb2RhbCgpO1xuICAgICAgICAgICAgICB0aGlzLkVycm9yRXZlbnRMaXN0ZW5lci5lbWl0KFwib3ZlcnRpbWVcIik7XG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwi57yT5Yay6LaF5pe277yBXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sIHRoaXMubWF4TG9hZFRpbWUgfHwgMTUwMDApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbiAgLy8g6I635Y+WcGxheWVy5a6e5L6LXG4gIHB1YmxpYyBnZXRGaWxlUGxheWVyKCkge1xuICAgIHJldHVybiB0aGlzLmZpbGVQbGF5ZXIgfHwgdW5kZWZpbmVkO1xuICB9XG4gIHB1YmxpYyBnZXRMaXZlUGxheWVyKCkge1xuICAgIHJldHVybiB0aGlzLmxpdmVQbGF5ZXIgfHwgdW5kZWZpbmVkO1xuICB9XG4gIC8vIOm7mOiupOmFjee9rlxuICBwdWJsaWMgc2V0RGVmYXVsdFByb3BlcnR5KHBsYXllcjogdmlkZW9qcy5QbGF5ZXIpIHtcbiAgICBwbGF5ZXIucGxheXNpbmxpbmUodHJ1ZSk7XG4gICAgLy9wbGF5ZXIuY3Jvc3NPcmlnaW4oXCJhbm9ueW1vdXNcIik7XG4gIH1cbiAgLy8g6ZSA5q+BXG4gIHB1YmxpYyBkaXNwb3NlKHBsYXllcjogdmlkZW9qcy5QbGF5ZXIgfCB1bmRlZmluZWQpIHtcbiAgICBpZiAoIXBsYXllcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXBsYXllci5pc0Rpc3Bvc2VkKCkpIHtcbiAgICAgIHBsYXllci5kaXNwb3NlKCk7XG4gICAgICBwbGF5ZXIgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG4gIC8vIOmUgOavgeWumuaXtuWZqFxuICBwdWJsaWMgZGVzdHJveVRpbWVvdXQoKSB7XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuaXNWaWRlb0JyZWFrKTtcbiAgICBjbGVhclRpbWVvdXQodGhpcy5pc1ZpZGVvTG9hZGluZ1RpbWVvdXQpO1xuICAgIGNsZWFySW50ZXJ2YWwodGhpcy5mdWxsU2NyZWVuVGltZXIpO1xuICAgIHRoaXMuaXNWaWRlb0JyZWFrID0gdW5