UNPKG

ng-toast-notify

Version:

Lightweight and flexible toast notifications for Angular

203 lines 30.6 kB
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; import * as i0 from "@angular/core"; import * as i1 from "./toastysound.service"; class Queue { constructor(capacity = Infinity) { this.capacity = capacity; this.storage = []; } setCapacity(c) { this.capacity = c; } getCapacity() { return this.capacity; } enqueue(item) { if (this.size() >= this.capacity) { throw Error('Toasty queue has reached max capacity, you cannot add more items.'); } this.storage.push(item); } dequeue() { return this.storage.shift(); } size() { return this.storage.length; } getElements() { return this.storage; } removeId(id) { const index = this.storage.findIndex(item => item.id === id); if (index !== -1) { const [removed] = this.storage.splice(index, 1); return removed; } return undefined; } } export var ToastType; (function (ToastType) { ToastType["Basic"] = "basic"; ToastType["Success"] = "success"; ToastType["Error"] = "error"; ToastType["Info"] = "info"; ToastType["Warning"] = "warning"; ToastType["Custom"] = "custom"; })(ToastType || (ToastType = {})); export class ToastyService { constructor(_toastySoundService) { this._toastySoundService = _toastySoundService; this.TOASTY_SERVICE_CONFIG = { capacity: 10, duration: 5000, messages: { now: 'just now', seconds: '{0} seconds ago', minutes: '{0} minutes ago' }, threshold_offsetX: 170 }; this.queue = new Queue(this.TOASTY_SERVICE_CONFIG.capacity); this.counter = 0; this.newToastBehaviorSubject = new BehaviorSubject([]); this.newToast$ = this.newToastBehaviorSubject.asObservable(); this.deleteToastBehaviorSubject = new BehaviorSubject(undefined); this.deleteToast$ = this.deleteToastBehaviorSubject.asObservable(); this.updateToastBehaviorSubject = new BehaviorSubject(undefined); this.updateToast$ = this.updateToastBehaviorSubject.asObservable(); } setDefaultDuration(d) { this.TOASTY_SERVICE_CONFIG.duration = d; } getDefaultDuration() { return this.TOASTY_SERVICE_CONFIG.duration; } setCapacity(c) { this.TOASTY_SERVICE_CONFIG.capacity = c; this.queue.setCapacity(c); } getCapacity() { return this.queue.getCapacity(); } showToast(title, message, toastConfig, isPromise) { this.counter++; // if sticky is true duration is infinity else use the provided duration or the default one const duration = toastConfig?.sticky ? Infinity : (toastConfig?.duration ?? this.TOASTY_SERVICE_CONFIG.duration); const toast = { id: this.counter, title: title, message: message, type: toastConfig?.type ?? ToastType.Basic, timestamp: Date.now(), duration: duration, expires: isPromise ? Infinity : Date.now() + duration, config: toastConfig, get icon() { if (toastConfig?.type == ToastType.Success) return "✅"; if (toastConfig?.type == ToastType.Info) return "ℹ️"; if (toastConfig?.type == ToastType.Warning) return "⚠️"; if (toastConfig?.type == ToastType.Error) return "❌"; return ""; } }; this.queue.enqueue(toast); this.newToastBehaviorSubject.next([...this.queue.getElements()]); if (toast.config?.beep) { this._toastySoundService.notify(); } // if sticky progress bar is not animated and toast will not expire if (!toast.config?.sticky) { if (toast.config?.progressBar) { setTimeout(() => { this.updateToast(toast.id, { animatePbar: true }); }, 100); } if (!isPromise) { setTimeout(() => { this.removeToast(toast.id); }, duration + 5); } } return this.counter; } showToastPromise(title, promise, config) { const idtoast = this.showToast(title, promise.loading, { ...config, loading: true }, true); const duration = config?.duration ?? this.TOASTY_SERVICE_CONFIG.duration; promise.promise .then((result) => { const successMessage = typeof promise.success === 'function' ? promise.success(result) : promise.success; this.updateToast(idtoast, { message: successMessage, type: ToastType.Success, expires: Date.now() + duration, config: { loading: false } }); }) .catch((err) => { const errorMessage = typeof promise.error === 'function' ? promise.error(err) : promise.error; this.updateToast(idtoast, { message: errorMessage, type: ToastType.Error, expires: Date.now() + duration, config: { loading: false } }); }) .finally(() => { if (!config?.sticky) setTimeout(() => this.removeToast(idtoast), duration); }); } removeToast(id) { this.newToastBehaviorSubject.next([...this.queue.getElements()]); // Trigger re-render to start exit animation setTimeout(() => { const t = this.queue.removeId(id); this.newToastBehaviorSubject.next([...this.queue.getElements()]); }, 500); // Wait for animation to finish before removing from queue } closeToast(id) { const t = this.queue.removeId(id); this.newToastBehaviorSubject.next([...this.queue.getElements()]); } updateTouchStart(id, touch) { const gesture = { date: Date.now(), touchStart: touch }; this.updateToast(id, { gesture: gesture }); } // Loops through the toasts to find which one was touched and updates its touchEnd updateTouchEnd(touch) { const toasts = this.queue.getElements().forEach(t => { if (t.gesture) { const deltaY = Math.abs(touch.clientY - t.gesture.touchStart.clientY); const deltaX = Math.abs(touch.clientX - t.gesture.touchStart.clientX); const deltaTime = Date.now() - t.gesture.date; if (deltaTime < 500 && deltaX > this.TOASTY_SERVICE_CONFIG.threshold_offsetX) { this.closeToast(t.id); } else { t.gesture = undefined; // Reset gesture if not swiped } } }); } updateTouchMove(touch) { const toasts = this.queue.getElements(); toasts.forEach(t => { if (t.gesture) { const deltaX = touch.clientX - t.gesture.touchStart.clientX; t.gesture.offsetX = deltaX; // Store the offset for potential use in UI updates } }); } updateToast(id, newData) { const toasts = this.queue.getElements(); const index = toasts.findIndex(t => t.id === id); if (index !== -1) { toasts[index] = { ...toasts[index], ...newData }; this.newToastBehaviorSubject.next([...toasts]); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToastyService, deps: [{ token: i1.ToastysoundService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToastyService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToastyService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.ToastysoundService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9hc3R5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy10b2FzdC1ub3RpZnkvc3JjL2xpYi90b2FzdHkuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7O0FBb0JoRSxNQUFNLEtBQUs7SUFHVCxZQUFvQixXQUFtQixRQUFRO1FBQTNCLGFBQVEsR0FBUixRQUFRLENBQW1CO1FBRnZDLFlBQU8sR0FBUSxFQUFFLENBQUM7SUFHMUIsQ0FBQztJQUVELFdBQVcsQ0FBQyxDQUFTO1FBQ25CLElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ3BCLENBQUM7SUFDRCxXQUFXLEtBQUssT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUV2QyxPQUFPLENBQUMsSUFBTztRQUNiLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNqQyxNQUFNLEtBQUssQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO1FBQ25GLENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBQ0QsT0FBTztRQUNMLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBQ0QsSUFBSTtRQUNGLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7SUFDN0IsQ0FBQztJQUNELFdBQVc7UUFDVCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUNELFFBQVEsQ0FBQyxFQUFVO1FBQ2pCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFD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QUFDO1lBQ2pELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDakQsQ0FBQztJQUNILENBQUM7K0dBbExVLGFBQWE7bUhBQWIsYUFBYSxjQUZaLE1BQU07OzRGQUVQLGFBQWE7a0JBSHpCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzL2ludGVybmFsL0JlaGF2aW9yU3ViamVjdCc7XHJcbmltcG9ydCB7IFRvYXN0eXNvdW5kU2VydmljZSB9IGZyb20gJy4vdG9hc3R5c291bmQuc2VydmljZSc7XHJcblxyXG5pbnRlcmZhY2UgSVNlcnZpY2VDb25maWcge1xyXG4gIGNhcGFjaXR5OiBudW1iZXI7XHJcbiAgZHVyYXRpb246IG51bWJlcjtcclxuICBtZXNzYWdlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcclxuICB0aHJlc2hvbGRfb2Zmc2V0WDogbnVtYmVyO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSVRvYXN0UXVldWU8VD4ge1xyXG4gIHNldENhcGFjaXR5KGM6IG51bWJlcik6IHZvaWQ7XHJcbiAgZ2V0Q2FwYWNpdHkoKTogbnVtYmVyO1xyXG4gIGVucXVldWUoaXRlbTogVCk6IHZvaWQ7XHJcbiAgZGVxdWV1ZSgpOiBUIHwgdW5kZWZpbmVkO1xyXG4gIHNpemUoKTogbnVtYmVyO1xyXG4gIGdldEVsZW1lbnRzKCk6IFRbXTtcclxuICByZW1vdmVJZChpZDogbnVtYmVyKTogVCB8IHVuZGVmaW5lZDtcclxufVxyXG5cclxuY2xhc3MgUXVldWU8VD4gaW1wbGVtZW50cyBJVG9hc3RRdWV1ZTxUPiB7XHJcbiAgcHJpdmF0ZSBzdG9yYWdlOiBUW10gPSBbXTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjYXBhY2l0eTogbnVtYmVyID0gSW5maW5pdHkpIHtcclxuICB9XHJcblxyXG4gIHNldENhcGFjaXR5KGM6IG51bWJlcikge1xyXG4gICAgdGhpcy5jYXBhY2l0eSA9IGM7XHJcbiAgfVxyXG4gIGdldENhcGFjaXR5KCkgeyByZXR1cm4gdGhpcy5jYXBhY2l0eTsgfVxyXG5cclxuICBlbnF1ZXVlKGl0ZW06IFQpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnNpemUoKSA+PSB0aGlzLmNhcGFjaXR5KSB7XHJcbiAgICAgIHRocm93IEVycm9yKCdUb2FzdHkgcXVldWUgaGFzIHJlYWNoZWQgbWF4IGNhcGFjaXR5LCB5b3UgY2Fubm90IGFkZCBtb3JlIGl0ZW1zLicpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5zdG9yYWdlLnB1c2goaXRlbSk7XHJcbiAgfVxyXG4gIGRlcXVldWUoKTogVCB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLnNoaWZ0KCk7XHJcbiAgfVxyXG4gIHNpemUoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLnN0b3JhZ2UubGVuZ3RoO1xyXG4gIH1cclxuICBnZXRFbGVtZW50cygpOiBUW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZTtcclxuICB9XHJcbiAgcmVtb3ZlSWQoaWQ6IG51bWJlcik6IFQgfCB1bmRlZmluZWQge1xyXG4gICAgY29uc3QgaW5kZXggPSB0aGlzLnN0b3JhZ2UuZmluZEluZGV4KGl0ZW0gPT4gKGl0ZW0gYXMgYW55KS5pZCA9PT0gaWQpO1xyXG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xyXG4gICAgICBjb25zdCBbcmVtb3ZlZF0gPSB0aGlzLnN0b3JhZ2Uuc3BsaWNlKGluZGV4LCAxKTtcclxuICAgICAgcmV0dXJuIHJlbW92ZWQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gIH1cclxufVxyXG5leHBvcnQgZW51bSBUb2FzdFR5cGUge1xyXG4gIEJhc2ljID0gJ2Jhc2ljJyxcclxuICBTdWNjZXNzID0gJ3N1Y2Nlc3MnLFxyXG4gIEVycm9yID0gJ2Vycm9yJyxcclxuICBJbmZvID0gJ2luZm8nLFxyXG4gIFdhcm5pbmcgPSAnd2FybmluZycsXHJcbiAgQ3VzdG9tID0gJ2N1c3RvbSdcclxufVxyXG5cclxuaW50ZXJmYWNlIFRvYXN0R2VzdHVyZSB7XHJcbiAgZGF0ZTogbnVtYmVyO1xyXG4gIHRvdWNoU3RhcnQ/OiBUb3VjaDtcclxuICB0b3VjaEVuZD86IFRvdWNoO1xyXG4gIG9mZnNldFg/OiBudW1iZXI7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVG9hc3RNb2RlbCB7XHJcbiAgaWQ6IG51bWJlcjtcclxuICB0aXRsZTogc3RyaW5nO1xyXG4gIG1lc3NhZ2U6IHN0cmluZztcclxuICB0eXBlOiBUb2FzdFR5cGU7XHJcbiAgdGltZXN0YW1wOiBudW1iZXI7XHJcbiAgZHVyYXRpb246IG51bWJlcjtcclxuICBleHBpcmVzOiBudW1iZXI7XHJcbiAgY29uZmlnPzogVG9hc3R5Q29uZmlnO1xyXG4gIGdldCBpY29uKCk6IHN0cmluZztcclxuXHJcbiAgZ2VzdHVyZT86IFRvYXN0R2VzdHVyZTtcclxuICBhbmltYXRlUGJhcj86IGJvb2xlYW47IC8vIFVzZWQgdG8gYW5pbWF0ZSB0aGUgcHJvZ3Jlc3MgYmFyXHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVG9hc3R5Q29uZmlnIHtcclxuICB0eXBlPzogVG9hc3RUeXBlO1xyXG4gIGR1cmF0aW9uPzogbnVtYmVyO1xyXG4gIHN0aWNreT86IGJvb2xlYW47XHJcbiAgZW5hYmxlSHRtbD86IGJvb2xlYW47XHJcbiAgY3VzdG9tU3R5bGU/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xyXG4gIGxvYWRpbmc/OiBib29sZWFuO1xyXG4gIGJlZXA/OiBib29sZWFuO1xyXG4gIHByb2dyZXNzQmFyPzogYm9vbGVhbjtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBUb2FzdHlQcm9taXNlPFQ+IHtcclxuICBwcm9taXNlOiBQcm9taXNlPFQ+O1xyXG4gIGxvYWRpbmc6IHN0cmluZztcclxuICBzdWNjZXNzOiBzdHJpbmcgfCAoKHJlc3VsdDogVCkgPT4gc3RyaW5nKTtcclxuICBlcnJvcjogc3RyaW5nIHwgKChlcnI6IGFueSkgPT4gc3RyaW5nKTtcclxufVxyXG5cclxuXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCdcclxufSlcclxuZXhwb3J0IGNsYXNzIFRvYXN0eVNlcnZpY2Uge1xyXG5cclxuICBwcml2YXRlIFRPQVNUWV9TRVJWSUNFX0NPTkZJRzogSVNlcnZpY2VDb25maWcgPSB7XHJcbiAgICBjYXBhY2l0eTogMTAsXHJcbiAgICBkdXJhdGlvbjogNTAwMCxcclxuICAgIG1lc3NhZ2VzOiB7XHJcbiAgICAgIG5vdzogJ2p1c3Qgbm93JyxcclxuICAgICAgc2Vjb25kczogJ3swfSBzZWNvbmRzIGFnbycsXHJcbiAgICAgIG1pbnV0ZXM6ICd7MH0gbWludXRlcyBhZ28nXHJcbiAgICB9LFxyXG4gICAgdGhyZXNob2xkX29mZnNldFg6IDE3MFxyXG4gIH07XHJcblxyXG5cclxuICBwcml2YXRlIHF1ZXVlOiBJVG9hc3RRdWV1ZTxUb2FzdE1vZGVsPiA9IG5ldyBRdWV1ZTxUb2FzdE1vZGVsPih0aGlzLlRPQVNUWV9TRVJWSUNFX0NPTkZJRy5jYXBhY2l0eSk7XHJcbiAgcHJpdmF0ZSBjb3VudGVyOiBudW1iZXIgPSAwO1xyXG4gIHByaXZhdGUgbmV3VG9hc3RCZWhhdmlvclN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFRvYXN0TW9kZWxbXT4oW10pO1xyXG4gIHB1YmxpYyBuZXdUb2FzdCQgPSB0aGlzLm5ld1RvYXN0QmVoYXZpb3JTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xyXG4gIHByaXZhdGUgZGVsZXRlVG9hc3RCZWhhdmlvclN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFRvYXN0TW9kZWwgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XHJcbiAgcHVibGljIGRlbGV0ZVRvYXN0JCA9IHRoaXMuZGVsZXRlVG9hc3RCZWhhdmlvclN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcbiAgcHJpdmF0ZSB1cGRhdGVUb2FzdEJlaGF2aW9yU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8VG9hc3RNb2RlbCB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcclxuICBwdWJsaWMgdXBkYXRlVG9hc3QkID0gdGhpcy51cGRhdGVUb2FzdEJlaGF2aW9yU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfdG9hc3R5U291bmRTZXJ2aWNlOiBUb2FzdHlzb3VuZFNlcnZpY2UpIHtcclxuICB9XHJcblxyXG4gIHNldERlZmF1bHREdXJhdGlvbihkOiBudW1iZXIpOiB2b2lkIHsgdGhpcy5UT0FTVFlfU0VSVklDRV9DT05GSUcuZHVyYXRpb24gPSBkOyB9XHJcbiAgZ2V0RGVmYXVsdER1cmF0aW9uKCk6IG51bWJlciB7IHJldHVybiB0aGlzLlRPQVNUWV9TRVJWSUNFX0NPTkZJRy5kdXJhdGlvbjsgfVxyXG4gIHNldENhcGFjaXR5KGM6IG51bWJlcikgeyB0aGlzLlRPQVNUWV9TRVJWSUNFX0NPTkZJRy5jYXBhY2l0eSA9IGM7IHRoaXMucXVldWUuc2V0Q2FwYWNpdHkoYyk7IH1cclxuICBnZXRDYXBhY2l0eSgpOiBudW1iZXIgeyByZXR1cm4gdGhpcy5xdWV1ZS5nZXRDYXBhY2l0eSgpOyB9XHJcblxyXG4gIHNob3dUb2FzdCh0aXRsZTogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcsIHRvYXN0Q29uZmlnPzogVG9hc3R5Q29uZmlnIHwgdW5kZWZpbmVkLCBpc1Byb21pc2U/OiBib29sZWFuKTogbnVtYmVyIHtcclxuICAgIHRoaXMuY291bnRlcisrO1xyXG5cclxuICAgIC8vIGlmIHN0aWNreSBpcyB0cnVlIGR1cmF0aW9uIGlzIGluZmluaXR5IGVsc2UgdXNlIHRoZSBwcm92aWRlZCBkdXJhdGlvbiBvciB0aGUgZGVmYXVsdCBvbmVcclxuICAgIGNvbnN0IGR1cmF0aW9uID0gdG9hc3RDb25maWc/LnN0aWNreSA/IEluZmluaXR5IDogKHRvYXN0Q29uZmlnPy5kdXJhdGlvbiA/PyB0aGlzLlRPQVNUWV9TRVJWSUNFX0NPTkZJRy5kdXJhdGlvbik7XHJcblxyXG4gICAgY29uc3QgdG9hc3Q6IFRvYXN0TW9kZWwgPSB7XHJcbiAgICAgIGlkOiB0aGlzLmNvdW50ZXIsXHJcbiAgICAgIHRpdGxlOiB0aXRsZSxcclxuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcclxuICAgICAgdHlwZTogdG9hc3RDb25maWc/LnR5cGUgPz8gVG9hc3RUeXBlLkJhc2ljLFxyXG4gICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXHJcbiAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcclxuICAgICAgZXhwaXJlczogaXNQcm9taXNlID8gSW5maW5pdHkgOiBEYXRlLm5vdygpICsgZHVyYXRpb24sXHJcbiAgICAgIGNvbmZpZzogdG9hc3RDb25maWcsXHJcbiAgICAgIGdldCBpY29uKCkge1xyXG4gICAgICAgIGlmICh0b2FzdENvbmZpZz8udHlwZSA9PSBUb2FzdFR5cGUuU3VjY2VzcylcclxuICAgICAgICAgIHJldHVybiBcIuKchVwiO1xyXG4gICAgICAgIGlmICh0b2FzdENvbmZpZz8udHlwZSA9PSBUb2FzdFR5cGUuSW5mbylcclxuICAgICAgICAgIHJldHVybiBcIuKEue+4j1wiO1xyXG4gICAgICAgIGlmICh0b2FzdENvbmZpZz8udHlwZSA9PSBUb2FzdFR5cGUuV2FybmluZylcclxuICAgICAgICAgIHJldHVybiBcIuKaoO+4j1wiO1xyXG4gICAgICAgIGlmICh0b2FzdENvbmZpZz8udHlwZSA9PSBUb2FzdFR5cGUuRXJyb3IpXHJcbiAgICAgICAgICByZXR1cm4gXCLinYxcIjtcclxuXHJcbiAgICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgdGhpcy5xdWV1ZS5lbnF1ZXVlKHRvYXN0KTtcclxuXHJcbiAgICB0aGlzLm5ld1RvYXN0QmVoYXZpb3JTdWJqZWN0Lm5leHQoWy4uLnRoaXMucXVldWUuZ2V0RWxlbWVudHMoKV0pO1xyXG5cclxuICAgIGlmICh0b2FzdC5jb25maWc/LmJlZXApIHtcclxuICAgICAgdGhpcy5fdG9hc3R5U291bmRTZXJ2aWNlLm5vdGlmeSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGlmIHN0aWNreSBwcm9ncmVzcyBiYXIgaXMgbm90IGFuaW1hdGVkIGFuZCB0b2FzdCB3aWxsIG5vdCBleHBpcmVcclxuICAgIGlmICghdG9hc3QuY29uZmlnPy5zdGlja3kpIHtcclxuICAgICAgaWYgKHRvYXN0LmNvbmZpZz8ucHJvZ3Jlc3NCYXIpIHtcclxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgIHRoaXMudXBkYXRlVG9hc3QodG9hc3QuaWQsIHsgYW5pbWF0ZVBiYXI6IHRydWUgfSk7XHJcbiAgICAgICAgfSwgMTAwKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKCFpc1Byb21pc2UpIHtcclxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgIHRoaXMucmVtb3ZlVG9hc3QodG9hc3QuaWQpO1xyXG4gICAgICAgIH0sIGR1cmF0aW9uICsgNSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpcy5jb3VudGVyO1xyXG4gIH1cclxuXHJcbiAgc2hvd1RvYXN0UHJvbWlzZTxUPih0aXRsZTogc3RyaW5nLCBwcm9taXNlOiBUb2FzdHlQcm9taXNlPFQ+LCBjb25maWc/OiBUb2FzdHlDb25maWcpIHtcclxuICAgIGNvbnN0IGlkdG9hc3QgPSB0aGlzLnNob3dUb2FzdCh0aXRsZSwgcHJvbWlzZS5sb2FkaW5nLCB7IC4uLmNvbmZpZywgbG9hZGluZzogdHJ1ZSB9LCB0cnVlKTtcclxuICAgIGNvbnN0IGR1cmF0aW9uID0gY29uZmlnPy5kdXJhdGlvbiA/PyB0aGlzLlRPQVNUWV9TRVJWSUNFX0NPTkZJRy5kdXJhdGlvbjtcclxuXHJcbiAgICBwcm9taXNlLnByb21pc2VcclxuICAgICAgLnRoZW4oKHJlc3VsdCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IHN1Y2Nlc3NNZXNzYWdlID1cclxuICAgICAgICAgIHR5cGVvZiBwcm9taXNlLnN1Y2Nlc3MgPT09ICdmdW5jdGlvbidcclxuICAgICAgICAgICAgPyBwcm9taXNlLnN1Y2Nlc3MocmVzdWx0KVxyXG4gICAgICAgICAgICA6IHByb21pc2Uuc3VjY2VzcztcclxuXHJcbiAgICAgICAgdGhpcy51cGRhdGVUb2FzdChpZHRvYXN0LCB7XHJcbiAgICAgICAgICBtZXNzYWdlOiBzdWNjZXNzTWVzc2FnZSxcclxuICAgICAgICAgIHR5cGU6IFRvYXN0VHlwZS5TdWNjZXNzLFxyXG4gICAgICAgICAgZXhwaXJlczogRGF0ZS5ub3coKSArIGR1cmF0aW9uLFxyXG4gICAgICAgICAgY29uZmlnOiB7IGxvYWRpbmc6IGZhbHNlIH1cclxuICAgICAgICB9KTtcclxuICAgICAgfSlcclxuICAgICAgLmNhdGNoKChlcnIpID0+IHtcclxuICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPVxyXG4gICAgICAgICAgdHlwZW9mIHByb21pc2UuZXJyb3IgPT09ICdmdW5jdGlvbidcclxuICAgICAgICAgICAgPyBwcm9taXNlLmVycm9yKGVycilcclxuICAgICAgICAgICAgOiBwcm9taXNlLmVycm9yO1xyXG5cclxuICAgICAgICB0aGlzLnVwZGF0ZVRvYXN0KGlkdG9hc3QsIHtcclxuICAgICAgICAgIG1lc3NhZ2U6IGVycm9yTWVzc2FnZSxcclxuICAgICAgICAgIHR5cGU6IFRvYXN0VHlwZS5FcnJvcixcclxuICAgICAgICAgIGV4cGlyZXM6IERhdGUubm93KCkgKyBkdXJhdGlvbixcclxuICAgICAgICAgIGNvbmZpZzogeyBsb2FkaW5nOiBmYWxzZSB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pXHJcbiAgICAgIC5maW5hbGx5KCgpID0+IHtcclxuICAgICAgICBpZiAoIWNvbmZpZz8uc3RpY2t5KVxyXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnJlbW92ZVRvYXN0KGlkdG9hc3QpLCBkdXJhdGlvbilcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcblxyXG4gIH1cclxuXHJcbiAgcmVtb3ZlVG9hc3QoaWQ6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5uZXdUb2FzdEJlaGF2aW9yU3ViamVjdC5uZXh0KFsuLi50aGlzLnF1ZXVlLmdldEVsZW1lbnRzKCldKTsgLy8gVHJpZ2dlciByZS1yZW5kZXIgdG8gc3RhcnQgZXhpdCBhbmltYXRpb25cclxuICAgIHNldFRpbWVvdXQoKCkgPT4geyBjb25zdCB0ID0gdGhpcy5xdWV1ZS5yZW1vdmVJZChpZCk7IHRoaXMubmV3VG9hc3RCZWhhdmlvclN1YmplY3QubmV4dChbLi4udGhpcy5xdWV1ZS5nZXRFbGVtZW50cygpXSk7fSwgNTAwKTsgLy8gV2FpdCBmb3IgYW5pbWF0aW9uIHRvIGZpbmlzaCBiZWZvcmUgcmVtb3ZpbmcgZnJvbSBxdWV1ZVxyXG4gIH1cclxuXHJcbiAgY2xvc2VUb2FzdChpZDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBjb25zdCB0ID0gdGhpcy5xdWV1ZS5yZW1vdmVJZChpZCk7XHJcbiAgICB0aGlzLm5ld1RvYXN0QmVoYXZpb3JTdWJqZWN0Lm5leHQoWy4uLnRoaXMucXVldWUuZ2V0RWxlbWVudHMoKV0pO1xyXG4gIH1cclxuXHJcbiAgdXBkYXRlVG91Y2hTdGFydChpZDogbnVtYmVyLCB0b3VjaDogVG91Y2gpOiB2b2lkIHtcclxuICAgIGNvbnN0IGdlc3R1cmU6IFRvYXN0R2VzdHVyZSA9IHsgZGF0ZTogRGF0ZS5ub3coKSwgdG91Y2hTdGFydDogdG91Y2ggfTtcclxuICAgIHRoaXMudXBkYXRlVG9hc3QoaWQsIHsgZ2VzdHVyZTogZ2VzdHVyZSB9KTtcclxuICB9XHJcblxyXG4gIC8vIExvb3BzIHRocm91Z2ggdGhlIHRvYXN0cyB0byBmaW5kIHdoaWNoIG9uZSB3YXMgdG91Y2hlZCBhbmQgdXBkYXRlcyBpdHMgdG91Y2hFbmRcclxuICB1cGRhdGVUb3VjaEVuZCh0b3VjaDogVG91Y2gpOiB2b2lkIHtcclxuICAgIGNvbnN0IHRvYXN0cyA9IHRoaXMucXVldWUuZ2V0RWxlbWVudHMoKS5mb3JFYWNoKFxyXG4gICAgICB0ID0+IHtcclxuICAgICAgICBpZiAodC5nZXN0dXJlKSB7XHJcbiAgICAgICAgICBjb25zdCBkZWx0YVkgPSBNYXRoLmFicyh0b3VjaC5jbGllbnRZIC0gdC5nZXN0dXJlLnRvdWNoU3RhcnQhLmNsaWVudFkpO1xyXG4gICAgICAgICAgY29uc3QgZGVsdGFYID0gTWF0aC5hYnModG91Y2guY2xpZW50WCAtIHQuZ2VzdHVyZS50b3VjaFN0YXJ0IS5jbGllbnRYKTtcclxuICAgICAgICAgIGNvbnN0IGRlbHRhVGltZSA9IERhdGUubm93KCkgLSB0Lmdlc3R1cmUuZGF0ZTtcclxuXHJcbiAgICAgICAgICBpZiAoZGVsdGFUaW1lIDwgNTAwICYmIGRlbHRhWCA+IHRoaXMuVE9BU1RZX1NFUlZJQ0VfQ09ORklHLnRocmVzaG9sZF9vZmZzZXRYKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2xvc2VUb2FzdCh0LmlkKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICB0Lmdlc3R1cmUgPSB1bmRlZmluZWQ7IC8vIFJlc2V0IGdlc3R1cmUgaWYgbm90IHN3aXBlZFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgKVxyXG4gIH1cclxuXHJcbiAgdXBkYXRlVG91Y2hNb3ZlKHRvdWNoOiBUb3VjaCk6IHZvaWQge1xyXG4gICAgY29uc3QgdG9hc3RzID0gdGhpcy5xdWV1ZS5nZXRFbGVtZW50cygpO1xyXG4gICAgdG9hc3RzLmZvckVhY2godCA9PiB7XHJcbiAgICAgIGlmICh0Lmdlc3R1cmUpIHtcclxuICAgICAgICBjb25zdCBkZWx0YVggPSB0b3VjaC5jbGllbnRYIC0gdC5nZXN0dXJlLnRvdWNoU3RhcnQhLmNsaWVudFg7XHJcbiAgICAgICAgdC5nZXN0dXJlLm9mZnNldFggPSBkZWx0YVg7IC8vIFN0b3JlIHRoZSBvZmZzZXQgZm9yIHBvdGVudGlhbCB1c2UgaW4gVUkgdXBkYXRlc1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlVG9hc3QoaWQ6IG51bWJlciwgbmV3RGF0YTogUGFydGlhbDxUb2FzdE1vZGVsPik6IHZvaWQge1xyXG4gICAgY29uc3QgdG9hc3RzID0gdGhpcy5xdWV1ZS5nZXRFbGVtZW50cygpO1xyXG4gICAgY29uc3QgaW5kZXggPSB0b2FzdHMuZmluZEluZGV4KHQgPT4gdC5pZCA9PT0gaWQpO1xyXG5cclxuICAgIGlmIChpbmRleCAhPT0gLTEpIHtcclxuICAgICAgdG9hc3RzW2luZGV4XSA9IHsgLi4udG9hc3RzW2luZGV4XSwgLi4ubmV3RGF0YSB9O1xyXG4gICAgICB0aGlzLm5ld1RvYXN0QmVoYXZpb3JTdWJqZWN0Lm5leHQoWy4uLnRvYXN0c10pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbn1cclxuIl19