truly-ui
Version:
Web Components for Desktop Applications.
242 lines (240 loc) • 49.8 kB
JavaScript
/*
MIT License
Copyright (c) 2019 Temainfo Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import { Component, EventEmitter, Input, ViewChild, Output } from '@angular/core';
import { Status } from './enums/status.enum';
import { Subscription } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "./services/chat.service";
import * as i2 from "../i18n/i18n.service";
import * as i3 from "@angular/common";
import * as i4 from "@angular/forms";
import * as i5 from "../avatar/avatar";
import * as i6 from "../icons/icons";
import * as i7 from "./parts/chat-content";
import * as i8 from "../misc/highlight.pipe";
import * as i9 from "./pipes/status-filter.pipe";
let uniqueIdentifier = 0;
export class TlChatList {
set contacts(data) {
this.setDataSource(data);
}
get contacts() {
return this._dataSource;
}
constructor(renderer, change, chatService, i18nService) {
this.renderer = renderer;
this.change = change;
this.chatService = chatService;
this.i18nService = i18nService;
this.maxHeight = '450px';
this.width = '400px';
this.color = 'basic';
this.loadingMessages = false;
this.chatStatus = {
BUSY: '#ffc019',
ONLINE: '#66cc99',
OFFLINE: '#ff3100'
};
this.lastActivityCheck = 0;
this.id = `tl-chatlist-${uniqueIdentifier++}`;
this.readMessage = new EventEmitter();
this.unreadMessages = new EventEmitter();
this.sendMessage = new EventEmitter();
this.changeStatus = new EventEmitter();
this.selectContact = new EventEmitter();
this.transform = '0';
this.selected = 'ONLINE';
this.noContactsFound = this.i18nService.getLocale().ChatList.noContactsFound;
this.searchContact = this.i18nService.getLocale().ChatList.searchContact;
this.insideChat = false;
this.filterControl = '';
this.messages = [];
this.subscription = new Subscription();
}
get online() {
return Status.ONLINE;
}
get offline() {
return Status.OFFLINE;
}
get busy() {
return Status.BUSY;
}
ngOnInit() {
this.listenChangeStatus();
this.listenChangeMessages();
this.listenUnreadMessages();
this.messages = this.chatService.getAllMessages(this.id);
}
ngOnChanges(changes) {
if (changes['contacts'] && changes['contacts'].currentValue && changes['contacts'].currentValue.length > 0) {
this.setDataSource(changes['contacts'].currentValue);
}
}
setDataSource(contacts, user = this.user) {
if (contacts && user && contacts.length > 0) {
if (!user.id) {
throw Error('User id not found');
}
this._dataSource = contacts.filter((item) => item.id !== user.id).map((contact) => {
return {
...contact,
status: this.getStatus(contact)
};
});
this.change.detectChanges();
}
}
listenChangeStatus() {
this.subscription.add(this.chatService.changeStatus.subscribe((value) => {
if (value.chatId === this.id) {
this.setStatus(value.status);
}
}));
}
listenChangeMessages() {
this.subscription.add(this.chatService.allMessages.subscribe((messages) => {
this.messages = messages;
this.change.detectChanges();
}));
}
listenUnreadMessages() {
this.subscription.add(this.chatService.unreadMessages.subscribe((messages) => {
this.unreadMessages.emit(messages);
}));
}
animationContentDone(event) {
if (event.animationName === 'showOffContent') {
this.insideChat = true;
}
}
getUnreadMessages(item) {
if (this.messages.length > 0) {
return this.messages.filter((message) => {
if (message.from && message.to) {
return (!message.viewed && message.from.id === item.id) && (message.to.id === this.user.id);
}
});
}
return [];
}
getFilter(statusSelected) {
if (statusSelected === this.offline) {
return { filter: this.filterControl, status: [this.offline], lastActivityCheck: this.lastActivityCheck };
}
return { filter: this.filterControl, status: [this.online, this.busy], lastActivityCheck: this.lastActivityCheck };
}
trackByFn(index) {
return index;
}
selectPartner(item) {
this.insideChat = true;
this.updatePartner(item);
this.selectContact.emit({ ...item, unreadMessages: this.getUnreadMessages(item) });
this.renderer.setStyle(this.content.nativeElement, 'animation', 'showOffContent 0.2s forwards');
this.chatService.readMessages(this.getUnreadMessages(item), this.user, this.id);
}
updatePartner(item) {
this.partner = item;
}
setStatus(status) {
this.changeStatus.emit({ user: this.user, status: status });
}
onMessage(message) {
const msm = {
id: String(new Date().getTime()),
to: this.partner,
from: this.user,
message: message.value,
time: message.time,
viewed: false
};
this.sendMessage.emit(msm);
}
selectStatus(status) {
if (status === 'ONLINE') {
this.transform = '0';
this.selected = 'ONLINE';
}
else if (status === 'OFFLINE') {
this.transform = '100px';
this.selected = 'OFFLINE';
}
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
getStatus(contact) {
if (this.lastActivityCheck === 0) {
return contact.status;
}
if (this.lastActivityCheck > 0) {
const diffMinutes = this.getDiffMinutes(contact.lastActivity) * 60;
return diffMinutes >= this.lastActivityCheck ? Status.OFFLINE : contact.status;
}
}
getDiffMinutes(lastActivity = new Date()) {
const currentTime = new Date().getTime();
const lastActivityTime = new Date(lastActivity).getTime();
const diff = ((currentTime - lastActivityTime) / 1000) / 60;
return Math.abs(Math.round(diff));
}
}
/** @nocollapse */ TlChatList.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlChatList, deps: [{ token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i1.ChatService }, { token: i2.I18nService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TlChatList.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TlChatList, selector: "tl-chatlist", inputs: { maxHeight: "maxHeight", width: "width", color: "color", loadingMessages: "loadingMessages", chatStatus: "chatStatus", partner: "partner", lastActivityCheck: "lastActivityCheck", id: "id", user: "user", contacts: "contacts" }, outputs: { readMessage: "readMessage", unreadMessages: "unreadMessages", sendMessage: "sendMessage", changeStatus: "changeStatus", selectContact: "selectContact" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div [class]=\"'chat-wrapper ' + color\" [style.width]=\"width\" [style.height]=\"maxHeight\">\n <div class=\"chat-header\">\n <ng-container *ngIf=\"!insideChat; else selectedPartner\">\n <div class=\"chat-wrapper-status\">\n <div class=\"chat-status-selection\" [style.transform]=\"'translateX(' + transform + ')'\"></div>\n <div class=\"chat-status\" [class.selected]=\"selected === 'ONLINE'\" (click)=\"selectStatus('ONLINE')\">\n <span>Online</span>\n </div>\n <div class=\"chat-status\" [class.selected]=\"selected === 'OFFLINE'\" (click)=\"selectStatus('OFFLINE')\">\n <span>Offline</span>\n </div>\n </div>\n </ng-container>\n </div>\n <ng-container *ngIf=\"!insideChat; else chatContent\">\n <div class=\"ui-wrapper-chat\">\n <div class=\"chat-filter-wrapper\">\n <tl-icon class=\"chat-filter-icon\" [lib]=\"'ion'\" [style]=\"'ios'\">search</tl-icon>\n <input class=\"chat-filter-contact\" [placeholder]=\"searchContact\" [(ngModel)]=\"filterControl\">\n </div>\n <div #content class=\"chat-content\" (animationend)=\"animationContentDone($event)\"\n [style.height]=\"'calc(100% - 40px)'\">\n <ng-container *ngTemplateOutlet=\"contactTemplate; context: { status: selected }\"></ng-container>\n </div>\n </div>\n </ng-container>\n</div>\n\n<ng-template #contactTemplate let-statusSelected=\"status\">\n <ng-container *ngIf=\"(contacts | status: getFilter(statusSelected)) as filtered\">\n <ng-container *ngIf=\"filtered.length > 0; else withoutContacts\">\n <ng-container *ngFor=\"let item of filtered; trackBy:trackByFn\">\n <div *ngIf=\"item\" class=\"chat-item\" (click)=\"selectPartner(item)\">\n <tl-avatar [size]=\"'45px'\"\n class=\"chat-img\"\n [style.border]=\"'2px solid ' + chatStatus[item.status]\"\n [src]=\"item?.image\"\n [gravatar]=\"item?.gravatar\" [shape]=\"'circle'\">\n </tl-avatar>\n <div class=\"chat-item-detail\">\n <span [innerHTML]=\"item.name | highlight:filterControl\"></span>\n <span>{{ item.description }}</span>\n </div>\n <div *ngIf=\"getUnreadMessages(item)?.length as messages\"\n class=\"chat-unread-messages\">{{ messages }}\n </div>\n </div>\n </ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #selectedPartner>\n <div class=\"chat-partner-wrapper\">\n <div (click)=\"insideChat = false\" class=\"arrow\">\n <tl-icon [lib]=\"'ion'\" [style]=\"'ios'\">arrow-back</tl-icon>\n </div>\n <div class=\"chat-partner\">\n <span>{{ partner?.name }}</span>\n </div>\n <tl-avatar [size]=\"'30px'\"\n class=\"chat-img\"\n [src]=\"partner?.image\"\n [gravatar]=\"partner?.gravatar\" [shape]=\"'circle'\">\n </tl-avatar>\n </div>\n</ng-template>\n\n<ng-template #chatContent>\n <tl-chat-content\n [id]=\"id\"\n [user]=\"user\"\n [maxHeight]=\"maxHeight\"\n [loadingMessages]=\"loadingMessages\"\n [chatStatus]=\"chatStatus\"\n (readMessage)=\"readMessage.emit($event)\"\n [partner]=\"partner\"\n (message)=\"onMessage($event)\">\n </tl-chat-content>\n</ng-template>\n\n<ng-template #withoutContacts>\n <div class=\"chat-without-contacts\">\n <tl-icon class=\"icon\" [lib]=\"'fa'\" [style]=\"'far'\">sad-tear</tl-icon>\n <span class=\"label\">{{ noContactsFound }}</span>\n </div>\n</ng-template>\n", styles: [".chat-wrapper{min-width:300px!important;position:relative}.chat-wrapper .chat-header{display:flex;position:relative;align-items:center;justify-content:space-evenly;height:35px;flex-wrap:wrap;z-index:1}.chat-wrapper .chat-header section{width:100%;text-align:center}.chat-wrapper .chat-header .chat-wrapper-status{display:grid;position:relative;grid-template-columns:100px 100px;grid-auto-flow:column;grid-template-rows:20px}.chat-wrapper .chat-header .chat-status-selection{position:absolute;width:100px;padding:0 15px;border-radius:10px;height:100%;transition:transform .3s ease-in-out;box-sizing:border-box}.chat-wrapper .chat-header .chat-status{width:100%;height:100%;text-align:center;display:flex;justify-content:center;align-items:center;z-index:0;cursor:pointer;font-size:1.1em;font-variant:all-petite-caps}.chat-wrapper .chat-header .chat-status.selected{transition:all .25s ease-in-out}.chat-wrapper .ui-wrapper-chat{padding:10px;position:relative;height:calc(100% - 35px);box-sizing:border-box}.chat-wrapper .chat-content{overflow-y:auto;overflow-x:hidden;border-top:0}.chat-wrapper .chat-content>.chat-item{display:flex;align-items:center;padding:10px;height:65px;box-sizing:border-box;margin-bottom:10px;border-radius:5px;animation:showInChatItem .25s ease-in forwards;transition:background,border .3s linear;cursor:pointer;border:1px solid transparent}.chat-wrapper .chat-content>.chat-item .chat-img{padding:2px;border-radius:50%;border-style:solid;border-width:2px;justify-content:center;display:flex}.chat-wrapper .chat-content>.chat-item .chat-item-detail{font-family:Segoe UI,serif;display:flex;flex-flow:column;flex:1;padding-left:10px}.chat-wrapper .chat-content>.chat-item .chat-item-detail span:last-child{font-size:.9em;color:#5f5f5f}.chat-wrapper .chat-content>.chat-item .chat-unread-messages{width:25px;height:25px;border-radius:50%;display:flex;justify-content:center;align-items:center;animation:shadow-pulse 1s infinite}.chat-wrapper .chat-content::-webkit-scrollbar{border-radius:5px;width:5px}.chat-wrapper .chat-content::-webkit-scrollbar-track{background:#cccccc}.chat-wrapper .chat-content::-webkit-scrollbar-thumb{background:#8dab9c}.chat-filter-wrapper .chat-filter-icon{font-size:1.5em;position:absolute;line-height:30px;padding:0 10px;color:#989898}.chat-filter-wrapper .chat-filter-contact{height:30px;width:100%;margin-bottom:10px;outline:none;border-radius:3px;padding-left:30px;box-sizing:border-box;font-family:Segoe UI,serif}.chat-partner-wrapper{display:flex;align-items:center;justify-content:flex-start;width:100%;padding:0 10px;color:#fff}.chat-partner-wrapper>.arrow{width:30px;box-sizing:border-box;text-align:center;transition:background .3s ease-in-out;border-radius:5px;cursor:pointer}.chat-partner-wrapper>.arrow:hover{background:#fff;color:#848484;padding:0 8px}.chat-partner-wrapper>.chat-img{position:absolute;right:10px;border-radius:50%;display:flex}.chat-partner-wrapper>.chat-partner{padding:0 10px}.chat-without-contacts{display:flex;align-items:center;justify-content:center;width:100%;height:100%;flex-flow:column;color:#b9b9b9}.chat-without-contacts>.icon{font-size:4em}.chat-without-contacts>.label{font-weight:500;font-family:Segoe UI,serif}@keyframes showInChatItem{0%{opacity:0}to{opacity:1}}@keyframes showOffContent{0%{opacity:1}to{opacity:0}}@keyframes shadow-pulse{0%{box-shadow:0 0 #f36767}to{box-shadow:0 0 0 8px #0000}}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.TlAvatar, selector: "tl-avatar", inputs: ["shape", "size", "src", "gravatar", "icon", "text", "char", "fontColor", "bgColor", "gender", "color"], outputs: ["selected"] }, { kind: "component", type: i6.TlIcons, selector: "tl-icon", inputs: ["icon", "lib", "style", "size", "animation", "color", "align"] }, { kind: "component", type: i7.TlChatContent, selector: "tl-chat-content", inputs: ["id", "maxHeight", "partner", "user", "loadingMessages", "chatStatus"], outputs: ["readMessage", "message"] }, { kind: "pipe", type: i8.HighlightPipe, name: "highlight" }, { kind: "pipe", type: i9.TlStatusFilterPipe, name: "status" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TlChatList, decorators: [{
type: Component,
args: [{ selector: 'tl-chatlist', template: "<div [class]=\"'chat-wrapper ' + color\" [style.width]=\"width\" [style.height]=\"maxHeight\">\n <div class=\"chat-header\">\n <ng-container *ngIf=\"!insideChat; else selectedPartner\">\n <div class=\"chat-wrapper-status\">\n <div class=\"chat-status-selection\" [style.transform]=\"'translateX(' + transform + ')'\"></div>\n <div class=\"chat-status\" [class.selected]=\"selected === 'ONLINE'\" (click)=\"selectStatus('ONLINE')\">\n <span>Online</span>\n </div>\n <div class=\"chat-status\" [class.selected]=\"selected === 'OFFLINE'\" (click)=\"selectStatus('OFFLINE')\">\n <span>Offline</span>\n </div>\n </div>\n </ng-container>\n </div>\n <ng-container *ngIf=\"!insideChat; else chatContent\">\n <div class=\"ui-wrapper-chat\">\n <div class=\"chat-filter-wrapper\">\n <tl-icon class=\"chat-filter-icon\" [lib]=\"'ion'\" [style]=\"'ios'\">search</tl-icon>\n <input class=\"chat-filter-contact\" [placeholder]=\"searchContact\" [(ngModel)]=\"filterControl\">\n </div>\n <div #content class=\"chat-content\" (animationend)=\"animationContentDone($event)\"\n [style.height]=\"'calc(100% - 40px)'\">\n <ng-container *ngTemplateOutlet=\"contactTemplate; context: { status: selected }\"></ng-container>\n </div>\n </div>\n </ng-container>\n</div>\n\n<ng-template #contactTemplate let-statusSelected=\"status\">\n <ng-container *ngIf=\"(contacts | status: getFilter(statusSelected)) as filtered\">\n <ng-container *ngIf=\"filtered.length > 0; else withoutContacts\">\n <ng-container *ngFor=\"let item of filtered; trackBy:trackByFn\">\n <div *ngIf=\"item\" class=\"chat-item\" (click)=\"selectPartner(item)\">\n <tl-avatar [size]=\"'45px'\"\n class=\"chat-img\"\n [style.border]=\"'2px solid ' + chatStatus[item.status]\"\n [src]=\"item?.image\"\n [gravatar]=\"item?.gravatar\" [shape]=\"'circle'\">\n </tl-avatar>\n <div class=\"chat-item-detail\">\n <span [innerHTML]=\"item.name | highlight:filterControl\"></span>\n <span>{{ item.description }}</span>\n </div>\n <div *ngIf=\"getUnreadMessages(item)?.length as messages\"\n class=\"chat-unread-messages\">{{ messages }}\n </div>\n </div>\n </ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #selectedPartner>\n <div class=\"chat-partner-wrapper\">\n <div (click)=\"insideChat = false\" class=\"arrow\">\n <tl-icon [lib]=\"'ion'\" [style]=\"'ios'\">arrow-back</tl-icon>\n </div>\n <div class=\"chat-partner\">\n <span>{{ partner?.name }}</span>\n </div>\n <tl-avatar [size]=\"'30px'\"\n class=\"chat-img\"\n [src]=\"partner?.image\"\n [gravatar]=\"partner?.gravatar\" [shape]=\"'circle'\">\n </tl-avatar>\n </div>\n</ng-template>\n\n<ng-template #chatContent>\n <tl-chat-content\n [id]=\"id\"\n [user]=\"user\"\n [maxHeight]=\"maxHeight\"\n [loadingMessages]=\"loadingMessages\"\n [chatStatus]=\"chatStatus\"\n (readMessage)=\"readMessage.emit($event)\"\n [partner]=\"partner\"\n (message)=\"onMessage($event)\">\n </tl-chat-content>\n</ng-template>\n\n<ng-template #withoutContacts>\n <div class=\"chat-without-contacts\">\n <tl-icon class=\"icon\" [lib]=\"'fa'\" [style]=\"'far'\">sad-tear</tl-icon>\n <span class=\"label\">{{ noContactsFound }}</span>\n </div>\n</ng-template>\n", styles: [".chat-wrapper{min-width:300px!important;position:relative}.chat-wrapper .chat-header{display:flex;position:relative;align-items:center;justify-content:space-evenly;height:35px;flex-wrap:wrap;z-index:1}.chat-wrapper .chat-header section{width:100%;text-align:center}.chat-wrapper .chat-header .chat-wrapper-status{display:grid;position:relative;grid-template-columns:100px 100px;grid-auto-flow:column;grid-template-rows:20px}.chat-wrapper .chat-header .chat-status-selection{position:absolute;width:100px;padding:0 15px;border-radius:10px;height:100%;transition:transform .3s ease-in-out;box-sizing:border-box}.chat-wrapper .chat-header .chat-status{width:100%;height:100%;text-align:center;display:flex;justify-content:center;align-items:center;z-index:0;cursor:pointer;font-size:1.1em;font-variant:all-petite-caps}.chat-wrapper .chat-header .chat-status.selected{transition:all .25s ease-in-out}.chat-wrapper .ui-wrapper-chat{padding:10px;position:relative;height:calc(100% - 35px);box-sizing:border-box}.chat-wrapper .chat-content{overflow-y:auto;overflow-x:hidden;border-top:0}.chat-wrapper .chat-content>.chat-item{display:flex;align-items:center;padding:10px;height:65px;box-sizing:border-box;margin-bottom:10px;border-radius:5px;animation:showInChatItem .25s ease-in forwards;transition:background,border .3s linear;cursor:pointer;border:1px solid transparent}.chat-wrapper .chat-content>.chat-item .chat-img{padding:2px;border-radius:50%;border-style:solid;border-width:2px;justify-content:center;display:flex}.chat-wrapper .chat-content>.chat-item .chat-item-detail{font-family:Segoe UI,serif;display:flex;flex-flow:column;flex:1;padding-left:10px}.chat-wrapper .chat-content>.chat-item .chat-item-detail span:last-child{font-size:.9em;color:#5f5f5f}.chat-wrapper .chat-content>.chat-item .chat-unread-messages{width:25px;height:25px;border-radius:50%;display:flex;justify-content:center;align-items:center;animation:shadow-pulse 1s infinite}.chat-wrapper .chat-content::-webkit-scrollbar{border-radius:5px;width:5px}.chat-wrapper .chat-content::-webkit-scrollbar-track{background:#cccccc}.chat-wrapper .chat-content::-webkit-scrollbar-thumb{background:#8dab9c}.chat-filter-wrapper .chat-filter-icon{font-size:1.5em;position:absolute;line-height:30px;padding:0 10px;color:#989898}.chat-filter-wrapper .chat-filter-contact{height:30px;width:100%;margin-bottom:10px;outline:none;border-radius:3px;padding-left:30px;box-sizing:border-box;font-family:Segoe UI,serif}.chat-partner-wrapper{display:flex;align-items:center;justify-content:flex-start;width:100%;padding:0 10px;color:#fff}.chat-partner-wrapper>.arrow{width:30px;box-sizing:border-box;text-align:center;transition:background .3s ease-in-out;border-radius:5px;cursor:pointer}.chat-partner-wrapper>.arrow:hover{background:#fff;color:#848484;padding:0 8px}.chat-partner-wrapper>.chat-img{position:absolute;right:10px;border-radius:50%;display:flex}.chat-partner-wrapper>.chat-partner{padding:0 10px}.chat-without-contacts{display:flex;align-items:center;justify-content:center;width:100%;height:100%;flex-flow:column;color:#b9b9b9}.chat-without-contacts>.icon{font-size:4em}.chat-without-contacts>.label{font-weight:500;font-family:Segoe UI,serif}@keyframes showInChatItem{0%{opacity:0}to{opacity:1}}@keyframes showOffContent{0%{opacity:1}to{opacity:0}}@keyframes shadow-pulse{0%{box-shadow:0 0 #f36767}to{box-shadow:0 0 0 8px #0000}}\n"] }]
}], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i1.ChatService }, { type: i2.I18nService }]; }, propDecorators: { maxHeight: [{
type: Input
}], width: [{
type: Input
}], color: [{
type: Input
}], loadingMessages: [{
type: Input
}], chatStatus: [{
type: Input
}], partner: [{
type: Input
}], lastActivityCheck: [{
type: Input
}], id: [{
type: Input
}], user: [{
type: Input
}], contacts: [{
type: Input,
args: ['contacts']
}], readMessage: [{
type: Output
}], unreadMessages: [{
type: Output
}], sendMessage: [{
type: Output
}], changeStatus: [{
type: Output
}], selectContact: [{
type: Output
}], content: [{
type: ViewChild,
args: ['content', { static: false }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdGxpc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90cnVseS11aS9zcmMvY29tcG9uZW50cy9jaGF0bGlzdC9jaGF0bGlzdC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RydWx5LXVpL3NyYy9jb21wb25lbnRzL2NoYXRsaXN0L2NoYXRsaXN0Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsT0FBTyxFQUNMLFNBQVMsRUFBYyxZQUFZLEVBQUUsS0FBSyxFQUFhLFNBQVMsRUFBRSxNQUFNLEVBRXpFLE1BQU0sZUFBZSxDQUFDO0FBSXZCLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUMzQyxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sTUFBTSxDQUFDOzs7Ozs7Ozs7OztBQUlsQyxJQUFJLGdCQUFnQixHQUFHLENBQUMsQ0FBQztBQU96QixNQUFNLE9BQU8sVUFBVTtJQXdCckIsSUFDSSxRQUFRLENBQUUsSUFBbUI7UUFDL0IsSUFBSSxDQUFDLGFBQWEsQ0FBRSxJQUFJLENBQUUsQ0FBQztJQUM3QixDQUFDO0lBQ0QsSUFBSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzFCLENBQUM7SUFnQ0QsWUFBb0IsUUFBbUIsRUFDbkIsTUFBeUIsRUFDekIsV0FBd0IsRUFDeEIsV0FBd0I7UUFIeEIsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUNuQixXQUFNLEdBQU4sTUFBTSxDQUFtQjtRQUN6QixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQS9EbkMsY0FBUyxHQUFHLE9BQU8sQ0FBQztRQUVwQixVQUFLLEdBQUcsT0FBTyxDQUFDO1FBRWhCLFVBQUssR0FBRyxPQUFPLENBQUM7UUFFaEIsb0JBQWUsR0FBRyxLQUFLLENBQUM7UUFFeEIsZUFBVSxHQUFl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RyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQU1HLE9BQU87c0JBQWYsS0FBSztnQkFFRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBRUcsRUFBRTtzQkFBVixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFHRixRQUFRO3NCQURYLEtBQUs7dUJBQUMsVUFBVTtnQkFRUCxXQUFXO3NCQUFwQixNQUFNO2dCQUVHLGNBQWM7c0JBQXZCLE1BQU07Z0JBRUcsV0FBVztzQkFBcEIsTUFBTTtnQkFFRyxZQUFZO3NCQUFyQixNQUFNO2dCQUVHLGFBQWE7c0JBQXRCLE1BQU07Z0JBRWdDLE9BQU87c0JBQTdDLFNBQVM7dUJBQUMsU0FBUyxFQUFFLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gTUlUIExpY2Vuc2VcblxuIENvcHlyaWdodCAoYykgMjAxOSBUZW1haW5mbyBTb2Z0d2FyZVxuXG4gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG4gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEVcbiBTT0ZUV0FSRS5cbiAqL1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIElucHV0LCBSZW5kZXJlcjIsIFZpZXdDaGlsZCwgT3V0cHV0LFxuICBPbkRlc3Ryb3ksIE9uSW5pdCwgQ2hhbmdlRGV0ZWN0b3JSZWYsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlc1xufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Q2hhdFN0YXR1c30gZnJvbSAnLi9pbnRlcmZhY2VzL2NoYXQtc3RhdHVzLmludGVyZmFjZSc7XG5pbXBvcnQge0NoYXRDb250YWN0fSBmcm9tICcuL2ludGVyZmFjZXMvY2hhdC1jb250YWN0LmludGVyZmFjZSc7XG5pbXBvcnQge0NoYXRNZXNzYWdlfSBmcm9tICcuL2ludGVyZmFjZXMvY2hhdC1tZXNzYWdlLmludGVyZmFjZSc7XG5pbXBvcnQge1N0YXR1c30gZnJvbSAnLi9lbnVtcy9zdGF0dXMuZW51bSc7XG5pbXBvcnQge1N1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0NoYXRTZXJ2aWNlfSBmcm9tICcuL3NlcnZpY2VzL2NoYXQuc2VydmljZSc7XG5pbXBvcnQge0kxOG5TZXJ2aWNlfSBmcm9tICcuLi9pMThuL2kxOG4uc2VydmljZSc7XG5cbmxldCB1bmlxdWVJZGVudGlmaWVyID0gMDtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndGwtY2hhdGxpc3QnLFxuICB0ZW1wbGF0ZVVybDogJy4vY2hhdGxpc3QuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NoYXRsaXN0LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgVGxDaGF0TGlzdCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuXG4gIEBJbnB1dCgpIG1heEhlaWdodCA9ICc0NTBweCc7XG5cbiAgQElucHV0KCkgd2lkdGggPSAnNDAwcHgnO1xuXG4gIEBJbnB1dCgpIGNvbG9yID0gJ2Jhc2ljJztcblxuICBASW5wdXQoKSBsb2FkaW5nTWVzc2FnZXMgPSBmYWxzZTtcblxuICBASW5wdXQoKSBjaGF0U3RhdHVzOiBDaGF0U3RhdHVzID0ge1xuICAgIEJVU1k6ICcjZmZjMDE5JyxcbiAgICBPTkxJTkU6ICcjNjZjYzk5JyxcbiAgICBPRkZMSU5FOiAnI2ZmMzEwMCdcbiAgfTtcblxuICBASW5wdXQoKSBwYXJ0bmVyOiBDaGF0Q29udGFjdDtcblxuICBASW5wdXQoKSBsYXN0QWN0aXZpdHlDaGVjayA9IDA7XG5cbiAgQElucHV0KCkgaWQgPSBgdGwtY2hhdGxpc3QtJHt1bmlxdWVJZGVudGlmaWVyKyt9YDtcblxuICBASW5wdXQoKSB1c2VyOiBDaGF0Q29udGFjdDtcblxuICBASW5wdXQoJ2NvbnRhY3RzJylcbiAgc2V0IGNvbnRhY3RzKCBkYXRhOiBDaGF0Q29udGFjdFtdICkge1xuICAgIHRoaXMuc2V0RGF0YVNvdXJjZSggZGF0YSApO1xuICB9XG4gIGdldCBjb250YWN0cygpOiBDaGF0Q29udGFjdFtdIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0YVNvdXJjZTtcbiAgfVxuXG4gIEBPdXRwdXQoKSByZWFkTWVzc2FnZTogRXZlbnRFbWl0dGVyPENoYXRNZXNzYWdlW10+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKSB1bnJlYWRNZXNzYWdlczogRXZlbnRFbWl0dGVyPENoYXRNZXNzYWdlW10+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBPdXRwdXQoKSBzZW5kTWVzc2FnZTogRXZlbnRFbWl0dGVyPENoYXRNZXNzYWdlPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgY2hhbmdlU3RhdHVzOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgc2VsZWN0Q29udGFjdDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQFZpZXdDaGlsZCgnY29udGVudCcsIHtzdGF0aWM6IGZhbHNlfSkgY29udGVudDogRWxlbWVudFJlZjtcblxuICBwdWJsaWMgdHJhbnNmb3JtID0gJzAnO1xuXG4gIHB1YmxpYyBzZWxlY3RlZCA9ICdPTkxJTkUnO1xuXG4gIHB1YmxpYyBub0NvbnRhY3RzRm91bmQgPSB0aGlzLmkxOG5TZXJ2aWNlLmdldExvY2FsZSgpLkNoYXRMaXN0Lm5vQ29udGFjdHNGb3VuZDtcblxuICBwdWJsaWMgc2VhcmNoQ29udGFjdCA9IHRoaXMuaTE4blNlcnZpY2UuZ2V0TG9jYWxlKCkuQ2hhdExpc3Quc2VhcmNoQ29udGFjdDtcblxuICBwdWJsaWMgaW5zaWRlQ2hhdCA9IGZhbHNlO1xuXG4gIHB1YmxpYyBmaWx0ZXJDb250cm9sID0gJyc7XG5cbiAgcHJpdmF0ZSBfZGF0YVNvdXJjZTtcblxuICBwdWJsaWMgbWVzc2FnZXMgPSBbXTtcblxuICBwcml2YXRlIHN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgICAgICAgICAgIHByaXZhdGUgY2hhbmdlOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBjaGF0U2VydmljZTogQ2hhdFNlcnZpY2UsXG4gICAgICAgICAgICAgIHByaXZhdGUgaTE4blNlcnZpY2U6IEkxOG5TZXJ2aWNlKSB7XG4gIH1cblxuICBnZXQgb25saW5lKCkge1xuICAgIHJldHVybiBTdGF0dXMuT05MSU5FO1xuICB9XG5cbiAgZ2V0IG9mZmxpbmUoKSB7XG4gICAgcmV0dXJuIFN0YXR1cy5PRkZMSU5FO1xuICB9XG5cbiAgZ2V0IGJ1c3koKSB7XG4gICAgcmV0dXJuIFN0YXR1cy5CVVNZO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5saXN0ZW5DaGFuZ2VTdGF0dXMoKTtcbiAgICB0aGlzLmxpc3RlbkNoYW5nZU1lc3NhZ2VzKCk7XG4gICAgdGhpcy5saXN0ZW5VbnJlYWRNZXNzYWdlcygpO1xuICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLmNoYXRTZXJ2aWNlLmdldEFsbE1lc3NhZ2VzKCB0aGlzLmlkICk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKCBjaGFuZ2VzWydjb250YWN0cyddICYmIGNoYW5nZXNbJ2NvbnRhY3RzJ10uY3VycmVudFZhbHVlICYmIGNoYW5nZXNbJ2NvbnRhY3RzJ10uY3VycmVudFZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc2V0RGF0YVNvdXJjZSggY2hhbmdlc1snY29udGFjdHMnXS5jdXJyZW50VmFsdWUgKTtcbiAgICB9XG4gIH1cblxuICBzZXREYXRhU291cmNlKGNvbnRhY3RzOiBDaGF0Q29udGFjdFtdLCB1c2VyOiBDaGF0Q29udGFjdCA9IHRoaXMudXNlcikge1xuICAgIGlmICggY29udGFjdHMgJiYgdXNlciAmJiBjb250YWN0cy5sZW5ndGggPiAwICkge1xuICAgICAgaWYgKCF1c2VyLmlkKSB7XG4gICAgICAgIHRocm93IEVycm9yKCdVc2VyIGlkIG5vdCBmb3VuZCcpO1xuICAgICAgfVxuICAgICAgdGhpcy5fZGF0YVNvdXJjZSA9IGNvbnRhY3RzLmZpbHRlcigoaXRlbSkgPT4gaXRlbS5pZCAhPT0gdXNlci5pZCkubWFwKChjb250YWN0KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmNvbnRhY3QsXG4gICAgICAgICAgICBzdGF0dXM6IHRoaXMuZ2V0U3RhdHVzKGNvbnRhY3QpXG4gICAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jaGFuZ2UuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIGxpc3RlbkNoYW5nZVN0YXR1cygpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQodGhpcy5jaGF0U2VydmljZS5jaGFuZ2VTdGF0dXMuc3Vic2NyaWJlKCh2YWx1ZTogeyBjaGF0SWQ6IHN0cmluZywgc3RhdHVzOiBTdGF0dXMgfSkgPT4ge1xuICAgICAgaWYgKHZhbHVlLmNoYXRJZCA9PT0gdGhpcy5pZCkge1xuICAgICAgICB0aGlzLnNldFN0YXR1cyh2YWx1ZS5zdGF0dXMpO1xuICAgICAgfVxuICAgIH0pKTtcbiAgfVxuXG4gIGxpc3RlbkNoYW5nZU1lc3NhZ2VzKCkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZCh0aGlzLmNoYXRTZXJ2aWNlLmFsbE1lc3NhZ2VzLnN1YnNjcmliZSgobWVzc2FnZXM6IENoYXRNZXNzYWdlW10pID0+IHtcbiAgICAgIHRoaXMubWVzc2FnZXMgPSBtZXNzYWdlcztcbiAgICAgIHRoaXMuY2hhbmdlLmRldGVjdENoYW5nZXMoKTtcbiAgICB9KSk7XG4gIH1cblxuICBsaXN0ZW5VbnJlYWRNZXNzYWdlcygpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQodGhpcy5jaGF0U2VydmljZS51bnJlYWRNZXNzYWdlcy5zdWJzY3JpYmUoKG1lc3NhZ2VzOiBDaGF0TWVzc2FnZVtdKSA9PiB7XG4gICAgICB0aGlzLnVucmVhZE1lc3NhZ2VzLmVtaXQoIG1lc3NhZ2VzICk7XG4gICAgfSkpO1xuICB9XG5cbiAgYW5pbWF0aW9uQ29udGVudERvbmUoZXZlbnQ6IEFuaW1hdGlvbkV2ZW50KSB7XG4gICAgaWYgKGV2ZW50LmFuaW1hdGlvbk5hbWUgPT09ICdzaG93T2ZmQ29udGVudCcpIHtcbiAgICAgIHRoaXMuaW5zaWRlQ2hhdCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgZ2V0VW5yZWFkTWVzc2FnZXMoaXRlbTogQ2hhdENvbnRhY3QpIHtcbiAgICBpZiAodGhpcy5tZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5maWx0ZXIoKG1lc3NhZ2U6IENoYXRNZXNzYWdlKSA9PiB7XG4gICAgICAgIGlmIChtZXNzYWdlLmZyb20gJiYgbWVzc2FnZS50bykge1xuICAgICAgICAgIHJldHVybiAoIW1lc3NhZ2Uudmlld2VkICYmIG1lc3NhZ2UuZnJvbS5pZCA9PT0gaXRlbS5pZCkgJiYgKG1lc3NhZ2UudG8uaWQgPT09IHRoaXMudXNlci5pZCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBnZXRGaWx0ZXIoc3RhdHVzU2VsZWN0ZWQpIHtcbiAgICBpZiAoc3RhdHVzU2VsZWN0ZWQgPT09IHRoaXMub2ZmbGluZSkge1xuICAgICAgcmV0dXJuIHtmaWx0ZXI6IHRoaXMuZmlsdGVyQ29udHJvbCwgc3RhdHVzOiBbdGhpcy5vZmZsaW5lXSwgbGFzdEFjdGl2aXR5Q2hlY2s6IHRoaXMubGFzdEFjdGl2aXR5Q2hlY2t9O1xuICAgIH1cbiAgICByZXR1cm4ge2ZpbHRlcjogdGhpcy5maWx0ZXJDb250cm9sLCBzdGF0dXM6IFt0aGlzLm9ubGluZSwgdGhpcy5idXN5XSwgbGFzdEFjdGl2aXR5Q2hlY2s6IHRoaXMubGFzdEFjdGl2aXR5Q2hlY2t9O1xuICB9XG5cbiAgdHJhY2tCeUZuKGluZGV4KSB7XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgc2VsZWN0UGFydG5lcihpdGVtOiBDaGF0Q29udGFjdCkge1xuICAgIHRoaXMuaW5zaWRlQ2hhdCA9IHRydWU7XG4gICAgdGhpcy51cGRhdGVQYXJ0bmVyKGl0ZW0pO1xuICAgIHRoaXMuc2VsZWN0Q29udGFjdC5lbWl0KHsuLi5pdGVtLCB1bnJlYWRNZXNzYWdlczogdGhpcy5nZXRVbnJlYWRNZXNzYWdlcyhpdGVtKX0pO1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jb250ZW50Lm5hdGl2ZUVsZW1lbnQsICdhbmltYXRpb24nLCAnc2hvd09mZkNvbnRlbnQgMC4ycyBmb3J3YXJkcycpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UucmVhZE1lc3NhZ2VzKCB0aGlzLmdldFVucmVhZE1lc3NhZ2VzKGl0ZW0pLCB0aGlzLnVzZXIsIHRoaXMuaWQpO1xuICB9XG5cbiAgdXBkYXRlUGFydG5lcihpdGVtOiBDaGF0Q29udGFjdCkge1xuICAgIHRoaXMucGFydG5lciA9IGl0ZW07XG4gIH1cblxuICBzZXRTdGF0dXMoc3RhdHVzOiBTdGF0dXMpIHtcbiAgICB0aGlzLmNoYW5nZVN0YXR1cy5lbWl0KHt1c2VyOiB0aGlzLnVzZXIsIHN0YXR1czogc3RhdHVzfSk7XG4gIH1cblxuICBvbk1lc3NhZ2UobWVzc2FnZTogeyB2YWx1ZTogc3RyaW5nLCB0aW1lOiBEYXRlIH0pIHtcbiAgICBjb25zdCBtc20gPSB7XG4gICAgICBpZDogU3RyaW5nKG5ldyBEYXRlKCkuZ2V0VGltZSgpKSxcbiAgICAgIHRvOiB0aGlzLnBhcnRuZXIsXG4gICAgICBmcm9tOiB0aGlzLnVzZXIsXG4gICAgICBtZXNzYWdlOiBtZXNzYWdlLnZhbHVlLFxuICAgICAgdGltZTogbWVzc2FnZS50aW1lLFxuICAgICAgdmlld2VkOiBmYWxzZVxuICAgIH07XG4gICAgdGhpcy5zZW5kTWVzc2FnZS5lbWl0KG1zbSk7XG4gIH1cblxuICBzZWxlY3RTdGF0dXMoc3RhdHVzKSB7XG4gICAgaWYgKHN0YXR1cyA9PT0gJ09OTElORScpIHtcbiAgICAgIHRoaXMudHJhbnNmb3JtID0gJzAnO1xuICAgICAgdGhpcy5zZWxlY3RlZCA9ICdPTkxJTkUnO1xuICAgIH0gZWxzZSBpZiAoc3RhdHVzID09PSAnT0ZGTElORScpIHtcbiAgICAgIHRoaXMudHJhbnNmb3JtID0gJzEwMHB4JztcbiAgICAgIHRoaXMuc2VsZWN0ZWQgPSAnT0ZGTElORSc7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG5cbiAgcHJpdmF0ZSBnZXRTdGF0dXMoY29udGFjdCkge1xuICAgIGlmICggdGhpcy5sYXN0QWN0aXZpdHlDaGVjayA9PT0gMCApIHtcbiAgICAgIHJldHVybiBjb250YWN0LnN0YXR1cztcbiAgICB9XG5cbiAgICBpZiAoIHRoaXMubGFzdEFjdGl2aXR5Q2hlY2sgPiAwICkge1xuICAgICAgY29uc3QgZGlmZk1pbnV0ZXMgPSB0aGlzLmdldERpZmZNaW51dGVzKGNvbnRhY3QubGFzdEFjdGl2aXR5KSAqIDYwO1xuICAgICAgcmV0dXJuIGRpZmZNaW51dGVzID49IHRoaXMubGFzdEFjdGl2aXR5Q2hlY2sgPyBTdGF0dXMuT0ZGTElORSA6IGNvbnRhY3Quc3RhdHVzO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGlmZk1pbnV0ZXMobGFzdEFjdGl2aXR5ID0gbmV3IERhdGUoKSkge1xuICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgbGFzdEFjdGl2aXR5VGltZSA9IG5ldyBEYXRlKGxhc3RBY3Rpdml0eSkuZ2V0VGltZSgpO1xuICAgIGNvbnN0IGRpZmYgPSAoKGN1cnJlbnRUaW1lIC0gbGFzdEFjdGl2aXR5VGltZSkgLyAxMDAwICkgLyA2MDtcbiAgICByZXR1cm4gTWF0aC5hYnMoTWF0aC5yb3VuZChkaWZmKSk7XG4gIH1cblxufVxuXG4iLCI8ZGl2IFtjbGFzc109XCInY2hhdC13cmFwcGVyICcgKyBjb2xvclwiIFtzdHlsZS53aWR0aF09XCJ3aWR0aFwiIFtzdHlsZS5oZWlnaHRdPVwibWF4SGVpZ2h0XCI+XG4gIDxkaXYgY2xhc3M9XCJjaGF0LWhlYWRlclwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhaW5zaWRlQ2hhdDsgZWxzZSBzZWxlY3RlZFBhcnRuZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjaGF0LXdyYXBwZXItc3RhdHVzXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjaGF0LXN0YXR1cy1zZWxlY3Rpb25cIiBbc3R5bGUudHJhbnNmb3JtXT1cIid0cmFuc2xhdGVYKCcgKyB0cmFuc2Zvcm0gKyAnKSdcIj48L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNoYXQtc3RhdHVzXCIgW2NsYXNzLnNlbGVjdGVkXT1cInNlbGVjdGVkID09PSAnT05MSU5FJ1wiIChjbGljayk9XCJzZWxlY3RTdGF0dXMoJ09OTElORScpXCI+XG4gICAgICAgICAgPHNwYW4+T25saW5lPC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNoYXQtc3RhdHVzXCIgW2NsYXNzLnNlbGVjdGVkXT1cInNlbGVjdGVkID09PSAnT0ZGTElORSdcIiAoY2xpY2spPVwic2VsZWN0U3RhdHVzKCdPRkZMSU5FJylcIj5cbiAgICAgICAgICA8c3Bhbj5PZmZsaW5lPC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2Rpdj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpbnNpZGVDaGF0OyBlbHNlIGNoYXRDb250ZW50XCI+XG4gICAgPGRpdiBjbGFzcz1cInVpLXdyYXBwZXItY2hhdFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNoYXQtZmlsdGVyLXdyYXBwZXJcIj5cbiAgICAgICAgPHRsLWljb24gY2xhc3M9XCJjaGF0LWZpbHRlci1pY29uXCIgW2xpYl09XCInaW9uJ1wiIFtzdHlsZV09XCInaW9zJ1wiPnNlYXJjaDwvdGwtaWNvbj5cbiAgICAgICAgPGlucHV0IGNsYXNzPVwiY2hhdC1maWx0ZXItY29udGFjdFwiIFtwbGFjZWhvbGRlcl09XCJzZWFyY2hDb250YWN0XCIgWyhuZ01vZGVsKV09XCJmaWx0ZXJDb250cm9sXCI+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgI2NvbnRlbnQgY2xhc3M9XCJjaGF0LWNvbnRlbnRcIiAoYW5pbWF0aW9uZW5kKT1cImFuaW1hdGlvbkNvbnRlbnREb25lKCRldmVudClcIlxuICAgICAgICAgICBbc3R5bGUuaGVpZ2h0XT1cIidjYWxjKDEwMCUgLSA0MHB4KSdcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImNvbnRhY3RUZW1wbGF0ZTsgY29udGV4dDogeyBzdGF0dXM6IHNlbGVjdGVkIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgI2NvbnRhY3RUZW1wbGF0ZSBsZXQtc3RhdHVzU2VsZWN0ZWQ9XCJzdGF0dXNcIj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIihjb250YWN0cyB8IHN0YXR1czogZ2V0RmlsdGVyKHN0YXR1c1NlbGVjdGVkKSkgYXMgZmlsdGVyZWRcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZmlsdGVyZWQubGVuZ3RoID4gMDsgZWxzZSB3aXRob3V0Q29udGFjdHNcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZmlsdGVyZWQ7IHRyYWNrQnk6dHJhY2tCeUZuXCI+XG4gICAgICAgIDxkaXYgKm5nSWY9XCJpdGVtXCIgY2xhc3M9XCJjaGF0LWl0ZW1cIiAoY2xpY2spPVwic2VsZWN0UGFydG5lcihpdGVtKVwiPlxuICAgICAgICAgIDx0bC1hdmF0YXIgW3NpemVdPVwiJzQ1cHgnXCJcbiAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiY2hhdC1pbWdcIlxuICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLmJvcmRlcl09XCInMnB4IHNvbGlkICcgKyBjaGF0U3RhdHVzW2l0ZW0uc3RhdHVzXVwiXG4gICAgICAgICAgICAgICAgICAgICBbc3JjXT1cIml0ZW0/LmltYWdlXCJcbiAgICAgICAgICAgICAgICAgICAgIFtncmF2YXRhcl09XCJpdGVtPy5ncmF2YXRhclwiIFtzaGFwZV09XCInY2lyY2xlJ1wiPlxuICAgICAgICAgIDwvdGwtYXZhdGFyPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjaGF0LWl0ZW0tZGV0YWlsXCI+XG4gICAgICAgICAgICA8c3BhbiBbaW5uZXJIVE1MXT1cIml0ZW0ubmFtZSB8IGhpZ2hsaWdodDpmaWx0ZXJDb250cm9sXCI+PC9zcGFuPlxuICAgICAgICAgICAgPHNwYW4+e3sgaXRlbS5kZXNjcmlwdGlvbiB9fTwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiZ2V0VW5yZWFkTWVzc2FnZXMoaXRlbSk/Lmxlbmd0aCBhcyBtZXNzYWdlc1wiXG4gICAgICAgICAgICAgICBjbGFzcz1cImNoYXQtdW5yZWFkLW1lc3NhZ2VzXCI+e3sgbWVzc2FnZXMgfX1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9uZy1jb250YWluZXI+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI3NlbGVjdGVkUGFydG5lcj5cbiAgPGRpdiBjbGFzcz1cImNoYXQtcGFydG5lci13cmFwcGVyXCI+XG4gICAgPGRpdiAoY2xpY2spPVwiaW5zaWRlQ2hhdCA9IGZhbHNlXCIgY2xhc3M9XCJhcnJvd1wiPlxuICAgICAgPHRsLWljb24gW2xpYl09XCInaW9uJ1wiIFtzdHlsZV09XCInaW9zJ1wiPmFycm93LWJhY2s8L3RsLWljb24+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNoYXQtcGFydG5lclwiPlxuICAgICAgPHNwYW4+e3sgcGFydG5lcj8ubmFtZSB9fTwvc3Bhbj5cbiAgICA8L2Rpdj5cbiAgICA8dGwtYXZhdGFyIFtzaXplXT1cIiczMHB4J1wiXG4gICAgICAgICAgICAgICBjbGFzcz1cImNoYXQtaW1nXCJcbiAgICAgICAgICAgICAgIFtzcmNdPVwicGFydG5lcj8uaW1hZ2VcIlxuICAgICAgICAgICAgICAgW2dyYXZhdGFyXT1cInBhcnRuZXI/LmdyYXZhdGFyXCIgW3NoYXBlXT1cIidjaXJjbGUnXCI+XG4gICAgPC90bC1hdmF0YXI+XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNjaGF0Q29udGVudD5cbiAgPHRsLWNoYXQtY29udGVudFxuICAgIFtpZF09XCJpZFwiXG4gICAgW3VzZXJdPVwidXNlclwiXG4gICAgW21heEhlaWdodF09XCJtYXhIZWlnaHRcIlxuICAgIFtsb2FkaW5nTWVzc2FnZXNdPVwibG9hZGluZ01lc3NhZ2VzXCJcbiAgICBbY2hhdFN0YXR1c109XCJjaGF0U3RhdHVzXCJcbiAgICAocmVhZE1lc3NhZ2UpPVwicmVhZE1lc3NhZ2UuZW1pdCgkZXZlbnQpXCJcbiAgICBbcGFydG5lcl09XCJwYXJ0bmVyXCJcbiAgICAobWVzc2FnZSk9XCJvbk1lc3NhZ2UoJGV2ZW50KVwiPlxuICA8L3RsLWNoYXQtY29udGVudD5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjd2l0aG91dENvbnRhY3RzPlxuICA8ZGl2IGNsYXNzPVwiY2hhdC13aXRob3V0LWNvbnRhY3RzXCI+XG4gICAgPHRsLWljb24gY2xhc3M9XCJpY29uXCIgW2xpYl09XCInZmEnXCIgW3N0eWxlXT1cIidmYXInXCI+c2FkLXRlYXI8L3RsLWljb24+XG4gICAgPHNwYW4gY2xhc3M9XCJsYWJlbFwiPnt7IG5vQ29udGFjdHNGb3VuZCB9fTwvc3Bhbj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19