import { Component, Input, OnChanges, OnInit, } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service'; import { StateService } from 'jslib/abstractions/state.service'; import { Utils } from 'jslib/misc/utils'; @Component({ selector: 'app-avatar', template: '', }) export class AvatarComponent implements OnChanges, OnInit { @Input() data: string; @Input() email: string; @Input() size = 45; @Input() charCount = 2; @Input() textColor = '#ffffff'; @Input() fontSize = 20; @Input() fontWeight = 300; @Input() dynamic = false; @Input() circle = false; src: string; constructor(public sanitizer: DomSanitizer, private cryptoFunctionService: CryptoFunctionService, private stateService: StateService) { } ngOnInit() { if (!this.dynamic) { this.generate(); } } ngOnChanges() { if (this.dynamic) { this.generate(); } } private async generate() { const enableGravatars = await this.stateService.get('enableGravatars'); if (enableGravatars && this.email != null) { const hashBytes = await this.cryptoFunctionService.hash(this.email.toLowerCase().trim(), 'md5'); const hash = Utils.fromBufferToHex(hashBytes).toLowerCase(); this.src = 'https://www.gravatar.com/avatar/' + hash + '?s=' + this.size + '&r=pg&d=retro'; } else { let chars: string = null; const upperData = this.data.toUpperCase(); if (this.charCount > 1) { chars = this.getFirstLetters(upperData, this.charCount); } if (chars == null) { chars = upperData.substr(0, this.charCount); } const charObj = this.getCharText(chars); const color = this.stringToColor(upperData); const svg = this.getSvg(this.size, color); svg.appendChild(charObj); const html = window.document.createElement('div').appendChild(svg).outerHTML; const svgHtml = window.btoa(unescape(encodeURIComponent(html))); this.src = 'data:image/svg+xml;base64,' + svgHtml; } } private stringToColor(str: string): string { let hash = 0; for (let i = 0; i < str.length; i++) { // tslint:disable-next-line hash = str.charCodeAt(i) + ((hash << 5) - hash); } let color = '#'; for (let i = 0; i < 3; i++) { // tslint:disable-next-line const value = (hash >> (i * 8)) & 0xFF; color += ('00' + value.toString(16)).substr(-2); } return color; } private getFirstLetters(data: string, count: number): string { const parts = data.split(' '); if (parts.length > 1) { let text = ''; for (let i = 0; i < count; i++) { text += parts[i].substr(0, 1); } return text; } return null; } private getSvg(size: number, color: string): HTMLElement { const svgTag = window.document.createElement('svg'); svgTag.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); svgTag.setAttribute('pointer-events', 'none'); svgTag.setAttribute('width', size.toString()); svgTag.setAttribute('height', size.toString()); svgTag.style.backgroundColor = color; svgTag.style.width = size + 'px'; svgTag.style.height = size + 'px'; return svgTag; } private getCharText(character: string): HTMLElement { const textTag = window.document.createElement('text'); textTag.setAttribute('text-anchor', 'middle'); textTag.setAttribute('y', '50%'); textTag.setAttribute('x', '50%'); textTag.setAttribute('dy', '0.35em'); textTag.setAttribute('pointer-events', 'auto'); textTag.setAttribute('fill', this.textColor); textTag.setAttribute('font-family', '"Open Sans","Helvetica Neue",Helvetica,Arial,' + 'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"'); textTag.textContent = character; textTag.style.fontWeight = this.fontWeight.toString(); textTag.style.fontSize = this.fontSize + 'px'; return textTag; } }