Replaces Gravatar's fallback image with custom 404 error handling.

pull/4338/head
Victor Usoltsev 3 years ago
parent 66d3ddb043
commit 8178dc6f58

@ -175,8 +175,8 @@
[isAdmin]="isAdmin" [isAdmin]="isAdmin"
[applicationName]="applicationName" [applicationName]="applicationName"
[applicationLogo]="customizationSettings?.logo" [applicationLogo]="customizationSettings?.logo"
[username]="username" [userName]="userName"
[email]="user?.email" [userEmail]="userEmail"
[accessToken]="accessToken" [accessToken]="accessToken"
[applicationUrl]="customizationSettings?.applicationUrl" [applicationUrl]="customizationSettings?.applicationUrl"
(logoutClick)="logOut();" (logoutClick)="logOut();"

@ -24,14 +24,14 @@ export class AppComponent implements OnInit {
public customizationSettings: ICustomizationSettings; public customizationSettings: ICustomizationSettings;
public customPageSettings: ICustomPage; public customPageSettings: ICustomPage;
public user: ILocalUser;
public showNav: boolean; public showNav: boolean;
public updateAvailable: boolean; public updateAvailable: boolean;
public currentUrl: string; public currentUrl: string;
public voteEnabled = false; public voteEnabled = false;
public applicationName: string = "Ombi" public applicationName: string = "Ombi"
public isAdmin: boolean; public isAdmin: boolean;
public username: string; public userName: string;
public userEmail: string;
public accessToken: string; public accessToken: string;
private hubConnected: boolean; private hubConnected: boolean;
@ -53,8 +53,6 @@ export class AppComponent implements OnInit {
this.translate.addLangs(["da", "de", "en", "es", "fr", "it", "hu", "nl", "no", "pl", "pt", "sk", "sv", "bg", "ru"]); this.translate.addLangs(["da", "de", "en", "es", "fr", "it", "hu", "nl", "no", "pl", "pt", "sk", "sv", "bg", "ru"]);
if (this.authService.loggedIn()) { if (this.authService.loggedIn()) {
this.user = this.authService.claims();
this.username = this.user.name;
this.identity.getAccessToken().subscribe(x => this.accessToken = x); this.identity.getAccessToken().subscribe(x => this.accessToken = x);
if (!this.hubConnected) { if (!this.hubConnected) {
this.signalrNotification.initialize(); this.signalrNotification.initialize();
@ -67,6 +65,8 @@ export class AppComponent implements OnInit {
}); });
} }
this.identity.getUser().subscribe(u => { this.identity.getUser().subscribe(u => {
this.userEmail = u.emailAddress;
this.userName = u.userName;
if (u.language) { if (u.language) {
this.translate.use(u.language); this.translate.use(u.language);
} }
@ -116,10 +116,6 @@ export class AppComponent implements OnInit {
if (event instanceof NavigationStart) { if (event instanceof NavigationStart) {
this.isAdmin = this.authService.hasRole("admin"); this.isAdmin = this.authService.hasRole("admin");
this.showNav = this.authService.loggedIn(); this.showNav = this.authService.loggedIn();
if (this.showNav) {
this.user = this.authService.claims();
this.username = this.user.name;
}
} }
}); });
} }

@ -89,8 +89,10 @@
</div> </div>
<div class="profile-block"> <div class="profile-block">
<a routerLink="/user-preferences"> <a routerLink="/user-preferences">
<div class="profile-username" data-test="profile-username">{{username}}</div> <div class="profile-username" data-test="profile-username">{{userName}}</div>
<div class="profile-img" data-test="profile-image"><img [src]="getUserImage()" /></div> <div class="profile-img" data-test="profile-image">
<img [src]="userProfileImageUrl" (error)="onProfileImageError()" >
</div>
</a> </a>
</div> </div>

