mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-06 09:20:43 +01:00
avatar component
This commit is contained in:
parent
1fb4f2946a
commit
9633800977
@ -16,6 +16,8 @@ import { ServicesModule } from './services/services.module';
|
|||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { ModalComponent } from './modal.component';
|
import { ModalComponent } from './modal.component';
|
||||||
|
|
||||||
|
import { AvatarComponent } from './components/avatar.component';
|
||||||
|
|
||||||
import { FooterComponent } from './layouts/footer.component';
|
import { FooterComponent } from './layouts/footer.component';
|
||||||
import { FrontendLayoutComponent } from './layouts/frontend-layout.component';
|
import { FrontendLayoutComponent } from './layouts/frontend-layout.component';
|
||||||
import { NavbarComponent } from './layouts/navbar.component';
|
import { NavbarComponent } from './layouts/navbar.component';
|
||||||
@ -87,6 +89,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
|
|||||||
AppComponent,
|
AppComponent,
|
||||||
AttachmentsComponent,
|
AttachmentsComponent,
|
||||||
AutofocusDirective,
|
AutofocusDirective,
|
||||||
|
AvatarComponent,
|
||||||
BlurClickDirective,
|
BlurClickDirective,
|
||||||
BoxRowDirective,
|
BoxRowDirective,
|
||||||
BulkDeleteComponent,
|
BulkDeleteComponent,
|
||||||
|
113
src/app/components/avatar.component.ts
Normal file
113
src/app/components/avatar.component.ts
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
Input,
|
||||||
|
OnChanges,
|
||||||
|
OnInit,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-avatar',
|
||||||
|
template: '<img [src]="sanitizer.bypassSecurityTrustResourceUrl(src)" title="{{data}}">',
|
||||||
|
})
|
||||||
|
export class AvatarComponent implements OnChanges, OnInit {
|
||||||
|
@Input() data: string;
|
||||||
|
@Input() width = 45;
|
||||||
|
@Input() height = 45;
|
||||||
|
@Input() charCount = 2;
|
||||||
|
@Input() textColor = '#ffffff';
|
||||||
|
@Input() fontSize = 20;
|
||||||
|
@Input() fontWeight = 300;
|
||||||
|
@Input() dynamic = false;
|
||||||
|
|
||||||
|
src: string;
|
||||||
|
|
||||||
|
constructor(public sanitizer: DomSanitizer) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (!this.dynamic) {
|
||||||
|
this.generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges() {
|
||||||
|
if (this.dynamic) {
|
||||||
|
this.generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private generate() {
|
||||||
|
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.width, this.height, 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(width: number, height: 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', width.toString());
|
||||||
|
svgTag.setAttribute('height', height.toString());
|
||||||
|
svgTag.style.backgroundColor = color;
|
||||||
|
svgTag.style.width = width + 'px';
|
||||||
|
svgTag.style.height = height + '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;
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,9 @@
|
|||||||
<input id="masterPasswordHint" class="form-control" type="text" name="MasterPasswordHint" [(ngModel)]="profile.masterPasswordHint">
|
<input id="masterPasswordHint" class="form-control" type="text" name="MasterPasswordHint" [(ngModel)]="profile.masterPasswordHint">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<app-avatar data="{{profile.name}}" dynamic="true" width="75" height="75" fontSize="35"></app-avatar>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick [disabled]="profileForm.loading">
|
<button type="submit" class="btn btn-primary btn-submit" appBlurClick [disabled]="profileForm.loading">
|
||||||
<i class="fa fa-spinner fa-spin"></i>
|
<i class="fa fa-spinner fa-spin"></i>
|
||||||
|
@ -47,12 +47,12 @@
|
|||||||
<button type="button" class="btn btn-primary" appBlurClick (click)="regenerate()">
|
<button type="button" class="btn btn-primary" appBlurClick (click)="regenerate()">
|
||||||
{{'regeneratePassword' | i18n}}
|
{{'regeneratePassword' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-outline-primary" appBlurClick (click)="copy()">
|
<button type="button" class="btn btn-outline-secondary" appBlurClick (click)="copy()">
|
||||||
{{'copyPassword' | i18n}}
|
{{'copyPassword' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
<button type="button" class="btn btn-outline-primary" appBlurClick (click)="history()" title="{{'passwordHistory' | i18n}}">
|
<button type="button" class="btn btn-outline-secondary" appBlurClick (click)="history()" title="{{'passwordHistory' | i18n}}">
|
||||||
<i class="fa fa-clock-o fa-lg"></i>
|
<i class="fa fa-clock-o fa-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -351,6 +351,12 @@ app-password-generator-history {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app-avatar {
|
||||||
|
img {
|
||||||
|
@extend .rounded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#duo-frame {
|
#duo-frame {
|
||||||
background: url('../images/loading.svg') 0 0 no-repeat;
|
background: url('../images/loading.svg') 0 0 no-repeat;
|
||||||
height: 330px;
|
height: 330px;
|
||||||
|
Loading…
Reference in New Issue
Block a user