UNPKG

@sourceloop/user-onboarding-client

Version:

Library for providing a smooth user onboarding

525 lines 76.2 kB
import { Injectable, } from '@angular/core'; import Shepherd from 'shepherd.js'; import { Status, } from '../models'; import { NavigationEnd } from '@angular/router'; import { Subject } from 'rxjs'; import { DEFAULT_MAX_WAIT_TIME, INTERVAL } from '../models/constants'; import * as i0 from "@angular/core"; import * as i1 from "./tour-store-service.service"; import * as i2 from "@angular/router"; export class TourServiceService { constructor(tourStoreService, router, componentFactory, injector, appRef) { this.tourStoreService = tourStoreService; this.router = router; this.componentFactory = componentFactory; this.injector = injector; this.appRef = appRef; this.tourComplete = new Subject(); this.tourComplete$ = this.tourComplete.asObservable(); this.tourStepChange = new Subject(); this.tourStepChange$ = this.tourStepChange.asObservable(); this.tourCancel = new Subject(); this.tourCancel$ = this.tourCancel.asObservable(); this.interval = INTERVAL; this._maxWaitTime = DEFAULT_MAX_WAIT_TIME; this._exitOnEsc = true; this.tourFailed = new Subject(); this.tourFailed$ = this.tourFailed.asObservable(); } set maxWaitTime(maxTime) { if (maxTime > 0) { this._maxWaitTime = maxTime; } } get maxWaitTime() { return this._maxWaitTime; } set exitOnEsc(esc) { this._exitOnEsc = esc; } get exitOnEsc() { return this._exitOnEsc; } addRemovedSteps(removedSteps) { const count = removedSteps.length; for (let i = 0; i < count; i++) { this.tour.steps.splice(0, 0, this.tour.steps.pop()); } } getTour() { return this.tour; } actionAssignment(e, b, wrapperNormalNext, wrapperNormalPrev, wrapperNext, wrapperPrev, func, tourId, props) { if (b.key === 'prevAction') { b.action = e.prevRoute === e.currentRoute ? wrapperNormalPrev : wrapperPrev; } else if (b.key === 'nextAction') { b.action = e.nextRoute === e.currentRoute ? wrapperNormalNext : wrapperNext; } else { b.action = func.bind({ tour: this.tour, tourId, props }); } } waitForElement(tourStep, tourId) { if (tourStep.attachTo === undefined) { return Promise.resolve(''); } else { const startTime = new Date().getTime(); return new Promise((resolve, reject) => { const timer = setInterval(() => { const now = new Date().getTime(); const element = this.checkElement(tourStep.attachTo); if (element) { clearInterval(timer); resolve(element); } else if (now - startTime >= this._maxWaitTime) { clearInterval(timer); reject({ tourId, message: `Error in loading tour` }); } else { // do nothing } }, this.interval); }); } } triggerTour(tourInstance, props) { let removedSteps = []; const sessionId = this.tourStoreService.getSessionId(); if (!sessionId) { this.tourStoreService.generateSessionId(); } this.tourStoreService .loadState({ tourId: tourInstance.tourId, sessionId }) .subscribe(tourState => { if (tourState && Object.keys(tourState).length) { if (tourState.status === Status.Complete) { return; } removedSteps = this.getRemovedSteps(tourInstance.tourSteps, tourState); tourInstance.tourSteps = this.getTourSteps(tourInstance.tourSteps, tourState); } else { tourState = { sessionId: this.tourStoreService.getSessionId(), step: tourInstance.tourSteps[0].id, props, status: Status.InProgress, }; this.tourStoreService .saveState({ tourId: tourInstance.tourId, state: tourState, }) .subscribe(); } tourInstance.tourSteps.forEach((e, index) => { e.buttons.forEach(b => { const key = b.key; const func = this.tourStoreService.getFnByKey(key); const wrapperNext = () => { this.navigateAndMoveToNextStep(e, tourInstance, tourState, index); }; const wrapperPrev = () => { this.navigateAndMoveToPrevStep(e, tourInstance, tourState, index, removedSteps); }; const wrapperNormalNext = () => { this.moveToNextStep(tourInstance, tourState, e, index); }; const wrapperNormalPrev = () => { this.moveToPrevStep(tourInstance, tourState, e, index, removedSteps); }; this.actionAssignment(e, b, wrapperNormalNext, wrapperNormalPrev, wrapperNext, wrapperPrev, func, tourInstance.tourId, tourState.props); }); }); this.tour.addSteps(tourInstance.tourSteps); this.waitForElement(tourInstance.tourSteps[0], tourInstance.tourId).then(element => { if (element) { element.scrollIntoView(true); } this.tour.start(); if (removedSteps.length) { removedSteps.forEach((er, index) => { er.buttons.forEach(br => { const k = br.key; const funcRemoved = this.tourStoreService.getFnByKey(k); const wrapperNextRemoved = () => { this.navigateAndMoveToNextStepRemoved(er, tourInstance, tourState, index, removedSteps); }; const wrapperPrevRemoved = () => { this.navigateAndMoveToPrevStepRemoved(er, tourInstance, tourState, index, removedSteps); }; const wrapperNormalNextRemoved = () => { this.moveToNextStepRemoved(tourInstance, tourState, er, index, removedSteps); }; const wrapperNormalPrevRemoved = () => { this.moveToPrevStepRemoved(tourInstance, tourState, er, index, removedSteps); }; this.actionAssignment(er, br, wrapperNormalNextRemoved, wrapperNormalPrevRemoved, wrapperNextRemoved, wrapperPrevRemoved, funcRemoved, tourInstance.tourId, tourState.props); }); }); this.tour.addSteps(removedSteps); this.addRemovedSteps(removedSteps); } }, err => { this.tourFailed.next(err); }); }); } run(tourId, params, props, filterFn, inputs) { this.tourStoreService .loadTour({ tourId, sessionId: this.tourStoreService.getSessionId(), }) .subscribe(tourInstance => { this.checkAndThrowError(tourInstance); if (params) { let steps = JSON.stringify(tourInstance.tourSteps); Object.keys(params).forEach(key => { steps = steps.replace(new RegExp(`\\{\\{${key}\\}\\}`), params[key]); }); tourInstance.tourSteps = JSON.parse(steps); } this.tour = new Shepherd.Tour({ useModalOverlay: true, exitOnEsc: this._exitOnEsc, defaultStepOptions: { cancelIcon: { enabled: true, }, scrollTo: { behavior: 'smooth', block: 'center' }, }, }); this.tour.on('complete', (event) => { event.tourId = tourInstance.tourId; this.tourComplete.next(event); }); // on pressing esc cancel event is emitted by shepherd this.tour.on('cancel', (event) => { event.tourId = tourInstance.tourId; this.tourCancel.next(event); }); if (filterFn) { tourInstance.tourSteps = filterFn(tourInstance.tourSteps); } if (tourInstance.tourSteps[0].attachTo) { tourInstance.tourSteps[0].attachTo.scrollTo = false; } this.checkComponents(tourInstance, inputs).then(() => { this.triggerTour(tourInstance, props); }); }); } async checkComponents(tourInstance, inputs) { for (const step of tourInstance.tourSteps) { if (typeof step.text !== 'string' && typeof step.text !== 'function') { const htmlStep = await this.parseComponent({ forStep: step.id, component: this.tourStoreService.getComponentByKey(step.text.component), }, inputs); step.text = htmlStep.html; } } } checkElement(attachTo) { switch (attachTo.type) { case 'string': return document.querySelector(attachTo.element); case 'element': return attachTo.element; case 'function': const fn = this.tourStoreService.getFnByKey(attachTo.element); return fn(); default: return false; } } getRemovedSteps(tourSteps, tourState) { let f = true; return tourSteps.filter(e => { if (e.id === tourState.step || !f) { f = false; } return f; }); } getTourSteps(tourSteps, tourState) { let flag = false; return tourSteps.filter(e => { if (e.id === tourState.step || flag) { flag = true; } return flag; }); } pauseAllVideos() { document.querySelectorAll('video').forEach(vid => vid.pause()); } setTourComplete(tourId, props) { this.tourStoreService .saveState({ tourId, state: { sessionId: this.tourStoreService.getSessionId(), step: '', props, status: Status.Complete, }, }) .subscribe(); } checkAndThrowError(tourInstance) { if (!tourInstance) { throw new Error(`No Tour Present`); } else if (tourInstance.tourSteps.length === 0) { throw new Error(`No Tour Steps Found`); } else if (tourInstance.tourSteps[0].buttons) { tourInstance.tourSteps[0].buttons.forEach(button => { if (button.key === `prevAction`) { throw new Error(`Step 1 can't have a previous button`); } }); } else { //do nothing } } moveToNextStep(tourInstance, tourState, step, index) { if (index === tourInstance.tourSteps.length - 1) { this.setTourComplete(tourInstance.tourId, tourState.props); this.tour.next(); } else { this.waitForElement(tourInstance.tourSteps[index + 1], tourInstance.tourId).then(() => { this.tourStoreService .saveState({ tourId: tourInstance.tourId, state: { sessionId: this.tourStoreService.getSessionId(), step: step.nextStepId, props: tourState.props, status: Status.InProgress, }, }) .subscribe(); this.tour.show(step.nextStepId); this.tourStepChange.next({ tourId: tourInstance.tourId, currentStepId: step.nextStepId, previousStepId: step.id, moveForward: true, }); this.pauseAllVideos(); }, err => { this.tourFailed.next(err); }); } } moveToPrevStep(tourInstance, tourState, step, index, removedSteps) { let waitForLastElementOfRemovedSteps = false; if (index === 0 && removedSteps.length) { waitForLastElementOfRemovedSteps = true; } this.waitForElement(waitForLastElementOfRemovedSteps ? removedSteps[removedSteps.length - 1] : tourInstance.tourSteps[index - 1], tourInstance.tourId).then(() => { this.tourStoreService .saveState({ tourId: tourInstance.tourId, state: { sessionId: this.tourStoreService.getSessionId(), step: waitForLastElementOfRemovedSteps ? removedSteps[removedSteps.length - 1].id : step.prevStepId, props: tourState.props, status: Status.InProgress, }, }) .subscribe(); if (waitForLastElementOfRemovedSteps) { this.tour.show(removedSteps[removedSteps.length - 1].id); } else { this.tour.show(step.prevStepId); } this.tourStepChange.next({ tourId: tourInstance.tourId, currentStepId: waitForLastElementOfRemovedSteps ? removedSteps[removedSteps.length - 1].id : step.prevStepId, previousStepId: step.id, moveForward: false, }); this.pauseAllVideos(); }, err => { this.tourFailed.next(err); }); } moveToNextStepRemoved(tourInstance, tourState, step, index, removedSteps) { let waitForFirstElementOfSteps = false; if (index === removedSteps.length - 1) { waitForFirstElementOfSteps = true; } this.waitForElement(waitForFirstElementOfSteps ? tourInstance.tourSteps[0] : removedSteps[index + 1], tourInstance.tourId).then(() => { this.tourStoreService .saveState({ tourId: tourInstance.tourId, state: { sessionId: this.tourStoreService.getSessionId(), step: waitForFirstElementOfSteps ? tourInstance.tourSteps[0].id : step.nextStepId, props: tourState.props, status: Status.InProgress, }, }) .subscribe(); if (waitForFirstElementOfSteps) { this.tour.show(tourInstance.tourSteps[0].id); } else { this.tour.show(step.nextStepId); } this.tourStepChange.next({ tourId: tourInstance.tourId, currentStepId: waitForFirstElementOfSteps ? tourInstance.tourSteps[0].id : step.nextStepId, previousStepId: step.id, moveForward: true, }); this.pauseAllVideos(); }, err => { this.tourFailed.next(err); }); } moveToPrevStepRemoved(tourInstance, tourState, step, index, removedSteps) { this.waitForElement(removedSteps[index - 1], tourInstance.tourId).then(() => { this.tourStoreService .saveState({ tourId: tourInstance.tourId, state: { sessionId: this.tourStoreService.getSessionId(), step: step.prevStepId, props: tourState.props, status: Status.InProgress, }, }) .subscribe(); this.tour.show(step.prevStepId); this.tourStepChange.next({ tourId: tourInstance.tourId, currentStepId: step.prevStepId, previousStepId: step.id, moveForward: false, }); this.pauseAllVideos(); }, err => { this.tourFailed.next(err); }); } navigateAndMoveToNextStep(currentStep, tourInstance, tourState, index) { if (index < tourInstance.tourSteps.length - 1) { this.router.navigate([currentStep.nextRoute]); this.router.events.subscribe((event) => { const nextStep = tourInstance.tourSteps.filter(ts => ts.id === currentStep.nextStepId)[0]; if (event instanceof NavigationEnd && event.url === nextStep.currentRoute) { this.moveToNextStep(tourInstance, tourState, currentStep, index); } }); } else { this.moveToNextStep(tourInstance, tourState, currentStep, index); } } navigateAndMoveToPrevStep(currentStep, tourInstance, tourState, index, removedSteps) { let moveToLastRemovedStep = false; if (index === 0 && removedSteps.length) { moveToLastRemovedStep = true; } const prevRoute = moveToLastRemovedStep ? removedSteps[removedSteps.length - 1].prevRoute : currentStep.prevRoute; this.router.navigate([prevRoute]); this.router.events.subscribe((event) => { let prevStep; if (moveToLastRemovedStep) { prevStep = removedSteps[removedSteps.length - 1]; } else { prevStep = tourInstance.tourSteps.filter(ts => ts.id === currentStep.prevStepId)[0]; } if (event instanceof NavigationEnd && event.url === prevStep.currentRoute) { this.moveToPrevStep(tourInstance, tourState, currentStep, index, removedSteps); } }); } navigateAndMoveToNextStepRemoved(currentStep, tourInstance, tourState, index, removedSteps) { let moveToFirstStep = false; if (index === removedSteps.length - 1) { moveToFirstStep = true; } const nextRoute = moveToFirstStep ? tourInstance.tourSteps[0].nextRoute : currentStep.nextRoute; this.router.navigate([nextRoute]); this.router.events.subscribe((event) => { let nextStep; if (moveToFirstStep) { nextStep = tourInstance.tourSteps[0]; } else { nextStep = tourInstance.tourSteps.filter(ts => ts.id === currentStep.nextStepId)[0]; } if (event instanceof NavigationEnd && event.url === nextStep.currentRoute) { this.moveToNextStepRemoved(tourInstance, tourState, currentStep, index, removedSteps); } }); } navigateAndMoveToPrevStepRemoved(currentStep, tourInstance, tourState, index, removedSteps) { this.router.navigate([currentStep.prevRoute]); this.router.events.subscribe((event) => { const prevStep = tourInstance.tourSteps.filter(ts => ts.id === currentStep.prevStepId)[0]; if (event instanceof NavigationEnd && event.url === prevStep.currentRoute) { this.moveToPrevStepRemoved(tourInstance, tourState, currentStep, index, removedSteps); } }); } parseComponent(step, input) { return Promise.resolve({ forStep: step.forStep, html: () => { const factory = this.componentFactory.resolveComponentFactory(step.component); const constructedComponent = factory.create(this.injector); Object.keys(input ?? {}).forEach(k => { constructedComponent.instance[k] = input[k]; }); constructedComponent.instance['tour'] = this.tour; this.appRef.attachView(constructedComponent.hostView); return constructedComponent.location.nativeElement; }, }); } } TourServiceService.ɵfac = function TourServiceService_Factory(t) { return new (t || TourServiceService)(i0.ɵɵinject(i1.TourStoreServiceService), i0.ɵɵinject(i2.Router), i0.ɵɵinject(i0.ComponentFactoryResolver), i0.ɵɵinject(i0.Injector), i0.ɵɵinject(i0.ApplicationRef)); }; TourServiceService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TourServiceService, factory: TourServiceService.ɵfac, providedIn: 'root' }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TourServiceService, [{ type: Injectable, args: [{ providedIn: 'root', }] }], function () { return [{ type: i1.TourStoreServiceService }, { type: i2.Router }, { type: i0.ComponentFactoryResolver }, { type: i0.Injector }, { type: i0.ApplicationRef }]; }, null); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG91ci1zZXJ2aWNlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3RvdXItc2VydmljZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUtBLE9BQU8sRUFHTCxVQUFVLEdBRVgsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxRQUFRLE1BQU0sYUFBYSxDQUFDO0FBQ25DLE9BQU8sRUFPTCxNQUFNLEdBS1AsTUFBTSxXQUFXLENBQUM7QUFDbkIsT0FBTyxFQUFTLGFBQWEsRUFBMkIsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBQyxxQkFBcUIsRUFBRSxRQUFRLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQzs7OztBQUtwRSxNQUFNLE9BQU8sa0JBQWtCO0lBa0I3QixZQUNtQixnQkFBeUMsRUFDekMsTUFBYyxFQUNkLGdCQUEwQyxFQUMxQyxRQUFrQixFQUNsQixNQUFzQjtRQUp0QixxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQXlCO1FBQ3pDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQTBCO1FBQzFDLGFBQVEsR0FBUixRQUFRLENBQVU7UUFDbEIsV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUF0QnhCLGlCQUFZLEdBQUcsSUFBSSxPQUFPLEVBQWdCLENBQUM7UUFDNUQsa0JBQWEsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2hDLG1CQUFjLEdBQUcsSUFBSSxPQUFPLEVBQWtCLENBQUM7UUFDaEUsb0JBQWUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3BDLGVBQVUsR0FBRyxJQUFJLE9BQU8sRUFBYyxDQUFDO1FBQ3hELGdCQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUM1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Q0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUN0RCxPQUFPLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUM7WUFDckQsQ0FBQztTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7O29GQTdzQlUsa0JBQWtCO3dFQUFsQixrQkFBa0IsV0FBbEIsa0JBQWtCLG1CQUZqQixNQUFNO3VGQUVQLGtCQUFrQjtjQUg5QixVQUFVO2VBQUM7Z0JBQ1YsVUFBVSxFQUFFLE1BQU07YUFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMjMgU291cmNlZnVzZSBUZWNobm9sb2dpZXNcbi8vXG4vLyBUaGlzIHNvZnR3YXJlIGlzIHJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbi8vIGh0dHBzOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlUXG5pbXBvcnQge1RvdXJTdG9yZVNlcnZpY2VTZXJ2aWNlfSBmcm9tICcuL3RvdXItc3RvcmUtc2VydmljZS5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIEFwcGxpY2F0aW9uUmVmLFxuICBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gIEluamVjdGFibGUsXG4gIEluamVjdG9yLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCBTaGVwaGVyZCBmcm9tICdzaGVwaGVyZC5qcyc7XG5pbXBvcnQge1xuICBUb3VyLFxuICBUb3VyQnV0dG9uLFxuICBUb3VyU3RlcCxcbiAgVG91clN0YXRlLFxuICBGaWx0ZXJGdW5jdGlvbixcbiAgUHJvcHMsXG4gIFN0YXR1cyxcbiAgVG91clN0ZXBDaGFuZ2UsXG4gIFRvdXJDb21wbGV0ZSxcbiAgVG91ckNhbmNlbCxcbiAgQ29tcG9uZW50U3RlcCxcbn0gZnJvbSAnLi4vbW9kZWxzJztcbmltcG9ydCB7Um91dGVyLCBOYXZpZ2F0aW9uRW5kLCBFdmVudCBhcyBOYXZpZ2F0aW9uRXZlbnR9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1N1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtERUZBVUxUX01BWF9XQUlUX1RJTUUsIElOVEVSVkFMfSBmcm9tICcuLi9tb2RlbHMvY29uc3RhbnRzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFRvdXJTZXJ2aWNlU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgdG91ckNvbXBsZXRlID0gbmV3IFN1YmplY3Q8VG91ckNvbXBsZXRlPigpO1xuICB0b3VyQ29tcGxldGUkID0gdGhpcy50b3VyQ29tcGxldGUuYXNPYnNlcnZhYmxlKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgdG91clN0ZXBDaGFuZ2UgPSBuZXcgU3ViamVjdDxUb3VyU3RlcENoYW5nZT4oKTtcbiAgdG91clN0ZXBDaGFuZ2UkID0gdGhpcy50b3VyU3RlcENoYW5nZS5hc09ic2VydmFibGUoKTtcbiAgcHJpdmF0ZSByZWFkb25seSB0b3VyQ2FuY2VsID0gbmV3IFN1YmplY3Q8VG91ckNhbmNlbD4oKTtcbiAgdG91ckNhbmNlbCQgPSB0aGlzLnRvdXJDYW5jZWwuYXNPYnNlcnZhYmxlKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW50ZXJ2YWwgPSBJTlRFUlZBTDtcbiAgcHJpdmF0ZSBfbWF4V2FpdFRpbWUgPSBERUZBVUxUX01BWF9XQUlUX1RJTUU7XG4gIHByaXZhdGUgX2V4aXRPbkVzYyA9IHRydWU7XG4gIHByaXZhdGUgcmVhZG9ubHkgdG91ckZhaWxlZCA9IG5ldyBTdWJqZWN0PHtcbiAgICB0b3VySWQ6IHN0cmluZztcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG4gIH0+KCk7XG4gIHRvdXJGYWlsZWQkID0gdGhpcy50b3VyRmFpbGVkLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIHByaXZhdGUgdG91cjogU2hlcGhlcmQuVG91cjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRvdXJTdG9yZVNlcnZpY2U6IFRvdXJTdG9yZVNlcnZpY2VTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcm91dGVyOiBSb3V0ZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb21wb25lbnRGYWN0b3J5OiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSByZWFkb25seSBhcHBSZWY6IEFwcGxpY2F0aW9uUmVmLFxuICApIHt9XG5cbiAgcHVibGljIHNldCBtYXhXYWl0VGltZShtYXhUaW1lOiBudW1iZXIpIHtcbiAgICBpZiAobWF4VGltZSA+IDApIHtcbiAgICAgIHRoaXMuX21heFdhaXRUaW1lID0gbWF4VGltZTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0IG1heFdhaXRUaW1lKCkge1xuICAgIHJldHVybiB0aGlzLl9tYXhXYWl0VGltZTtcbiAgfVxuXG4gIHB1YmxpYyBzZXQgZXhpdE9uRXNjKGVzYzogYm9vbGVhbikge1xuICAgIHRoaXMuX2V4aXRPbkVzYyA9IGVzYztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgZXhpdE9uRXNjKCkge1xuICAgIHJldHVybiB0aGlzLl9leGl0T25Fc2M7XG4gIH1cbiAgcHJpdmF0ZSBhZGRSZW1vdmVkU3RlcHMocmVtb3ZlZFN0ZXBzKTogdm9pZCB7XG4gICAgY29uc3QgY291bnQgPSByZW1vdmVkU3RlcHMubGVuZ3RoO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgdGhpcy50b3VyLnN0ZXBzLnNwbGljZSgwLCAwLCB0aGlzLnRvdXIuc3RlcHMucG9wKCkpO1xuICAgIH1cbiAgfVxuXG4gIGdldFRvdXIoKSB7XG4gICAgcmV0dXJuIHRoaXMudG91cjtcbiAgfVxuXG4gIHByaXZhdGUgYWN0aW9uQXNzaWdubWVudChcbiAgICBlOiBUb3VyU3RlcCxcbiAgICBiOiBUb3VyQnV0dG9uLFxuICAgIHdyYXBwZXJOb3JtYWxOZXh0LFxuICAgIHdyYXBwZXJOb3JtYWxQcmV2LFxuICAgIHdyYXBwZXJOZXh0LFxuICAgIHdyYXBwZXJQcmV2LFxuICAgIGZ1bmMsXG4gICAgdG91cklkOiBzdHJpbmcsXG4gICAgcHJvcHM6IFByb3BzLFxuICApOiB2b2lkIHtcbiAgICBpZiAoYi5rZXkgPT09ICdwcmV2QWN0aW9uJykge1xuICAgICAgYi5hY3Rpb24gPVxuICAgICAgICBlLnByZXZSb3V0ZSA9PT0gZS5jdXJyZW50Um91dGUgPyB3cmFwcGVyTm9ybWFsUHJldiA6IHdyYXBwZXJQcmV2O1xuICAgIH0gZWxzZSBpZiAoYi5rZXkgPT09ICduZXh0QWN0aW9uJykge1xuICAgICAgYi5hY3Rpb24gPVxuICAgICAgICBlLm5leHRSb3V0ZSA9PT0gZS5jdXJyZW50Um91dGUgPyB3cmFwcGVyTm9ybWFsTmV4dCA6IHdyYXBwZXJOZXh0O1xuICAgIH0gZWxzZSB7XG4gICAgICBiLmFjdGlvbiA9IGZ1bmMuYmluZCh7dG91cjogdGhpcy50b3VyLCB0b3VySWQsIHByb3BzfSk7XG4gICAgfVxuICB9XG5c