@ -1,5 +1,5 @@
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core';
import { IUser, RequestType, UserType } from '../interfaces'; import { IUser, RequestType, UserType } from '../interfaces';
import { SettingsService, SettingsStateService } from '../services'; import { SettingsService, SettingsStateService } from '../services';
@ -40,16 +40,16 @@ export class MyNavComponent implements OnInit {
@Input() public applicationLogo: string; @Input() public applicationLogo: string;
@Input() public applicationUrl: string; @Input() public applicationUrl: string;
@Input() public accessToken: string; @Input() public accessToken: string;
@Input() public username: string; @Input() public userName: string;
@Input() public userEmail: string;
@Input() public isAdmin: string; @Input() public isAdmin: string;
@Input() public email: string;
@Output() public logoutClick = new EventEmitter(); @Output() public logoutClick = new EventEmitter();
public theme: string; public theme: string;
public issuesEnabled: boolean = false; public issuesEnabled: boolean = false;
public navItems: INavBar[]; public navItems: INavBar[];
public searchFilter: SearchFilter; public searchFilter: SearchFilter;
public SearchFilterType = SearchFilterType; public SearchFilterType = SearchFilterType;
public emailHash: string | Int32Array; public userProfileImageUrl: string;
public welcomeText: string; public welcomeText: string;
public RequestType = RequestType; public RequestType = RequestType;
@ -63,7 +63,6 @@ export class MyNavComponent implements OnInit {
} }
public async ngOnInit() { public async ngOnInit() {
this.searchFilter = { this.searchFilter = {
movies: true, movies: true,
music: false, music: false,
@ -71,11 +70,7 @@ export class MyNavComponent implements OnInit {
tvShows: true tvShows: true
} }
if (this.email) { this.setProfileImageUrl(this.userEmail)
const md5 = new Md5();
this.emailHash = md5.appendStr(this.email).end();
}
this.issuesEnabled = await this.settingsService.issueEnabled().toPromise(); this.issuesEnabled = await this.settingsService.issueEnabled().toPromise();
this.settingState.setIssue(this.issuesEnabled); this.settingState.setIssue(this.issuesEnabled);
@ -103,6 +98,12 @@ export class MyNavComponent implements OnInit {
]; ];
} }
ngOnChanges(changes: SimpleChanges) {
if(changes?.userEmail || changes?.applicationLogo){
this.setProfileImageUrl(this.userEmail)
}
}
public logOut() { public logOut() {
this.logoutClick.emit(); this.logoutClick.emit();
} }
@ -138,9 +139,27 @@ export class MyNavComponent implements OnInit {
}); });
} }
public getUserImage(): string { private setProfileImageUrl(email: string): void {
var fallback = this.applicationLogo ? this.applicationLogo : 'https://raw.githubusercontent.com/Ombi-app/Ombi/gh-pages/img/android-chrome-512x512.png'; if (email) {
return `https://www.gravatar.com/avatar/${this.emailHash}?d=${fallback}`; const md5 = new Md5();
const emailHash = md5.appendStr(email).end();
this.userProfileImageUrl = `https://www.gravatar.com/avatar/${emailHash}?d=404`;;
}
else{
this.userProfileImageUrl = this.getFallbackProfileImageUrl();
}
}
public onProfileImageError(): void {
const fallbackLogo = this.getFallbackProfileImageUrl();
if (this.userProfileImageUrl === fallbackLogo) return;
this.userProfileImageUrl = fallbackLogo;
}
private getFallbackProfileImageUrl() {
return this.applicationLogo
? this.applicationLogo
: "https://raw.githubusercontent.com/Ombi-app/Ombi/gh-pages/img/android-chrome-512x512.png";
} }
public openMobileApp(event: any) { public openMobileApp(event: any) {
@ -148,6 +167,5 @@ export class MyNavComponent implements OnInit {
const url = `ombi://${this.applicationUrl}|${this.accessToken}`; const url = `ombi://${this.applicationUrl}|${this.accessToken}`;
window.location.assign(url); window.location.assign(url);
} }
} }

@ -1,8 +1,8 @@
<div class="small-middle-container" *ngIf="username"> <div class="small-middle-container" *ngIf="username">
<div class="d-flex"> <div class="d-flex">
<img class="profile-img" [src]="getProfileImage()"> <img class="profile-img" [src]="userProfileImageUrl" (error)="onProfileImageError()" >
<h2 id="usernameTitle">{{username}} <h2 id="usernameTitle">{{username}}
<small id="emailTitle" *ngIf="user.emailAddress">({{user.emailAddress}})</small> <small id="emailTitle" *ngIf="user?.emailAddress">({{user.emailAddress}})</small>
</h2> </h2>
</div> </div>
@ -15,7 +15,7 @@
User Type: User Type:
</div> </div>
<div class="col-7 col-sm-9 col-md-10"> <div class="col-7 col-sm-9 col-md-10">
{{UserType[user.userType]}} {{UserType[user?.userType]}}
</div> </div>
</div> </div>
@ -75,7 +75,7 @@
</div> </div>
</mat-tab> </mat-tab>
<mat-tab *ngIf="user.userType === UserType.LocalUser" label="Security"> <mat-tab *ngIf="user?.userType === UserType.LocalUser" label="Security">
<div class="tab-content"> <div class="tab-content">
<h2>Change Details</h2> <h2>Change Details</h2>
<form novalidate [formGroup]="passwordForm" (ngSubmit)="updatePassword()"> <form novalidate [formGroup]="passwordForm" (ngSubmit)="updatePassword()">

