ngx-avatar-2
Version:
A universal avatar component for Angular applications that fetches / generates avatar based on the information you have about the user.
330 lines • 31.1 kB
JavaScript
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { AsyncSource } from './sources/async-source';
import { AvatarSource } from './sources/avatar-source.enum';
import { takeWhile, map } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "./sources/source.factory";
import * as i2 from "./avatar.service";
import * as i3 from "@angular/common";
/**
* Universal avatar component that
* generates avatar from different sources
*
* export
* class AvatarComponent
* implements {OnChanges}
*/
export class AvatarComponent {
sourceFactory;
avatarService;
round = true;
size = 50;
textSizeRatio = 3;
bgColor;
fgColor = '#FFF';
borderColor;
style = {};
cornerRadius = 0;
facebook;
twitter;
google;
instagram;
vkontakte;
skype;
gravatar;
github;
custom;
initials;
value;
placeholder;
initialsSize = 0;
clickOnAvatar = new EventEmitter();
isAlive = true;
avatarSrc = null;
avatarText = null;
avatarStyle = {};
hostStyle = {};
currentIndex = -1;
sources = [];
constructor(sourceFactory, avatarService) {
this.sourceFactory = sourceFactory;
this.avatarService = avatarService;
}
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 {
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 = 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: err => {
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 ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.11", ngImport: i0, type: AvatarComponent, deps: [{ token: i1.SourceFactory }, { token: i2.AvatarService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.11", type: AvatarComponent, selector: "ngx-avatar", 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"], initials: ["name", "initials"], value: "value", 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"
[width]="size"
[height]="size"
[ngStyle]="avatarStyle"
(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: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.11", ngImport: i0, type: AvatarComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-avatar', template: `
<div
(click)="onAvatarClicked()"
class="avatar-container"
[ngStyle]="hostStyle"
>
<img
*ngIf="avatarSrc; else textAvatar"
[src]="avatarSrc"
[width]="size"
[height]="size"
[ngStyle]="avatarStyle"
(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: function () { return [{ type: i1.SourceFactory }, { type: i2.AvatarService }]; }, 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']
}], initials: [{
type: Input,
args: ['name']
}], value: [{
type: Input
}], placeholder: [{
type: Input
}], initialsSize: [{
type: Input
}], clickOnAvatar: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXZhdGFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1hdmF0YXItMi9zcmMvbGliL2F2YXRhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFJYixNQUFNLGVBQWUsQ0FBQztBQUd2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHckQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7O0FBSWhEOzs7Ozs7O0dBT0c7QUFvQ0gsTUFBTSxPQUFPLGVBQWU7SUF5RGpCO0lBQ0M7SUF4REgsS0FBSyxHQUFHLElBQUksQ0FBQztJQUViLElBQUksR0FBb0IsRUFBRSxDQUFDO0lBRTNCLGFBQWEsR0FBRyxDQUFDLENBQUM7SUFFbEIsT0FBTyxDQUFxQjtJQUU1QixPQUFPLEdBQUcsTUFBTSxDQUFDO0lBRWpCLFdBQVcsQ0FBcUI7SUFFaEMsS0FBSyxHQUFVLEVBQUUsQ0FBQztJQUVsQixZQUFZLEdBQW9CLENBQUMsQ0FBQztJQUVsQyxRQUFRLENBQWlCO0lBRXpCLE9BQU8sQ0FBaUI7SUFFeEIsTUFBTSxDQUFpQjtJQUV2QixTQUFTLENBQWlCO0lBRTFCLFNBQVMsQ0FBaUI7SUFFMUIsS0FBSyxDQUFpQjtJQUV0QixRQUFRLENBQWlCO0lBRXpCLE1BQU0sQ0FBaUI7SUFFdkIsTUFBTSxDQUFpQjtJQUV2QixRQUFRLENBQWlCO0lBRXpCLEtBQUssQ0FBaUI7SUFFdEIsV0FBVyxDQUFVO0lBRXJCLFlBQVksR0FBb0IsQ0FBQyxDQUFDO0lBR2xDLGFBQWEsR0FBeUIsSUFBSSxZQUFZLEVBQVUsQ0FBQztJQUVqRSxPQUFPLEdBQUcsSUFBSSxD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LE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssVUFBVSxDQUFDLENBQUM7SUFDakYsQ0FBQzt3R0E3UFUsZUFBZTs0RkFBZixlQUFlLG10QkF4QmhCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JUOzs0RkFFVSxlQUFlO2tCQWxDM0IsU0FBUzsrQkFFRSxZQUFZLFlBUVo7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQlQ7Z0lBSU0sS0FBSztzQkFEWCxLQUFLO2dCQUdDLElBQUk7c0JBRFYsS0FBSztnQkFHQyxhQUFhO3NCQURuQixLQUFLO2dCQUdDLE9BQU87c0JBRGIsS0FBSztnQkFHQyxPQUFPO3NCQURiLEtBQUs7Z0JBR0MsV0FBVztzQkFEakIsS0FBSztnQkFHQyxLQUFLO3NCQURYLEtBQUs7Z0JBR0MsWUFBWTtzQkFEbEIsS0FBSztnQkFHQyxRQUFRO3NCQURkLEtBQUs7dUJBQUMsWUFBWTtnQkFHWixPQUFPO3NCQURiLEtBQUs7dUJBQUMsV0FBVztnQkFHWCxNQUFNO3NCQURaLEtBQUs7dUJBQUMsVUFBVTtnQkFHVixTQUFTO3NCQURmLEtBQUs7dUJBQUMsYUFBYTtnQkFHYixTQUFTO3NCQURmLEtBQUs7dUJBQUMsYUFBYTtnQkFHYixLQUFLO3NCQURYLEtBQUs7dUJBQUMsU0FBUztnQkFHVCxRQUFRO3NCQURkLEtBQUs7dUJBQUMsWUFBWTtnQkFHWixNQUFNO3NCQURaLEtBQUs7dUJBQUMsVUFBVTtnQkFHVixNQUFNO3NCQURaLEtBQUs7dUJBQUMsS0FBSztnQkFHTCxRQUFRO3NCQURkLEtBQUs7dUJBQUMsTUFBTTtnQkFHTixLQUFLO3NCQURYLEtBQUs7Z0JBR0MsV0FBVztzQkFEakIsS0FBSztnQkFHQyxZQUFZO3NCQURsQixLQUFLO2dCQUlDLGFBQWE7c0JBRG5CLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbiAgT25DaGFuZ2VzLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBPbkRlc3Ryb3lcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IFNvdXJjZSB9IGZyb20gJy4vc291cmNlcy9zb3VyY2UnO1xuaW1wb3J0IHsgQXN5bmNTb3VyY2UgfSBmcm9tICcuL3NvdXJjZXMvYXN5bmMtc291cmNlJztcbmltcG9ydCB7IFNvdXJjZUZhY3RvcnkgfSBmcm9tICcuL3NvdXJjZXMvc291cmNlLmZhY3RvcnknO1xuaW1wb3J0IHsgQXZhdGFyU2VydmljZSB9IGZyb20gJy4vYXZhdGFyLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXZhdGFyU291cmNlIH0gZnJvbSAnLi9zb3VyY2VzL2F2YXRhci1zb3VyY2UuZW51bSc7XG5pbXBvcnQgeyB0YWtlV2hpbGUsIG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxudHlwZSBTdHlsZSA9IFBhcnRpYWw8Q1NTU3R5bGVEZWNsYXJhdGlvbj47XG5cbi8qKlxuICogVW5pdmVyc2FsIGF2YXRhciBjb21wb25lbnQgdGhhdFxuICogZ2VuZXJhdGVzIGF2YXRhciBmcm9tIGRpZmZlcmVudCBzb3VyY2VzXG4gKlxuICogZXhwb3J0XG4gKiBjbGFzcyBBdmF0YXJDb21wb25lbnRcbiAqIGltcGxlbWVudHMge09uQ2hhbmdlc31cbiAqL1xuXG5AQ29tcG9uZW50KHtcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxuICBzZWxlY3RvcjogJ25neC1hdmF0YXInLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICA6aG9zdCB7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICAgIH1cbiAgICBgXG4gIF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdlxuICAgICAgKGNsaWNrKT1cIm9uQXZhdGFyQ2xpY2tlZCgpXCJcbiAgICAgIGNsYXNzPVwiYXZhdGFyLWNvbnRhaW5lclwiXG4gICAgICBbbmdTdHlsZV09XCJob3N0U3R5bGVcIlxuICAgID5cbiAgICAgIDxpbWdcbiAgICAgICAgKm5nSWY9XCJhdmF0YXJTcmM7IGVsc2UgdGV4dEF2YXRhclwiXG4gICAgICAgIFtzcmNdPVwiYXZhdGFyU3JjXCJcbiAgICAgICAgW3dpZHRoXT1cInNpemVcIlxuICAgICAgICBbaGVpZ2h0XT1cInNpemVcIlxuICAgICAgICBbbmdTdHlsZV09XCJhdmF0YXJTdHlsZVwiXG4gICAgICAgIChlcnJvcik9XCJmZXRjaEF2YXRhclNvdXJjZSgpXCJcbiAgICAgICAgY2xhc3M9XCJhdmF0YXItY29udGVudFwiXG4gICAgICAgIGxvYWRpbmc9XCJsYXp5XCJcbiAgICAgIC8+XG4gICAgICA8bmctdGVtcGxhdGUgI3RleHRBdmF0YXI+XG4gICAgICAgIDxkaXYgKm5nSWY9XCJhdmF0YXJUZXh0XCIgY2xhc3M9XCJhdmF0YXItY29udGVudFwiIFtuZ1N0eWxlXT1cImF2YXRhclN0eWxlXCI+XG4gICAgICAgICAge3sgYXZhdGFyVGV4dCB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9kaXY+XG4gIGBcbn0pXG5leHBvcnQgY2xhc3MgQXZhdGFyQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKVxuICBwdWJsaWMgcm91bmQgPSB0cnVlO1xuICBASW5wdXQoKVxuICBwdWJsaWMgc2l6ZTogc3RyaW5nIHwgbnVtYmVyID0gNTA7XG4gIEBJbnB1dCgpXG4gIHB1YmxpYyB0ZXh0U2l6ZVJhdGlvID0gMztcbiAgQElucHV0KClcbiAgcHVibGljIGJnQ29sb3I6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgQElucHV0KClcbiAgcHVibGljIGZnQ29sb3IgPSAnI0ZGRic7XG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBib3JkZXJDb2xvcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBASW5wdXQoKVxuICBwdWJsaWMgc3R5bGU6IFN0eWxlID0ge307XG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjb3JuZXJSYWRpdXM6IHN0cmluZyB8IG51bWJlciA9IDA7XG4gIEBJbnB1dCgnZmFjZWJvb2tJZCcpXG4gIHB1YmxpYyBmYWNlYm9vaz86IHN0cmluZyB8IG51bGw7XG4gIEBJbnB1dCgndHdpdHRlcklkJylcbiAgcHVibGljIHR3aXR0ZXI/OiBzdHJpbmcgfCBudWxsO1xuICBASW5wdXQoJ2dvb2dsZUlkJylcbiAgcHVibGljIGdvb2dsZT86IHN0cmluZyB8IG51bGw7XG4gIEBJbnB1dCgnaW5zdGFncmFtSWQnKVxuICBwdWJsaWMgaW5zdGFncmFtPzogc3RyaW5nIHwgbnVsbDtcbiAgQElucHV0KCd2a29udGFrdGVJZCcpXG4gIHB1YmxpYyB2a29udGFrdGU/OiBzdHJpbmcgfCBudWxsO1xuICBASW5wdXQoJ3NreXBlSWQnKVxuICBwdWJsaWMgc2t5cGU/OiBzdHJpbmcgfCBudWxsO1xuICBASW5wdXQoJ2dyYXZhdGFySWQnKVxuICBwdWJsaWMgZ3JhdmF0YXI/OiBzdHJpbmcgfCBudWxsO1xuICBASW5wdXQoJ2dpdGh1YklkJylcbiAgcHVibGljIGdpdGh1Yj86IHN0cmluZyB8IG51bGw7XG4gIEBJbnB1dCgnc3JjJylcbiAgcHVibGljIGN1c3RvbT86IHN0cmluZyB8IG51bGw7XG4gIEBJbnB1dCgnbmFtZScpXG4gIHB1YmxpYyBpbml0aWFscz86IHN0cmluZyB8IG51bGw7XG4gIEBJbnB1dCgpXG4gIHB1YmxpYyB2YWx1ZT86IHN0cmluZyB8IG51bGw7XG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBwbGFjZWhvbGRlcj86IHN0cmluZztcbiAgQElucHV0KClcbiAgcHVibGljIGluaXRpYWxzU2l6ZTogc3RyaW5nIHwgbnVtYmVyID0gMDtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIGNsaWNrT25BdmF0YXI6IEV2ZW50RW1pdHRlcjxTb3VyY2U+ID0gbmV3IEV2ZW50RW1pdHRlcjxTb3VyY2U+KCk7XG5cbiAgcHVibGljIGlzQWxpdmUgPSB0cnVlO1xuICBwdWJsaWMgYXZhdGFyU3JjOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIGF2YXRhclRleHQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgYXZhdGFyU3R5bGU6IFN0eWxlID0ge307XG4gIHB1YmxpYyBob3N0U3R5bGU6IFN0eWxlID0ge307XG5cbiAgcHJpdmF0ZSBjdXJyZW50SW5kZXggPSAtMTtcbiAgcHJpdmF0ZSBzb3VyY2VzOiBTb3VyY2VbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBzb3VyY2VGYWN0b3J5OiBTb3VyY2VGYWN0b3J5LFxuICAgIHByaXZhdGUgYXZhdGFyU2VydmljZTogQXZhdGFyU2VydmljZVxuICApIHt9XG5cbiAgcHVibGljIG9uQXZhdGFyQ2xpY2tlZCgpOiB2b2lkIHtcbiAgICB0aGlzLmNsaWNrT25BdmF0YXIuZW1pdCh0aGlzLnNvdXJjZXNbdGhpcy5jdXJyZW50SW5kZXhdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlY3QgaW5wdXRzIGNoYW5nZVxuICAgKlxuICAgKiBwYXJhbSB7eyBbcHJvcEtleTogc3RyaW5nXTogU2ltcGxlQ2hhbmdlIH19IGNoYW5nZXNcbiAgICpcbiAgICogbWVtYmVyb2YgQXZhdGFyQ29tcG9uZW50XG4gICAqL1xuICBwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGZvciAoY29uc3QgcHJvcE5hbWUgaW4gY2hhbmdlcykge1xuICAgICAgaWYgKHRoaXMuYXZhdGFyU2VydmljZS5pc1NvdXJjZShwcm9wTmFtZSkpIHtcbiAgICAgICAgY29uc3Qgc291cmNlVHlwZTogQXZhdGFyU291cmNlID0gQXZhdGFyU291cmNlW3Byb3BOYW1lLnRvVXBwZXJDYXNlKCkgYXMga2V5b2YgdHlwZW9mIEF2YXRhclNvdXJjZV0gO1xuICAgICAgICBjb25zdCBjdXJyZW50VmFsdWUgPSBjaGFuZ2VzW3Byb3BOYW1lXS5jdXJyZW50VmFsdWU7XG4gICAgICAgIGlmIChjdXJyZW50VmFsdWUgJiYgdHlwZW9mIGN1cnJlbnRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICB0aGlzLmFkZFNvdXJjZShzb3VyY2VUeXBlLCBjdXJyZW50VmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMucmVtb3ZlU291cmNlKHNvdXJjZVR5cGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIHJlaW5pdGlhbGl6ZSB0aGUgYXZhdGFyIGNvbXBvbmVudCB3aGVuIGEgc291cmNlIHByb3BlcnR5IHZhbHVlIGhhcyBjaGFuZ2VkXG4gICAgLy8gdGhlIGZhbGxiYWNrIHN5c3RlbSBtdXN0IGJlIHJlLWludm9rZWQgd2l0aCB0aGUgbmV3IHZhbHVlcy5cbiAgICB0aGlzLmluaXRpYWxpemVBdmF0YXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaCBhdmF0YXIgc291cmNlXG4gICAqXG4gICAqIG1lbWJlck9mIEF2YXRhckNvbXBvbmVudFxuICAgKi9cbiAgcHVibGljIGZldGNoQXZhdGFyU291cmNlKCk6IHZvaWQge1xuICAgIGNvbnN0IHByZXZpb3VzU291cmNlID0gdGhpcy5zb3VyY2VzW3RoaXMuY3VycmVudEluZGV4XTtcbiAgICBpZiAocHJldmlvdXNTb3VyY2UpIHtcbiAgICAgIHRoaXMuYXZhdGFyU2VydmljZS5tYXJrU291cmNlQXNGYWlsZWQocHJldmlvdXNTb3VyY2UpO1xuICAgIH1cblxuICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuZmluZE5leHRTb3VyY2UoKTtcbiAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmF2YXRhclNlcnZpY2UuaXNUZXh0QXZhdGFyKHNvdXJjZS5zb3VyY2VUeXBlKSkge1xuICAgICAgdGhpcy5idWlsZFRleHRBdmF0YXIoc291cmNlKTtcbiAgICAgIHRoaXMuYXZhdGFyU3JjID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5idWlsZEltYWdlQXZhdGFyKHNvdXJjZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBmaW5kTmV4dFNvdXJjZSgpOiBTb3VyY2UgfCBudWxsIHtcbiAgICB3aGlsZSAoKyt0aGlzLmN1cnJlbnRJbmRleCA8IHRoaXMuc291cmNlcy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuc291cmNlc1t0aGlzLmN1cnJlbnRJbmRleF07XG4gICAgICBpZiAoc291cmNlICYmICF0aGlzLmF2YXRhclNlcnZpY2Uuc291cmNlSGFzRmFpbGVkQmVmb3JlKHNvdXJjZSkpIHtcbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmlzQWxpdmUgPSBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIHRoZSBhdmF0YXIgY29tcG9uZW50IGFuZCBpdHMgZmFsbGJhY2sgc3lzdGVtXG4gICAqL1xuICBwcml2YXRlIGluaXRpYWxpemVBdmF0YXIoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50SW5kZXggPSAtMTtcbiAgICBpZiAodGhpcy5zb3VyY2VzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc29ydEF2YXRhclNvdXJjZXMoKTtcbiAgICAgIHRoaXMuZmV0Y2hBdmF0YXJTb3VyY2UoKTtcbiAgICAgIHRoaXMuaG9zdFN0eWxlID0ge1xuICAgICAgICB3aWR0aDogdGhpcy5zaXplICsgJ3B4JyxcbiAgICAgICAgaGVpZ2h0OiB0aGlzLnNpemUgKyAncHgnXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc29ydEF2YXRhclNvdXJjZXMoKTogdm9pZCB7XG4gICAgdGhpcy5zb3VyY2VzLnNvcnQoKHNvdXJjZTEsIHNvdXJjZTIpID0+XG4gICAgICB0aGlzLmF2YXRhclNlcnZpY2UuY29tcGFyZVNvdXJjZXMoc291cmNlMS5zb3VyY2VUeXBlLCBzb3VyY2UyLnNvdXJjZVR5cGUpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRUZXh0QXZhdGFyKGF2YXRhclNvdXJjZTogU291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5hdmF0YXJUZXh0ID0gYXZhdGFyU291cmNlLmdldEF2YXRhcigrdGhpcy5pbml0aWFsc1NpemUpO1xuICAgIHRoaXMuYXZhdGFyU3R5bGUgPSB0aGlzLmdldEluaXRpYWxzU3R5bGUoYXZhdGFyU291cmNlLnNvdXJjZUlkKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRJbWFnZUF2YXRhcihhdmF0YXJTb3VyY2U6IFNvdXJjZSk6IHZvaWQge1xuICAgIHRoaXMuYXZhdGFyU3R5bGUgPSB0aGlzLmdldEltYWdlU3R5bGUoKTtcbiAgICBpZiAoYXZhdGFyU291cmNlIGluc3RhbmNlb2YgQXN5bmNTb3VyY2UpIHtcbiAgICAgIHRoaXMuZmV0Y2hBbmRQcm9jZXNzQXN5bmNBdmF0YXIoYXZhdGFyU291cmNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hdmF0YXJTcmMgPSBhdmF0YXJTb3VyY2UuZ2V0QXZhdGFyKCt0aGlzLnNpemUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiByZXR1cm5zIGluaXRpYWxzIHN0eWxlXG4gICAqXG4gICAqIG1lbWJlck9mIEF2YXRhckNvbXBvbmVudFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRJbml0aWFsc1N0eWxlKGF2YXRhclZhbHVlOiBzdHJpbmcpOiBTdHlsZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG4gICAgICBib3JkZXJSYWRpdXM6IHRoaXMucm91bmQgPyAnMTAwJScgOiB0aGlzLmNvcm5lclJhZGl1cyArICdweCcsXG4gICAgICBib3JkZXI6IHRoaXMuYm9yZGVyQ29sb3IgPyAnMXB4IHNvbGlkICcgKyB0aGlzLmJvcmRlckNvbG9yIDogJycsXG4gICAgICB0ZXh0VHJhbnNmb3JtOiAndXBwZXJjYXNlJyxcbiAgICAgIGNvbG9yOiB0aGlzLmZnQ29sb3IsXG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuYmdDb2xvclxuICAgICAgICA/IHRoaXMuYmdDb2xvclxuICAgICAgICA6IHRoaXMuYXZhdGFyU2VydmljZS5nZXRSYW5kb21Db2xvcihhdmF0YXJWYWx1ZSksXG4gICAgICBmb250OlxuICAgICAgICBNYXRoLmZsb29yKCt0aGlzLnNpemUgLyB0aGlzLnRleHRTaXplUmF0aW8pICtcbiAgICAgICAgJ3B4IEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWYnLFxuICAgICAgbGluZUhlaWdodDogdGhpcy5zaXplICsgJ3B4JyxcbiAgICAgIC4uLnRoaXMuc3R5bGVcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIHJldHVybnMgaW1hZ2Ugc3R5bGVcbiAgICpcbiAgICogbWVtYmVyT2YgQXZhdGFyQ29tcG9uZW50XG4gICAqL1xuICBwcml2YXRlIGdldEltYWdlU3R5bGUoKTogU3R5bGUge1xuICAgIHJldHVybiB7XG4gICAgICBtYXhXaWR0aDogJzEwMCUnLFxuICAgICAgYm9yZGVyUmFkaXVzOiB0aGlzLnJvdW5kID8gJzUwJScgOiB0aGlzLmNvcm5lclJhZGl1cyArICdweCcsXG4gICAgICBib3JkZXI6IHRoaXMuYm9yZGVyQ29sb3IgPyAnMXB4IHNvbGlkICcgKyB0aGlzLmJvcmRlckNvbG9yIDogJycsXG4gICAgICB3aWR0aDogdGhpcy5zaXplICsgJ3B4JyxcbiAgICAgIGhlaWdodDogdGhpcy5zaXplICsgJ3B4JyxcbiAgICAgIC4uLnRoaXMuc3R5bGUsXG4gICAgfTtcbiAgfVxuICAvKipcbiAgICogRmV0Y2ggYXZhdGFyIGltYWdlIGFzeW5jaHJvbm91c2x5LlxuICAgKlxuICAgKiBwYXJhbSB7U291cmNlfSBzb3VyY2UgcmVwcmVzZW50cyBhdmF0YXIgc291cmNlXG4gICAqIG1lbWJlcm9mIEF2YXRhckNvbXBvbmVudFxuICAgKi9cbiAgcHJpdmF0ZSBmZXRjaEFuZFByb2Nlc3NBc3luY0F2YXRhcihzb3VyY2U6IEFzeW5jU291cmNlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXZhdGFyU2VydmljZS5zb3VyY2VIYXNGYWlsZWRCZWZvcmUoc291cmNlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuYXZhdGFyU2VydmljZVxuICAgICAgICAuZmV0Y2hBdmF0YXIoc291cmNlLmdldEF2YXRhcigrdGhpcy5zaXplKSlcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICB0YWtlV2hpbGUoKCkgPT4gdGhpcy5pc0FsaXZlKSxcbiAgICAgICAgICAgIG1hcChyZXNwb25zZSA9PiBzb3VyY2UucHJvY2Vzc1Jlc3BvbnNlKHJlc3BvbnNlLCArdGhpcy5zaXplKSksXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgICAgICBuZXh0OiBhdmF0YXJTcmMgPT4gKHRoaXMuYXZhdGFyU3JjID0gYXZhdGFyU3JjKSxcbiAgICAgICAgICAgIGVycm9yOiBlcnIgPT4ge1xuICAgICAgICAgICAgICB0aGlzLmZldGNoQXZhdGFyU291cmNlKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYXZhdGFyIHNvdXJjZVxuICAgKlxuICAgKiBwYXJhbSBzb3VyY2VUeXBlIGF2YXRhciBzb3VyY2UgdHlwZSBlLmcgZmFjZWJvb2ssdHdpdHRlciwgZXRjLlxuICAgKiBwYXJhbSBzb3VyY2VWYWx1ZSAgc291cmNlIHZhbHVlIGUuZyBmYWNlYm9va0lkIHZhbHVlLCBldGMuXG4gICAqL1xuICBwcml2YXRlIGFkZFNvdXJjZShzb3VyY2VUeXBlOiBBdmF0YXJTb3VyY2UsIHNvdXJjZVZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBzb3VyY2UgPSB0aGlzLnNvdXJjZXMuZmluZChzID0+IHMuc291cmNlVHlwZSA9PT0gc291cmNlVHlwZSk7XG4gICAgaWYgKHNvdXJjZSkge1xuICAgICAgc291cmNlLnNvdXJjZUlkID0gc291cmNlVmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc291cmNlcy5wdXNoKFxuICAgICAgICAgIHRoaXMuc291cmNlRmFjdG9yeS5uZXdJbnN0YW5jZShzb3VyY2VUeXBlLCBzb3VyY2VWYWx1ZSksXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYXZhdGFyIHNvdXJjZVxuICAgKlxuICAgKiBwYXJhbSBzb3VyY2VUeXBlIGF2YXRhciBzb3VyY2UgdHlwZSBlLmcgZmFjZWJvb2ssdHdpdHRlciwgZXRjLlxuICAgKi9cbiAgcHJpdmF0ZSByZW1vdmVTb3VyY2Uoc291cmNlVHlwZTogQXZhdGFyU291cmNlKTogdm9pZCB7XG4gICAgdGhpcy5zb3VyY2VzID0gdGhpcy5zb3VyY2VzLmZpbHRlcihzb3VyY2UgPT4gc291cmNlLnNvdXJjZVR5cGUgIT09IHNvdXJjZVR5cGUpO1xuICB9XG59XG4iXX0=