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
JavaScript
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=