diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index e88960e070..a7c285e1d0 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -8,6 +8,7 @@ import { NgModule } from '@angular/core';
import { ServicesModule } from './services/services.module';
import { AppComponent } from './app.component';
+import { IconComponent } from './vault/icon.component';
import { LoginComponent } from './accounts/login.component';
import { VaultComponent } from './vault/vault.component';
@@ -20,6 +21,7 @@ import { VaultComponent } from './vault/vault.component';
],
declarations: [
AppComponent,
+ IconComponent,
LoginComponent,
VaultComponent,
],
diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts
index f5f78a68aa..49d473b26e 100644
--- a/src/app/services/services.module.ts
+++ b/src/app/services/services.module.ts
@@ -97,6 +97,7 @@ environmentService.setUrlsFromStorage().then(() => {
{ provide: CipherServiceAbstraction, useValue: cipherService },
{ provide: FolderServiceAbstraction, useValue: folderService },
{ provide: CollectionServiceAbstraction, useValue: collectionService },
+ { provide: EnvironmentServiceAbstraction, useValue: environmentService },
],
})
export class ServicesModule {
diff --git a/src/app/vault/icon.component.html b/src/app/vault/icon.component.html
new file mode 100644
index 0000000000..6a18b04293
--- /dev/null
+++ b/src/app/vault/icon.component.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/app/vault/icon.component.ts b/src/app/vault/icon.component.ts
new file mode 100644
index 0000000000..1a57b1f621
--- /dev/null
+++ b/src/app/vault/icon.component.ts
@@ -0,0 +1,88 @@
+import * as template from './icon.component.html';
+
+import {
+ Component,
+ Input,
+ OnChanges,
+} from '@angular/core';
+
+import { CipherType } from 'jslib/enums/cipherType';
+
+import { EnvironmentService } from 'jslib/abstractions/environment.service';
+
+@Component({
+ selector: 'app-vault-icon',
+ template: template,
+})
+export class IconComponent implements OnChanges {
+ @Input() cipher: any;
+ icon: string;
+ image: string;
+ fallbackImage: string;
+ imageEnabled: boolean;
+
+ private iconsUrl: string;
+
+ constructor(private environmentService: EnvironmentService) {
+ this.imageEnabled = true; // TODO
+
+ this.iconsUrl = environmentService.iconsUrl;
+ if (!this.iconsUrl) {
+ if (environmentService.baseUrl) {
+ this.iconsUrl = environmentService.baseUrl + '/icons';
+ } else {
+ this.iconsUrl = 'https://icons.bitwarden.com';
+ }
+ }
+ }
+
+ ngOnChanges() {
+ switch (this.cipher.type) {
+ case CipherType.Login:
+ this.icon = 'fa-globe';
+ this.setLoginIcon();
+ break;
+ case CipherType.SecureNote:
+ this.icon = 'fa-sticky-note-o';
+ break;
+ case CipherType.Card:
+ this.icon = 'fa-credit-card';
+ break;
+ case CipherType.Identity:
+ this.icon = 'fa-id-card-o';
+ break;
+ default:
+ break;
+ }
+ }
+
+ private setLoginIcon() {
+ if (this.cipher.login.uri) {
+ let hostnameUri = this.cipher.login.uri;
+ let isWebsite = false;
+
+ if (hostnameUri.indexOf('androidapp://') === 0) {
+ this.icon = 'fa-android';
+ this.image = null;
+ } else if (hostnameUri.indexOf('iosapp://') === 0) {
+ this.icon = 'fa-apple';
+ this.image = null;
+ } else if (this.imageEnabled && hostnameUri.indexOf('://') === -1 && hostnameUri.indexOf('.') > -1) {
+ hostnameUri = 'http://' + hostnameUri;
+ isWebsite = true;
+ } else if (this.imageEnabled) {
+ isWebsite = hostnameUri.indexOf('http') === 0 && hostnameUri.indexOf('.') > -1;
+ }
+
+ if (this.imageEnabled && isWebsite) {
+ try {
+ const url = new URL(hostnameUri);
+ this.image = this.iconsUrl + '/' + url.hostname + '/icon.png';
+ this.fallbackImage = '../images/fa-globe.png'; // TODO?
+ } catch (e) { }
+ }
+ } else {
+ this.image = null;
+ }
+ }
+}
diff --git a/src/app/vault/vault.component.html b/src/app/vault/vault.component.html
index 116cfe9e83..ee646e6aba 100644
--- a/src/app/vault/vault.component.html
+++ b/src/app/vault/vault.component.html
@@ -53,6 +53,7 @@