@ -15,6 +15,7 @@ import { APP_BASE_HREF } from "@angular/common";
export class UserPreferenceComponent implements OnInit { export class UserPreferenceComponent implements OnInit {
public username: string; public username: string;
public userProfileImageUrl: string;
public selectedLang: string; public selectedLang: string;
public availableLanguages = AvailableLanguages; public availableLanguages = AvailableLanguages;
public qrCode: string; public qrCode: string;
@ -61,6 +62,7 @@ export class UserPreferenceComponent implements OnInit {
this.user = await this.identityService.getUser().toPromise(); this.user = await this.identityService.getUser().toPromise();
this.selectedCountry = this.user.streamingCountry; this.selectedCountry = this.user.streamingCountry;
this.setProfileImageUrl(this.user);
this.identityService.getSupportedStreamingCountries().subscribe(x => this.countries = x); this.identityService.getSupportedStreamingCountries().subscribe(x => this.countries = x);
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x); this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
@ -92,14 +94,27 @@ export class UserPreferenceComponent implements OnInit {
this.identityService.updateStreamingCountry(this.selectedCountry).subscribe(x => this.notification.success(this.translate.instant("UserPreferences.Updated"))); this.identityService.updateStreamingCountry(this.selectedCountry).subscribe(x => this.notification.success(this.translate.instant("UserPreferences.Updated")));
} }
public getProfileImage(): string { private setProfileImageUrl(user: IUser): void {
let emailHash: string|Int32Array; if (user?.emailAddress) {
if (this.user.emailAddress) {
const md5 = new Md5(); const md5 = new Md5();
emailHash = md5.appendStr(this.user.emailAddress).end(); const emailHash = md5.appendStr(this.user.emailAddress).end();
this.userProfileImageUrl = `https://www.gravatar.com/avatar/${emailHash}?d=404`;;
} }
var fallback = this.customizationSettings.logo ? this.customizationSettings.logo : 'https://raw.githubusercontent.com/Ombi-app/Ombi/gh-pages/img/android-chrome-512x512.png'; else{
return `https://www.gravatar.com/avatar/${emailHash}?d=${fallback}`; this.userProfileImageUrl = this.getFallbackProfileImageUrl();
}
}
public onProfileImageError(): void {
const fallbackLogo = this.getFallbackProfileImageUrl();
if (this.userProfileImageUrl === fallbackLogo) return;
this.userProfileImageUrl = fallbackLogo;
}
private getFallbackProfileImageUrl() {
return this.customizationSettings?.logo
? this.customizationSettings.logo
: "https://raw.githubusercontent.com/Ombi-app/Ombi/gh-pages/img/android-chrome-512x512.png";
} }
public updatePassword() { public updatePassword() {

@ -182,7 +182,7 @@
<button type="button" data-test="deletebtn" mat-raised-button color="warn" class="btn btn-danger-outline" (click)="delete()">Delete</button> <button type="button" data-test="deletebtn" mat-raised-button color="warn" class="btn btn-danger-outline" (click)="delete()">Delete</button>
<button type="button" style="float:right;" mat-raised-button color="primary" class="btn btn-info-outline" (click)="resetPassword()" matTooltip="You need your SMTP settings setup">Send <button type="button" style="float:right;" mat-raised-button color="primary" class="btn btn-info-outline" (click)="resetPassword()" matTooltip="You need your SMTP settings setup">Send
Reset Password Link</button> Reset Password Link</button>
<button *ngIf="customization.applicationUrl" type="button" mat-raised-button color="accent" class="btn btn-info-outline" (click)="appLink()" matTooltip="Send this link to the user and they can then open the app and directly login">Copy users App Link</button> <button *ngIf="customization?.applicationUrl" type="button" mat-raised-button color="accent" class="btn btn-info-outline" (click)="appLink()" matTooltip="Send this link to the user and they can then open the app and directly login">Copy users App Link</button>
</div> </div>

Loading…
Cancel
Save