UNPKG

ngx-avatars

Version:

A universal avatar component for Angular applications that fetches / generates avatar based on the information you have about the user.

336 lines 35.2 kB
import { Component, Input, Output, EventEmitter, SecurityContext } from '@angular/core'; import { AsyncSource } from './sources/async-source'; import { SourceFactory } from './sources/source.factory'; import { AvatarService } from './avatar.service'; import { AvatarSource } from './sources/avatar-source.enum'; import { takeWhile, map } from 'rxjs/operators'; import { DomSanitizer } from '@angular/platform-browser'; import * as i0 from "@angular/core"; import * as i1 from "./sources/source.factory"; import * as i2 from "./avatar.service"; import * as i3 from "@angular/platform-browser"; import * as i4 from "@angular/common"; /** * Universal avatar component that * generates avatar from different sources * * export * class AvatarComponent * implements {OnChanges} */ export class AvatarComponent { constructor(sourceFactory, avatarService, sanitizer) { this.sourceFactory = sourceFactory; this.avatarService = avatarService; this.sanitizer = sanitizer; this.round = true; this.size = 50; this.textSizeRatio = 3; this.fgColor = '#FFF'; this.style = {}; this.cornerRadius = 0; this.initialsSize = 0; this.clickOnAvatar = new EventEmitter(); this.isAlive = true; this.avatarSrc = null; this.avatarAlt = null; this.avatarText = null; this.avatarStyle = {}; this.hostStyle = {}; this.currentIndex = -1; this.sources = []; } onAvatarClicked() { this.clickOnAvatar.emit(this.sources[this.currentIndex]); } /** * Detect inputs change * * param {{ [propKey: string]: SimpleChange }} changes * * memberof AvatarComponent */ ngOnChanges(changes) { for (const propName in changes) { if (this.avatarService.isSource(propName)) { const sourceType = AvatarSource[propName.toUpperCase()]; const currentValue = changes[propName].currentValue; if (currentValue && typeof currentValue === 'string') { this.addSource(sourceType, currentValue); } else { const sanitized = this.sanitizer.sanitize(SecurityContext.URL, currentValue); if (sanitized) { this.addSource(sourceType, sanitized); } else { this.removeSource(sourceType); } } } } // reinitialize the avatar component when a source property value has changed // the fallback system must be re-invoked with the new values. this.initializeAvatar(); } /** * Fetch avatar source * * memberOf AvatarComponent */ fetchAvatarSource() { const previousSource = this.sources[this.currentIndex]; if (previousSource) { this.avatarService.markSourceAsFailed(previousSource); } const source = this.findNextSource(); if (!source) { return; } if (this.avatarService.isTextAvatar(source.sourceType)) { this.buildTextAvatar(source); this.avatarSrc = null; } else { this.buildImageAvatar(source); } } findNextSource() { while (++this.currentIndex < this.sources.length) { const source = this.sources[this.currentIndex]; if (source && !this.avatarService.sourceHasFailedBefore(source)) { return source; } } return null; } ngOnDestroy() { this.isAlive = false; } /** * Initialize the avatar component and its fallback system */ initializeAvatar() { this.currentIndex = -1; if (this.sources.length > 0) { this.sortAvatarSources(); this.fetchAvatarSource(); this.hostStyle = { width: this.size + 'px', height: this.size + 'px' }; } } sortAvatarSources() { this.sources.sort((source1, source2) => this.avatarService.compareSources(source1.sourceType, source2.sourceType)); } buildTextAvatar(avatarSource) { this.avatarText = avatarSource.getAvatar(+this.initialsSize); this.avatarStyle = this.getInitialsStyle(avatarSource.sourceId); } buildImageAvatar(avatarSource) { this.avatarStyle = this.getImageStyle(); if (avatarSource instanceof AsyncSource) { this.fetchAndProcessAsyncAvatar(avatarSource); } else { this.avatarSrc = this.sanitizer.bypassSecurityTrustUrl(avatarSource.getAvatar(+this.size)); this.avatarAlt = avatarSource.getAvatar(+this.size); } } /** * * returns initials style * * memberOf AvatarComponent */ getInitialsStyle(avatarValue) { return { textAlign: 'center', borderRadius: this.round ? '100%' : this.cornerRadius + 'px', border: this.borderColor ? '1px solid ' + this.borderColor : '', textTransform: 'uppercase', color: this.fgColor, backgroundColor: this.bgColor ? this.bgColor : this.avatarService.getRandomColor(avatarValue), font: Math.floor(+this.size / this.textSizeRatio) + 'px Helvetica, Arial, sans-serif', lineHeight: this.size + 'px', ...this.style }; } /** * * returns image style * * memberOf AvatarComponent */ getImageStyle() { return { maxWidth: '100%', borderRadius: this.round ? '50%' : this.cornerRadius + 'px', border: this.borderColor ? '1px solid ' + this.borderColor : '', width: this.size + 'px', height: this.size + 'px', ...this.style, }; } /** * Fetch avatar image asynchronously. * * param {Source} source represents avatar source * memberof AvatarComponent */ fetchAndProcessAsyncAvatar(source) { if (this.avatarService.sourceHasFailedBefore(source)) { return; } this.avatarService .fetchAvatar(source.getAvatar(+this.size)) .pipe(takeWhile(() => this.isAlive), map(response => source.processResponse(response, +this.size))) .subscribe({ next: avatarSrc => (this.avatarSrc = avatarSrc), error: () => { this.fetchAvatarSource(); } }); } /** * Add avatar source * * param sourceType avatar source type e.g facebook,twitter, etc. * param sourceValue source value e.g facebookId value, etc. */ addSource(sourceType, sourceValue) { const source = this.sources.find(s => s.sourceType === sourceType); if (source) { source.sourceId = sourceValue; } else { this.sources.push(this.sourceFactory.newInstance(sourceType, sourceValue)); } } /** * Remove avatar source * * param sourceType avatar source type e.g facebook,twitter, etc. */ removeSource(sourceType) { this.sources = this.sources.filter(source => source.sourceType !== sourceType); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AvatarComponent, deps: [{ token: i1.SourceFactory }, { token: i2.AvatarService }, { token: i3.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.2", type: AvatarComponent, selector: "ngx-avatars", inputs: { round: "round", size: "size", textSizeRatio: "textSizeRatio", bgColor: "bgColor", fgColor: "fgColor", borderColor: "borderColor", style: "style", cornerRadius: "cornerRadius", facebook: ["facebookId", "facebook"], twitter: ["twitterId", "twitter"], google: ["googleId", "google"], instagram: ["instagramId", "instagram"], vkontakte: ["vkontakteId", "vkontakte"], skype: ["skypeId", "skype"], gravatar: ["gravatarId", "gravatar"], github: ["githubId", "github"], custom: ["src", "custom"], customAlt: ["alt", "customAlt"], initials: ["name", "initials"], value: "value", referrerpolicy: "referrerpolicy", placeholder: "placeholder", initialsSize: "initialsSize" }, outputs: { clickOnAvatar: "clickOnAvatar" }, usesOnChanges: true, ngImport: i0, template: ` <div (click)="onAvatarClicked()" class="avatar-container" [ngStyle]="hostStyle" > <img *ngIf="avatarSrc; else textAvatar" [src]="avatarSrc" [alt]="(customAlt)? customAlt: avatarAlt" [width]="size" [height]="size" [ngStyle]="avatarStyle" [referrerPolicy]="referrerpolicy" (error)="fetchAvatarSource()" class="avatar-content" loading="lazy" /> <ng-template #textAvatar> <div *ngIf="avatarText" class="avatar-content" [ngStyle]="avatarStyle"> {{ avatarText }} </div> </ng-template> </div> `, isInline: true, styles: [":host{border-radius:50%}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: AvatarComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-avatars', template: ` <div (click)="onAvatarClicked()" class="avatar-container" [ngStyle]="hostStyle" > <img *ngIf="avatarSrc; else textAvatar" [src]="avatarSrc" [alt]="(customAlt)? customAlt: avatarAlt" [width]="size" [height]="size" [ngStyle]="avatarStyle" [referrerPolicy]="referrerpolicy" (error)="fetchAvatarSource()" class="avatar-content" loading="lazy" /> <ng-template #textAvatar> <div *ngIf="avatarText" class="avatar-content" [ngStyle]="avatarStyle"> {{ avatarText }} </div> </ng-template> </div> `, styles: [":host{border-radius:50%}\n"] }] }], ctorParameters: () => [{ type: i1.SourceFactory }, { type: i2.AvatarService }, { type: i3.DomSanitizer }], propDecorators: { round: [{ type: Input }], size: [{ type: Input }], textSizeRatio: [{ type: Input }], bgColor: [{ type: Input }], fgColor: [{ type: Input }], borderColor: [{ type: Input }], style: [{ type: Input }], cornerRadius: [{ type: Input }], facebook: [{ type: Input, args: ['facebookId'] }], twitter: [{ type: Input, args: ['twitterId'] }], google: [{ type: Input, args: ['googleId'] }], instagram: [{ type: Input, args: ['instagramId'] }], vkontakte: [{ type: Input, args: ['vkontakteId'] }], skype: [{ type: Input, args: ['skypeId'] }], gravatar: [{ type: Input, args: ['gravatarId'] }], github: [{ type: Input, args: ['githubId'] }], custom: [{ type: Input, args: ['src'] }], customAlt: [{ type: Input, args: ['alt'] }], initials: [{ type: Input, args: ['name'] }], value: [{ type: Input }], referrerpolicy: [{ type: Input }], placeholder: [{ type: Input }], initialsSize: [{ type: Input }], clickOnAvatar: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXZhdGFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1hdmF0YXJzL3NyYy9saWIvYXZhdGFyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUlaLGVBQWUsRUFDaEIsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQ25ELE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUN2RCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDL0MsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBQzFELE9BQU8sRUFBQyxTQUFTLEVBQUUsR0FBRyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFlBQVksRUFBVyxNQUFNLDJCQUEyQixDQUFDOzs7Ozs7QUFJbEU7Ozs7Ozs7R0FPRztBQXNDSCxNQUFNLE9BQU8sZUFBZTtJQTZEMUIsWUFDUyxhQUE0QixFQUMzQixhQUE0QixFQUM1QixTQUF1QjtRQUZ4QixrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQUMzQixrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQUM1QixjQUFTLEdBQVQsU0FBUyxDQUFjO1FBOUQxQixVQUFLLEdBQUcsSUFBSSxDQUFDO1FBRWIsU0FBSSxHQUFvQixFQUFFLENBQUM7UUFFM0Isa0JBQWEsR0FBRyxDQUFDLENBQUM7UUFJbEIsWUFBTyxHQUFHLE1BQU0sQ0FBQztRQUlqQixVQUFLLEdBQVUsRUFBRSxDQUFDO1FBRWxCLGlCQUFZLEdBQW9CLENBQUMsQ0FBQztRQThCbEMsaUJBQVksR0FBb0IsQ0FBQyxDQUFDO1FBR2xDLGtCQUFhLEdBQXlCLElBQUksWUFBWSxFQUFVLENBQUM7UUFF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WixLQUFLO3VCQUFDLFVBQVU7Z0JBR1YsU0FBUztzQkFEZixLQUFLO3VCQUFDLGFBQWE7Z0JBR2IsU0FBUztzQkFEZixLQUFLO3VCQUFDLGFBQWE7Z0JBR2IsS0FBSztzQkFEWCxLQUFLO3VCQUFDLFNBQVM7Z0JBR1QsUUFBUTtzQkFEZCxLQUFLO3VCQUFDLFlBQVk7Z0JBR1osTUFBTTtzQkFEWixLQUFLO3VCQUFDLFVBQVU7Z0JBR1YsTUFBTTtzQkFEWixLQUFLO3VCQUFDLEtBQUs7Z0JBR0wsU0FBUztzQkFEZixLQUFLO3VCQUFDLEtBQUs7Z0JBR0wsUUFBUTtzQkFEZCxLQUFLO3VCQUFDLE1BQU07Z0JBR04sS0FBSztzQkFEWCxLQUFLO2dCQUdDLGNBQWM7c0JBRHBCLEtBQUs7Z0JBR0MsV0FBVztzQkFEakIsS0FBSztnQkFHQyxZQUFZO3NCQURsQixLQUFLO2dCQUlDLGFBQWE7c0JBRG5CLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBJbnB1dCxcclxuICBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIE9uQ2hhbmdlcyxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIE9uRGVzdHJveSxcclxuICBTZWN1cml0eUNvbnRleHRcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCB7U291cmNlfSBmcm9tICcuL3NvdXJjZXMvc291cmNlJztcclxuaW1wb3J0IHtBc3luY1NvdXJjZX0gZnJvbSAnLi9zb3VyY2VzL2FzeW5jLXNvdXJjZSc7XHJcbmltcG9ydCB7U291cmNlRmFjdG9yeX0gZnJvbSAnLi9zb3VyY2VzL3NvdXJjZS5mYWN0b3J5JztcclxuaW1wb3J0IHtBdmF0YXJTZXJ2aWNlfSBmcm9tICcuL2F2YXRhci5zZXJ2aWNlJztcclxuaW1wb3J0IHtBdmF0YXJTb3VyY2V9IGZyb20gJy4vc291cmNlcy9hdmF0YXItc291cmNlLmVudW0nO1xyXG5pbXBvcnQge3Rha2VXaGlsZSwgbWFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IERvbVNhbml0aXplciwgU2FmZVVybCB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xyXG5cclxudHlwZSBTdHlsZSA9IFBhcnRpYWw8Q1NTU3R5bGVEZWNsYXJhdGlvbj47XHJcblxyXG4vKipcclxuICogVW5pdmVyc2FsIGF2YXRhciBjb21wb25lbnQgdGhhdFxyXG4gKiBnZW5lcmF0ZXMgYXZhdGFyIGZyb20gZGlmZmVyZW50IHNvdXJjZXNcclxuICpcclxuICogZXhwb3J0XHJcbiAqIGNsYXNzIEF2YXRhckNvbXBvbmVudFxyXG4gKiBpbXBsZW1lbnRzIHtPbkNoYW5nZXN9XHJcbiAqL1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAnbmd4LWF2YXRhcnMnLFxyXG4gIHN0eWxlczogW1xyXG4gICAgYFxyXG4gICAgICAgIDpob3N0IHtcclxuICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogNTAlO1xyXG4gICAgICAgIH1cclxuICAgIGBcclxuICBdLFxyXG4gIHRlbXBsYXRlOiBgXHJcbiAgICAgIDxkaXZcclxuICAgICAgICAgICAgICAoY2xpY2spPVwib25BdmF0YXJDbGlja2VkKClcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiYXZhdGFyLWNvbnRhaW5lclwiXHJcbiAgICAgICAgICAgICAgW25nU3R5bGVdPVwiaG9zdFN0eWxlXCJcclxuICAgICAgPlxyXG4gICAgICAgICAgPGltZ1xyXG4gICAgICAgICAgICAgICAgICAqbmdJZj1cImF2YXRhclNyYzsgZWxzZSB0ZXh0QXZhdGFyXCJcclxuICAgICAgICAgICAgICAgICAgW3NyY109XCJhdmF0YXJTcmNcIlxyXG4gICAgICAgICAgICAgICAgICBbYWx0XT1cIihjdXN0b21BbHQpPyBjdXN0b21BbHQ6IGF2YXRhckFsdFwiXHJcbiAgICAgICAgICAgICAgICAgIFt3aWR0aF09XCJzaXplXCJcclxuICAgICAgICAgICAgICAgICAgW2hlaWdodF09XCJzaXplXCJcclxuICAgICAgICAgICAgICAgICAgW25nU3R5bGVdPVwiYXZhdGFyU3R5bGVcIlxyXG4gICAgICAgICAgICAgICAgICBbcmVmZXJyZXJQb2xpY3ldPVwicmVmZXJyZXJwb2xpY3lcIlxyXG4gICAgICAgICAgICAgICAgICAoZXJyb3IpPVwiZmV0Y2hBdmF0YXJTb3VyY2UoKVwiXHJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYXZhdGFyLWNvbnRlbnRcIlxyXG4gICAgICAgICAgICAgICAgICBsb2FkaW5nPVwibGF6eVwiXHJcbiAgICAgICAgICAvPlxyXG4gICAgICAgICAgPG5nLXRlbXBsYXRlICN0ZXh0QXZhdGFyPlxyXG4gICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJhdmF0YXJUZXh0XCIgY2xhc3M9XCJhdmF0YXItY29udGVudFwiIFtuZ1N0eWxlXT1cImF2YXRhclN0eWxlXCI+XHJcbiAgICAgICAgICAgICAgICAgIHt7IGF2YXRhclRleHQgfX1cclxuICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgIDwvZGl2PlxyXG4gIGBcclxufSlcclxuZXhwb3J0IGNsYXNzIEF2YXRhckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyByb3VuZCA9IHRydWU7XHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgc2l6ZTogc3RyaW5nIHwgbnVtYmVyID0gNTA7XHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgdGV4dFNpemVSYXRpbyA9IDM7XHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgYmdDb2xvcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGZnQ29sb3IgPSAnI0ZGRic7XHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgYm9yZGVyQ29sb3I6IHN0cmluZyB8IHVuZGVmaW5lZDtcclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBzdHlsZTogU3R5bGUgPSB7fTtcclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBjb3JuZXJSYWRpdXM6IHN0cmluZyB8IG51bWJlciA9IDA7XHJcbiAgQElucHV0KCdmYWNlYm9va0lkJylcclxuICBwdWJsaWMgZmFjZWJvb2s/OiBzdHJpbmcgfCBudWxsO1xyXG4gIEBJbnB1dCgndHdpdHRlcklkJylcclxuICBwdWJsaWMgdHdpdHRlcj86IHN0cmluZyB8IG51bGw7XHJcbiAgQElucHV0KCdnb29nbGVJZCcpXHJcbiAgcHVibGljIGdvb2dsZT86IHN0cmluZyB8IG51bGw7XHJcbiAgQElucHV0KCdpbnN0YWdyYW1JZCcpXHJcbiAgcHVibGljIGluc3RhZ3JhbT86IHN0cmluZyB8IG51bGw7XHJcbiAgQElucHV0KCd2a29udGFrdGVJZCcpXHJcbiAgcHVibGljIHZrb250YWt0ZT86IHN0cmluZyB8IG51bGw7XHJcbiAgQElucHV0KCdza3lwZUlkJylcclxuICBwdWJsaWMgc2t5cGU/OiBzdHJpbmcgfCBudWxsO1xyXG4gIEBJbnB1dCgnZ3JhdmF0YXJJZCcpXHJcbiAgcHVibGljIGdyYXZhdGFyPzogc3RyaW5nIHwgbnVsbDtcclxuICBASW5wdXQoJ2dpdGh1YklkJylcclxuICBwdWJsaWMgZ2l0aHViPzogc3RyaW5nIHwgbnVsbDtcclxuICBASW5wdXQoJ3NyYycpXHJcbiAgcHVibGljIGN1c3RvbT86IHN0cmluZyB8IFNhZmVVcmwgfCBudWxsO1xyXG4gIEBJbnB1dCgnYWx0JylcclxuICBwdWJsaWMgY3VzdG9tQWx0Pzogc3RyaW5nIHwgbnVsbDtcclxuICBASW5wdXQoJ25hbWUnKVxyXG4gIHB1YmxpYyBpbml0aWFscz86IHN0cmluZyB8IG51bGw7XHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgdmFsdWU/OiBzdHJpbmcgfCBudWxsO1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIHJlZmVycmVycG9saWN5Pzogc3RyaW5nIHwgbnVsbDtcclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBwbGFjZWhvbGRlcj86IHN0cmluZztcclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBpbml0aWFsc1NpemU6IHN0cmluZyB8IG51bWJlciA9IDA7XHJcblxyXG4gIEBPdXRwdXQoKVxyXG4gIHB1YmxpYyBjbGlja09uQXZhdGFyOiBFdmVudEVtaXR0ZXI8U291cmNlPiA9IG5ldyBFdmVudEVtaXR0ZXI8U291cmNlPigpO1xyXG5cclxuICBwdWJsaWMgaXNBbGl2ZSA9IHRydWU7XHJcbiAgcHVibGljIGF2YXRhclNyYzogU2FmZVVybCB8IG51bGwgPSBudWxsO1xyXG4gIHB1YmxpYyBhdmF0YXJBbHQ6IFNhZmVVcmwgfCBudWxsID0gbnVsbDtcclxuICBwdWJsaWMgYXZhdGFyVGV4dDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcbiAgcHVibGljIGF2YXRhclN0eWxlOiBTdHlsZSA9IHt9O1xyXG4gIHB1YmxpYyBob3N0U3R5bGU6IFN0eWxlID0ge307XHJcblxyXG4gIHByaXZhdGUgY3VycmVudEluZGV4ID0gLTE7XHJcbiAgcHJpdmF0ZSBzb3VyY2VzOiBTb3VyY2VbXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHB1YmxpYyBzb3VyY2VGYWN0b3J5OiBTb3VyY2VGYWN0b3J5LFxyXG4gICAgcHJpdmF0ZSBhdmF0YXJTZXJ2aWNlOiBBdmF0YXJTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplclxyXG4gICkge1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uQXZhdGFyQ2xpY2tlZCgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xpY2tPbkF2YXRhci5lbWl0KHRoaXMuc291cmNlc1t0aGlzLmN1cnJlbnRJbmRleF0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGV0ZWN0IGlucHV0cyBjaGFuZ2VcclxuICAgKlxyXG4gICAqIHBhcmFtIHt7IFtwcm9wS2V5OiBzdHJpbmddOiBTaW1wbGVDaGFuZ2UgfX0gY2hhbmdlc1xyXG4gICAqXHJcbiAgICogbWVtYmVyb2YgQXZhdGFyQ29tcG9uZW50XHJcbiAgICovXHJcbiAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgIGZvciAoY29uc3QgcHJvcE5hbWUgaW4gY2hhbmdlcykge1xyXG4gICAgICBpZiAodGhpcy5hdmF0YXJTZXJ2aWNlLmlzU291cmNlKHByb3BOYW1lKSkge1xyXG4gICAgICAgIGNvbnN0IHNvdXJjZVR5cGU6IEF2YXRhclNvdXJjZSA9IEF2YXRhclNvdXJjZVtwcm9wTmFtZS50b1VwcGVyQ2FzZSgpIGFzIGtleW9mIHR5cGVvZiBBdmF0YXJTb3VyY2VdO1xyXG4gICAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGNoYW5nZXNbcHJvcE5hbWVdLmN1cnJlbnRWYWx1ZTtcclxuICAgICAgICBpZiAoY3VycmVudFZhbHVlICYmIHR5cGVvZiBjdXJyZW50VmFsdWUgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICB0aGlzLmFkZFNvdXJjZShzb3VyY2VUeXBlLCBjdXJyZW50VmFsdWUpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zdCBzYW5pdGl6ZWQgPSB0aGlzLnNhbml0aXplci5zYW5pdGl6ZShTZWN1cml0eUNvbnRleHQuVVJMLCBjdXJyZW50VmFsdWUpO1xyXG4gICAgICAgICAgaWYgKHNhbml0aXplZCkge1xyXG4gICAgICAgICAgICB0aGlzLmFkZFNvdXJjZShzb3VyY2VUeXBlLCBzYW5pdGl6ZWQpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5yZW1vdmVTb3VyY2Uoc291cmNlVHlwZSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyByZWluaXRpYWxpemUgdGhlIGF2YXRhciBjb21wb25lbnQgd2hlbiBhIHNvdXJjZSBwcm9wZXJ0eSB2YWx1ZSBoYXMgY2hhbmdlZFxyXG4gICAgLy8gdGhlIGZhbGxiYWNrIHN5c3RlbSBtdXN0IGJlIHJlLWludm9rZWQgd2l0aCB0aGUgbmV3IHZhbHVlcy5cclxuICAgIHRoaXMuaW5pdGlhbGl6ZUF2YXRhcigpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRmV0Y2ggYXZhdGFyIHNvdXJjZVxyXG4gICAqXHJcbiAgICogbWVtYmVyT2YgQXZhdGFyQ29tcG9uZW50XHJcbiAgICovXHJcbiAgcHVibGljIGZldGNoQXZhdGFyU291cmNlKCk6IHZvaWQge1xyXG4gICAgY29uc3QgcHJldmlvdXNTb3VyY2UgPSB0aGlzLnNvdXJjZXNbdGhpcy5jdXJyZW50SW5kZXhdO1xyXG4gICAgaWYgKHByZXZpb3VzU291cmNlKSB7XHJcbiAgICAgIHRoaXMuYXZhdGFyU2VydmljZS5tYXJrU291cmNlQXNGYWlsZWQocHJldmlvdXNTb3VyY2UpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuZmluZE5leHRTb3VyY2UoKTtcclxuICAgIGlmICghc291cmNlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5hdmF0YXJTZXJ2aWNlLmlzVGV4dEF2YXRhcihzb3VyY2Uuc291cmNlVHlwZSkpIHtcclxuICAgICAgdGhpcy5idWlsZFRleHRBdmF0YXIoc291cmNlKTtcclxuICAgICAgdGhpcy5hdmF0YXJTcmMgPSBudWxsO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5idWlsZEltYWdlQXZhdGFyKHNvdXJjZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZpbmROZXh0U291cmNlKCk6IFNvdXJjZSB8IG51bGwge1xyXG4gICAgd2hpbGUgKCsrdGhpcy5jdXJyZW50SW5kZXggPCB0aGlzLnNvdXJjZXMubGVuZ3RoKSB7XHJcbiAgICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuc291cmNlc1t0aGlzLmN1cnJlbnRJbmRleF07XHJcbiAgICAgIGlmIChzb3VyY2UgJiYgIXRoaXMuYXZhdGFyU2VydmljZS5zb3VyY2VIYXNGYWlsZWRCZWZvcmUoc291cmNlKSkge1xyXG4gICAgICAgIHJldHVybiBzb3VyY2U7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuaXNBbGl2ZSA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW5pdGlhbGl6ZSB0aGUgYXZhdGFyIGNvbXBvbmVudCBhbmQgaXRzIGZhbGxiYWNrIHN5c3RlbVxyXG4gICAqL1xyXG4gIHByaXZhdGUgaW5pdGlhbGl6ZUF2YXRhcigpOiB2b2lkIHtcclxuICAgIHRoaXMuY3VycmVudEluZGV4ID0gLTE7XHJcbiAgICBpZiAodGhpcy5zb3VyY2VzLmxlbmd0aCA+IDApIHtcclxuICAgICAgdGhpcy5zb3J0QXZhdGFyU291cmNlcygpO1xyXG4gICAgICB0aGlzLmZldGNoQXZhdGFyU291cmNlKCk7XHJcbiAgICAgIHRoaXMuaG9zdFN0eWxlID0ge1xyXG4gICAgICAgIHdpZHRoOiB0aGlzLnNpemUgKyAncHgnLFxyXG4gICAgICAgIGhlaWdodDogdGhpcy5zaXplICsgJ3B4J1xyXG4gICAgICB9O1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzb3J0QXZhdGFyU291cmNlcygpOiB2b2lkIHtcclxuICAgIHRoaXMuc291cmNlcy5zb3J0KChzb3VyY2UxOiBTb3VyY2UsIHNvdXJjZTI6IFNvdXJjZSkgPT5cclxuICAgICAgdGhpcy5hdmF0YXJTZXJ2aWNlLmNvbXBhcmVTb3VyY2VzKHNvdXJjZTEuc291cmNlVHlwZSwgc291cmNlMi5zb3VyY2VUeXBlKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYnVpbGRUZXh0QXZhdGFyKGF2YXRhclNvdXJjZTogU291cmNlKTogdm9pZCB7XHJcbiAgICB0aGlzLmF2YXRhclRleHQgPSBhdmF0YXJTb3VyY2UuZ2V0QXZhdGFyKCt0aGlzLmluaXRpYWxzU2l6ZSk7XHJcbiAgICB0aGlzLmF2YXRhclN0eWxlID0gdGhpcy5nZXRJbml0aWFsc1N0eWxlKGF2YXRhclNvdXJjZS5zb3VyY2VJZCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJ1aWxkSW1hZ2VBdmF0YXIoYXZhdGFyU291cmNlOiBTb3VyY2UpOiB2b2lkIHtcclxuICAgIHRoaXMuYXZhdGFyU3R5bGUgPSB0aGlzLmdldEltYWdlU3R5bGUoKTtcclxuICAgIGlmIChhdmF0YXJTb3VyY2UgaW5zdGFuY2VvZiBBc3luY1NvdXJjZSkge1xyXG4gICAgICB0aGlzLmZldGNoQW5kUHJvY2Vzc0FzeW5jQXZhdGFyKGF2YXRhclNvdXJjZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmF2YXRhclNyYyA9IHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RVcmwoYXZhdGFyU291cmNlLmdldEF2YXRhcigrdGhpcy5zaXplKSk7XHJcbiAgICAgIHRoaXMuYXZhdGFyQWx0ID0gYXZhdGFyU291cmNlLmdldEF2YXRhcigrdGhpcy5zaXplKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqXHJcbiAgICogcmV0dXJucyBpbml0aWFscyBzdHlsZVxyXG4gICAqXHJcbiAgICogbWVtYmVyT2YgQXZhdGFyQ29tcG9uZW50XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZXRJbml0aWFsc1N0eWxlKGF2YXRhclZhbHVlOiBzdHJpbmcpOiBTdHlsZSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxyXG4gICAgICBib3JkZXJSYWRpdXM6IHRoaXMucm91bmQgPyAnMTAwJScgOiB0aGlzLmNvcm5lclJhZGl1cyArICdweCcsXHJcbiAgICAgIGJvcmRlcjogdGhpcy5ib3JkZXJDb2xvciA/ICcxcHggc29saWQgJyArIHRoaXMuYm9yZGVyQ29sb3IgOiAnJyxcclxuICAgICAgdGV4dFRyYW5zZm9ybTogJ3VwcGVyY2FzZScsXHJcbiAgICAgIGNvbG9yOiB0aGlzLmZnQ29sb3IsXHJcbiAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5iZ0NvbG9yXHJcbiAgICAgICAgPyB0aGlzLmJnQ29sb3JcclxuICAgICAgICA6IHRoaXMuYXZhdGFyU2VydmljZS5nZXRSYW5kb21Db2xvcihhdmF0YXJWYWx1ZSksXHJcbiAgICAgIGZvbnQ6XHJcbiAgICAgICAgTWF0aC5mbG9vcigrdGhpcy5zaXplIC8gdGhpcy50ZXh0U2l6ZVJhdGlvKSArXHJcbiAgICAgICAgJ3B4IEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWYnLFxyXG4gICAgICBsaW5lSGVpZ2h0OiB0aGlzLnNpemUgKyAncHgnLFxyXG4gICAgICAuLi50aGlzLnN0eWxlXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICpcclxuICAgKiByZXR1cm5zIGltYWdlIHN0eWxlXHJcbiAgICpcclxuICAgKiBtZW1iZXJPZiBBdmF0YXJDb21wb25lbnRcclxuICAgKi9cclxuICBwcml2YXRlIGdldEltYWdlU3R5bGUoKTogU3R5bGUge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgbWF4V2lkdGg6ICcxMDAlJyxcclxuICAgICAgYm9yZGVyUmFkaXVzOiB0aGlzLnJvdW5kID8gJzUwJScgOiB0aGlzLmNvcm5lclJhZGl1cyArICdweCcsXHJcbiAgICAgIGJvcmRlcjogdGhpcy5ib3JkZXJDb2xvciA/ICcxcHggc29saWQgJyArIHRoaXMuYm9yZGVyQ29sb3IgOiAnJyxcclxuICAgICAgd2lkdGg6IHRoaXMuc2l6ZSArICdweCcsXHJcbiAgICAgIGhlaWdodDogdGhpcy5zaXplICsgJ3B4JyxcclxuICAgICAgLi4udGhpcy5zdHlsZSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBGZXRjaCBhdmF0YXIgaW1hZ2UgYXN5bmNocm9ub3VzbHkuXHJcbiAgICpcclxuICAgKiBwYXJhbSB7U291cmNlfSBzb3VyY2UgcmVwcmVzZW50cyBhdmF0YXIgc291cmNlXHJcbiAgICogbWVtYmVyb2YgQXZhdGFyQ29tcG9uZW50XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBmZXRjaEFuZFByb2Nlc3NBc3luY0F2YXRhcihzb3VyY2U6IEFzeW5jU291cmNlKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5hdmF0YXJTZXJ2aWNlLnNvdXJjZUhhc0ZhaWxlZEJlZm9yZShzb3VyY2UpKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmF2YXRhclNlcnZpY2VcclxuICAgICAgLmZldGNoQXZhdGFyKHNvdXJjZS5nZXRBdmF0YXIoK3RoaXMuc2l6ZSkpXHJcbiAgICAgIC5waXBlKFxyXG4gICAgICAgIHRha2VXaGlsZSgoKSA9PiB0aGlzLmlzQWxpdmUpLFxyXG4gICAgICAgIG1hcChyZXNwb25zZSA9PiBzb3VyY2UucHJvY2Vzc1Jlc3BvbnNlKHJlc3BvbnNlLCArdGhpcy5zaXplKSlcclxuICAgICAgKVxyXG4gICAgICAuc3Vic2NyaWJlKHtcclxuICAgICAgICBuZXh0OiBhdmF0YXJTcmMgPT4gKHRoaXMuYXZhdGFyU3JjID0gYXZhdGFyU3JjKSxcclxuICAgICAgICBlcnJvcjogKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5mZXRjaEF2YXRhclNvdXJjZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGQgYXZhdGFyIHNvdXJjZVxyXG4gICAqXHJcbiAgICogcGFyYW0gc291cmNlVHlwZSBhdmF0YXIgc291cmNlIHR5cGUgZS5nIGZhY2Vib29rLHR3aXR0ZXIsIGV0Yy5cclxuICAgKiBwYXJhbSBzb3VyY2VWYWx1ZSAgc291cmNlIHZhbHVlIGUuZyBmYWNlYm9va0lkIHZhbHVlLCBldGMuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhZGRTb3VyY2Uoc291cmNlVHlwZTogQXZhdGFyU291cmNlLCBzb3VyY2VWYWx1ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBzb3VyY2UgPSB0aGlzLnNvdXJjZXMuZmluZChzID0+IHMuc291cmNlVHlwZSA9PT0gc291cmNlVHlwZSk7XHJcbiAgICBpZiAoc291cmNlKSB7XHJcbiAgICAgIHNvdXJjZS5zb3VyY2VJZCA9IHNvdXJjZVZhbHVlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5zb3VyY2VzLnB1c2goXHJcbiAgICAgICAgdGhpcy5zb3VyY2VGYWN0b3J5Lm5ld0luc3RhbmNlKHNvdXJjZVR5cGUsIHNvdXJjZVZhbHVlKSxcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlbW92ZSBhdmF0YXIgc291cmNlXHJcbiAgICpcclxuICAgKiBwYXJhbSBzb3VyY2VUeXBlIGF2YXRhciBzb3VyY2UgdHlwZSBlLmcgZmFjZWJvb2ssdHdpdHRlciwgZXRjLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVtb3ZlU291cmNlKHNvdXJjZVR5cGU6IEF2YXRhclNvdXJjZSk6IHZvaWQge1xyXG4gICAgdGhpcy5zb3VyY2VzID0gdGhpcy5zb3VyY2VzLmZpbHRlcihzb3VyY2UgPT4gc291cmNlLnNvdXJjZVR5cGUgIT09IHNvdXJjZVR5cGUpO1xyXG4gIH1cclxufVxyXG4iXX0=