mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-24 12:06:15 +01:00
[PM-1400] Update IconComponent to use OnPush ChangeDetection (#5181)
* Add disableFavicon$ to stateService * Change IconComponent's ChangeDetectionStrategy and use disableFavicon$ observable * Only get first result from disableFavicon observable * Move disabledFavicon$ to SettingsService * Update usage of disableFavicon to use SettingsService * Remove getting and setting of disabledFavicon on login * Settings service observable adjustments * Fix for popup initially having a null value for the disableFavicon setting in settingsService * Move disabledFavicon$ subscription to ngOnInit * feat: experiment with observables * Remove SettingsService from browser app component * Fix storybook changes * Update apps/web/src/app/vault/components/vault-items/vault-items.stories.ts Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com> * Fix mock function signature --------- Co-authored-by: Andreas Coroiu <andreas.coroiu@gmail.com> Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>
This commit is contained in:
parent
a899ea370e
commit
671a9115bb
@ -3,6 +3,7 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
|
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
|
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||||
import { ThemeType, UriMatchType } from "@bitwarden/common/enums";
|
import { ThemeType, UriMatchType } from "@bitwarden/common/enums";
|
||||||
@ -39,7 +40,8 @@ export class OptionsComponent implements OnInit {
|
|||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private totpService: TotpService,
|
private totpService: TotpService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
private themingService: AbstractThemingService
|
private themingService: AbstractThemingService,
|
||||||
|
private settingsService: SettingsService
|
||||||
) {
|
) {
|
||||||
this.themeOptions = [
|
this.themeOptions = [
|
||||||
{ name: i18nService.t("default"), value: ThemeType.System },
|
{ name: i18nService.t("default"), value: ThemeType.System },
|
||||||
@ -89,7 +91,7 @@ export class OptionsComponent implements OnInit {
|
|||||||
|
|
||||||
this.enableAutoTotpCopy = !(await this.stateService.getDisableAutoTotpCopy());
|
this.enableAutoTotpCopy = !(await this.stateService.getDisableAutoTotpCopy());
|
||||||
|
|
||||||
this.enableFavicon = !(await this.stateService.getDisableFavicon());
|
this.enableFavicon = !this.settingsService.getDisableFavicon();
|
||||||
|
|
||||||
this.enableBadgeCounter = !(await this.stateService.getDisableBadgeCounter());
|
this.enableBadgeCounter = !(await this.stateService.getDisableBadgeCounter());
|
||||||
|
|
||||||
@ -129,7 +131,7 @@ export class OptionsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateFavicon() {
|
async updateFavicon() {
|
||||||
await this.stateService.setDisableFavicon(!this.enableFavicon);
|
await this.settingsService.setDisableFavicon(!this.enableFavicon);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateBadgeCounter() {
|
async updateBadgeCounter() {
|
||||||
|
@ -3,9 +3,13 @@ import { BehaviorSubject } from "rxjs";
|
|||||||
import { AccountSettingsSettings } from "@bitwarden/common/models/domain/account";
|
import { AccountSettingsSettings } from "@bitwarden/common/models/domain/account";
|
||||||
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
||||||
|
|
||||||
import { sessionSync } from "../decorators/session-sync-observable";
|
import { browserSession, sessionSync } from "../decorators/session-sync-observable";
|
||||||
|
|
||||||
|
@browserSession
|
||||||
export class BrowserSettingsService extends SettingsService {
|
export class BrowserSettingsService extends SettingsService {
|
||||||
@sessionSync({ initializer: (obj: string[][]) => obj })
|
@sessionSync({ initializer: (obj: string[][]) => obj })
|
||||||
protected _settings: BehaviorSubject<AccountSettingsSettings>;
|
protected _settings: BehaviorSubject<AccountSettingsSettings>;
|
||||||
|
|
||||||
|
@sessionSync({ initializer: (b: boolean) => b })
|
||||||
|
protected _disableFavicon: BehaviorSubject<boolean>;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { DeviceType, ThemeType, StorageLocation, KeySuffixOptions } from "@bitwarden/common/enums";
|
import { DeviceType, ThemeType, KeySuffixOptions } from "@bitwarden/common/enums";
|
||||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||||
import { Utils } from "@bitwarden/common/misc/utils";
|
import { Utils } from "@bitwarden/common/misc/utils";
|
||||||
|
|
||||||
@ -107,7 +108,8 @@ export class SettingsComponent implements OnInit {
|
|||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
private modalService: ModalService,
|
private modalService: ModalService,
|
||||||
private themingService: AbstractThemingService
|
private themingService: AbstractThemingService,
|
||||||
|
private settingsService: SettingsService
|
||||||
) {
|
) {
|
||||||
const isMac = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop;
|
const isMac = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop;
|
||||||
|
|
||||||
@ -437,10 +439,7 @@ export class SettingsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async saveFavicons() {
|
async saveFavicons() {
|
||||||
await this.stateService.setDisableFavicon(!this.form.value.enableFavicons);
|
await this.settingsService.setDisableFavicon(!this.form.value.enableFavicons);
|
||||||
await this.stateService.setDisableFavicon(!this.form.value.enableFavicons, {
|
|
||||||
storageLocation: StorageLocation.Disk,
|
|
||||||
});
|
|
||||||
this.messagingService.send("refreshCiphers");
|
this.messagingService.send("refreshCiphers");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import { AbstractThemingService } from "@bitwarden/angular/services/theming/them
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
|
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
@ -51,7 +52,8 @@ export class PreferencesComponent implements OnInit {
|
|||||||
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private themingService: AbstractThemingService
|
private themingService: AbstractThemingService,
|
||||||
|
private settingsService: SettingsService
|
||||||
) {
|
) {
|
||||||
this.vaultTimeoutOptions = [
|
this.vaultTimeoutOptions = [
|
||||||
{ name: i18nService.t("oneMinute"), value: 1 },
|
{ name: i18nService.t("oneMinute"), value: 1 },
|
||||||
@ -128,11 +130,10 @@ export class PreferencesComponent implements OnInit {
|
|||||||
takeUntil(this.destroy$)
|
takeUntil(this.destroy$)
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
const initialFormValues = {
|
const initialFormValues = {
|
||||||
vaultTimeout: await this.vaultTimeoutSettingsService.getVaultTimeout(),
|
vaultTimeout: await this.vaultTimeoutSettingsService.getVaultTimeout(),
|
||||||
vaultTimeoutAction: await this.vaultTimeoutSettingsService.getVaultTimeoutAction(),
|
vaultTimeoutAction: await this.vaultTimeoutSettingsService.getVaultTimeoutAction(),
|
||||||
enableFavicons: !(await this.stateService.getDisableFavicon()),
|
enableFavicons: !(await this.settingsService.getDisableFavicon()),
|
||||||
enableFullWidth: await this.stateService.getEnableFullWidth(),
|
enableFullWidth: await this.stateService.getEnableFullWidth(),
|
||||||
theme: await this.stateService.getTheme(),
|
theme: await this.stateService.getTheme(),
|
||||||
locale: (await this.stateService.getLocale()) ?? null,
|
locale: (await this.stateService.getLocale()) ?? null,
|
||||||
@ -157,7 +158,7 @@ export class PreferencesComponent implements OnInit {
|
|||||||
values.vaultTimeout,
|
values.vaultTimeout,
|
||||||
values.vaultTimeoutAction
|
values.vaultTimeoutAction
|
||||||
);
|
);
|
||||||
await this.stateService.setDisableFavicon(!values.enableFavicons);
|
await this.settingsService.setDisableFavicon(!values.enableFavicons);
|
||||||
await this.stateService.setEnableFullWidth(values.enableFullWidth);
|
await this.stateService.setEnableFullWidth(values.enableFullWidth);
|
||||||
this.messagingService.send("setFullWidth");
|
this.messagingService.send("setFullWidth");
|
||||||
if (values.theme !== this.startingTheme) {
|
if (values.theme !== this.startingTheme) {
|
||||||
|
@ -5,6 +5,7 @@ import { BehaviorSubject } from "rxjs";
|
|||||||
|
|
||||||
import { AvatarUpdateService } from "@bitwarden/common/abstractions/account/avatar-update.service";
|
import { AvatarUpdateService } from "@bitwarden/common/abstractions/account/avatar-update.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
||||||
|
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||||
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
@ -69,6 +70,15 @@ export default {
|
|||||||
},
|
},
|
||||||
} as Partial<StateService>,
|
} as Partial<StateService>,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: SettingsService,
|
||||||
|
useValue: {
|
||||||
|
disableFavicon$: new BehaviorSubject(false).asObservable(),
|
||||||
|
getDisableFavicon() {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
} as Partial<SettingsService>,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: AvatarUpdateService,
|
provide: AvatarUpdateService,
|
||||||
useValue: {
|
useValue: {
|
||||||
|
@ -260,8 +260,6 @@ export class LockComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private async doContinue(evaluatePasswordAfterUnlock: boolean) {
|
private async doContinue(evaluatePasswordAfterUnlock: boolean) {
|
||||||
await this.stateService.setEverBeenUnlocked(true);
|
await this.stateService.setEverBeenUnlocked(true);
|
||||||
const disableFavicon = await this.stateService.getDisableFavicon();
|
|
||||||
await this.stateService.setDisableFavicon(!!disableFavicon);
|
|
||||||
this.messagingService.send("unlocked");
|
this.messagingService.send("unlocked");
|
||||||
|
|
||||||
if (evaluatePasswordAfterUnlock) {
|
if (evaluatePasswordAfterUnlock) {
|
||||||
|
@ -152,8 +152,6 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit
|
|||||||
this.router.navigate([this.forcePasswordResetRoute]);
|
this.router.navigate([this.forcePasswordResetRoute]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const disableFavicon = await this.stateService.getDisableFavicon();
|
|
||||||
await this.stateService.setDisableFavicon(!!disableFavicon);
|
|
||||||
if (this.onSuccessfulLogin != null) {
|
if (this.onSuccessfulLogin != null) {
|
||||||
this.onSuccessfulLogin();
|
this.onSuccessfulLogin();
|
||||||
}
|
}
|
||||||
|
@ -212,8 +212,6 @@ export class SsoComponent {
|
|||||||
this.router.navigate([this.forcePasswordResetRoute]);
|
this.router.navigate([this.forcePasswordResetRoute]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const disableFavicon = await this.stateService.getDisableFavicon();
|
|
||||||
await this.stateService.setDisableFavicon(!!disableFavicon);
|
|
||||||
if (this.onSuccessfulLogin != null) {
|
if (this.onSuccessfulLogin != null) {
|
||||||
await this.onSuccessfulLogin();
|
await this.onSuccessfulLogin();
|
||||||
}
|
}
|
||||||
|
@ -197,8 +197,6 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
|||||||
this.captchaToken
|
this.captchaToken
|
||||||
);
|
);
|
||||||
const response: AuthResult = await this.formPromise;
|
const response: AuthResult = await this.formPromise;
|
||||||
const disableFavicon = await this.stateService.getDisableFavicon();
|
|
||||||
await this.stateService.setDisableFavicon(!!disableFavicon);
|
|
||||||
if (this.handleCaptchaRequired(response)) {
|
if (this.handleCaptchaRequired(response)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
<div class="icon" aria-hidden="true">
|
<div class="icon" aria-hidden="true">
|
||||||
<img
|
<ng-container *ngIf="data$ | async as data">
|
||||||
[src]="image"
|
<img
|
||||||
appFallbackSrc="{{ fallbackImage }}"
|
[src]="data.image"
|
||||||
*ngIf="imageEnabled && image"
|
[appFallbackSrc]="data.fallbackImage"
|
||||||
alt=""
|
*ngIf="data.imageEnabled && data.image"
|
||||||
decoding="async"
|
alt=""
|
||||||
loading="lazy"
|
decoding="async"
|
||||||
/>
|
loading="lazy"
|
||||||
<i class="tw-text-muted bwi bwi-lg {{ icon }}" *ngIf="!imageEnabled || !image"></i>
|
/>
|
||||||
|
<i
|
||||||
|
class="tw-text-muted bwi bwi-lg {{ data.icon }}"
|
||||||
|
*ngIf="!data.imageEnabled || !data.image"
|
||||||
|
></i>
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
import { Component, Input, OnChanges } from "@angular/core";
|
import { ChangeDetectionStrategy, Component, Input, OnInit } from "@angular/core";
|
||||||
|
import {
|
||||||
|
BehaviorSubject,
|
||||||
|
combineLatest,
|
||||||
|
distinctUntilChanged,
|
||||||
|
filter,
|
||||||
|
map,
|
||||||
|
Observable,
|
||||||
|
} from "rxjs";
|
||||||
|
|
||||||
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
||||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { Utils } from "@bitwarden/common/misc/utils";
|
import { Utils } from "@bitwarden/common/misc/utils";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
@ -25,89 +33,101 @@ const cardIcons: Record<string, string> = {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: "app-vault-icon",
|
selector: "app-vault-icon",
|
||||||
templateUrl: "icon.component.html",
|
templateUrl: "icon.component.html",
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class IconComponent implements OnChanges {
|
export class IconComponent implements OnInit {
|
||||||
@Input() cipher: CipherView;
|
@Input()
|
||||||
icon: string;
|
set cipher(value: CipherView) {
|
||||||
image: string;
|
this.cipher$.next(value);
|
||||||
fallbackImage: string;
|
|
||||||
imageEnabled: boolean;
|
|
||||||
|
|
||||||
private iconsUrl: string;
|
|
||||||
|
|
||||||
constructor(environmentService: EnvironmentService, private stateService: StateService) {
|
|
||||||
this.iconsUrl = environmentService.getIconsUrl();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnChanges() {
|
protected data$: Observable<{
|
||||||
// Components may be re-used when using cdk-virtual-scroll. Which puts the component in a weird state,
|
imageEnabled: boolean;
|
||||||
// to avoid this we reset all state variables.
|
image?: string;
|
||||||
this.image = null;
|
fallbackImage: string;
|
||||||
this.fallbackImage = null;
|
icon?: string;
|
||||||
this.imageEnabled = !(await this.stateService.getDisableFavicon());
|
}>;
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected load() {
|
private cipher$ = new BehaviorSubject<CipherView>(undefined);
|
||||||
switch (this.cipher.type) {
|
|
||||||
case CipherType.Login:
|
|
||||||
this.icon = "bwi-globe";
|
|
||||||
this.setLoginIcon();
|
|
||||||
break;
|
|
||||||
case CipherType.SecureNote:
|
|
||||||
this.icon = "bwi-sticky-note";
|
|
||||||
break;
|
|
||||||
case CipherType.Card:
|
|
||||||
this.icon = "bwi-credit-card";
|
|
||||||
this.setCardIcon();
|
|
||||||
break;
|
|
||||||
case CipherType.Identity:
|
|
||||||
this.icon = "bwi-id-card";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private setLoginIcon() {
|
constructor(
|
||||||
if (this.cipher.login.uri) {
|
private environmentService: EnvironmentService,
|
||||||
let hostnameUri = this.cipher.login.uri;
|
private settingsService: SettingsService
|
||||||
let isWebsite = false;
|
) {}
|
||||||
|
|
||||||
if (hostnameUri.indexOf("androidapp://") === 0) {
|
async ngOnInit() {
|
||||||
this.icon = "bwi-android";
|
const iconsUrl = this.environmentService.getIconsUrl();
|
||||||
this.image = null;
|
|
||||||
} else if (hostnameUri.indexOf("iosapp://") === 0) {
|
|
||||||
this.icon = "bwi-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) {
|
this.data$ = combineLatest([
|
||||||
try {
|
this.settingsService.disableFavicon$.pipe(distinctUntilChanged()),
|
||||||
this.image = this.iconsUrl + "/" + Utils.getHostname(hostnameUri) + "/icon.png";
|
this.cipher$.pipe(filter((c) => c !== undefined)),
|
||||||
this.fallbackImage = "images/bwi-globe.png";
|
]).pipe(
|
||||||
} catch (e) {
|
map(([disableFavicon, cipher]) => {
|
||||||
// Ignore error since the fallback icon will be shown if image is null.
|
const imageEnabled = !disableFavicon;
|
||||||
|
let image = undefined;
|
||||||
|
let fallbackImage = "";
|
||||||
|
let icon = undefined;
|
||||||
|
|
||||||
|
switch (cipher.type) {
|
||||||
|
case CipherType.Login:
|
||||||
|
icon = "bwi-globe";
|
||||||
|
|
||||||
|
if (cipher.login.uri) {
|
||||||
|
let hostnameUri = cipher.login.uri;
|
||||||
|
let isWebsite = false;
|
||||||
|
|
||||||
|
if (hostnameUri.indexOf("androidapp://") === 0) {
|
||||||
|
icon = "bwi-android";
|
||||||
|
image = null;
|
||||||
|
} else if (hostnameUri.indexOf("iosapp://") === 0) {
|
||||||
|
icon = "bwi-apple";
|
||||||
|
image = null;
|
||||||
|
} else if (
|
||||||
|
imageEnabled &&
|
||||||
|
hostnameUri.indexOf("://") === -1 &&
|
||||||
|
hostnameUri.indexOf(".") > -1
|
||||||
|
) {
|
||||||
|
hostnameUri = "http://" + hostnameUri;
|
||||||
|
isWebsite = true;
|
||||||
|
} else if (imageEnabled) {
|
||||||
|
isWebsite = hostnameUri.indexOf("http") === 0 && hostnameUri.indexOf(".") > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageEnabled && isWebsite) {
|
||||||
|
try {
|
||||||
|
image = iconsUrl + "/" + Utils.getHostname(hostnameUri) + "/icon.png";
|
||||||
|
fallbackImage = "images/bwi-globe.png";
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore error since the fallback icon will be shown if image is null.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
image = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CipherType.SecureNote:
|
||||||
|
icon = "bwi-sticky-note";
|
||||||
|
break;
|
||||||
|
case CipherType.Card:
|
||||||
|
icon = "bwi-credit-card";
|
||||||
|
if (imageEnabled && cipher.card.brand in cardIcons) {
|
||||||
|
icon = "credit-card-icon " + cardIcons[cipher.card.brand];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CipherType.Identity:
|
||||||
|
icon = "bwi-id-card";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.image = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private setCardIcon() {
|
return {
|
||||||
const brand = this.cipher.card.brand;
|
imageEnabled,
|
||||||
if (this.imageEnabled && brand in cardIcons) {
|
image,
|
||||||
this.icon = "credit-card-icon " + cardIcons[brand];
|
fallbackImage,
|
||||||
}
|
icon,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,11 @@ import { AccountSettingsSettings } from "../models/domain/account";
|
|||||||
|
|
||||||
export abstract class SettingsService {
|
export abstract class SettingsService {
|
||||||
settings$: Observable<AccountSettingsSettings>;
|
settings$: Observable<AccountSettingsSettings>;
|
||||||
|
disableFavicon$: Observable<boolean>;
|
||||||
|
|
||||||
setEquivalentDomains: (equivalentDomains: string[][]) => Promise<any>;
|
setEquivalentDomains: (equivalentDomains: string[][]) => Promise<any>;
|
||||||
getEquivalentDomains: (url: string) => Set<string>;
|
getEquivalentDomains: (url: string) => Set<string>;
|
||||||
|
setDisableFavicon: (value: boolean) => Promise<any>;
|
||||||
|
getDisableFavicon: () => boolean;
|
||||||
clear: (userId?: string) => Promise<void>;
|
clear: (userId?: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,13 @@ export abstract class StateService<T extends Account = Account> {
|
|||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
getDisableContextMenuItem: (options?: StorageOptions) => Promise<boolean>;
|
getDisableContextMenuItem: (options?: StorageOptions) => Promise<boolean>;
|
||||||
setDisableContextMenuItem: (value: boolean, options?: StorageOptions) => Promise<void>;
|
setDisableContextMenuItem: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||||
|
/**
|
||||||
|
* @deprecated Do not call this, use SettingsService
|
||||||
|
*/
|
||||||
getDisableFavicon: (options?: StorageOptions) => Promise<boolean>;
|
getDisableFavicon: (options?: StorageOptions) => Promise<boolean>;
|
||||||
|
/**
|
||||||
|
* @deprecated Do not call this, use SettingsService
|
||||||
|
*/
|
||||||
setDisableFavicon: (value: boolean, options?: StorageOptions) => Promise<void>;
|
setDisableFavicon: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||||
getDisableGa: (options?: StorageOptions) => Promise<boolean>;
|
getDisableGa: (options?: StorageOptions) => Promise<boolean>;
|
||||||
setDisableGa: (value: boolean, options?: StorageOptions) => Promise<void>;
|
setDisableGa: (value: boolean, options?: StorageOptions) => Promise<void>;
|
||||||
|
@ -7,8 +7,10 @@ import { AccountSettingsSettings } from "../models/domain/account";
|
|||||||
|
|
||||||
export class SettingsService implements SettingsServiceAbstraction {
|
export class SettingsService implements SettingsServiceAbstraction {
|
||||||
protected _settings: BehaviorSubject<AccountSettingsSettings> = new BehaviorSubject({});
|
protected _settings: BehaviorSubject<AccountSettingsSettings> = new BehaviorSubject({});
|
||||||
|
protected _disableFavicon = new BehaviorSubject<boolean>(null);
|
||||||
|
|
||||||
settings$ = this._settings.asObservable();
|
settings$ = this._settings.asObservable();
|
||||||
|
disableFavicon$ = this._disableFavicon.asObservable();
|
||||||
|
|
||||||
constructor(private stateService: StateService) {
|
constructor(private stateService: StateService) {
|
||||||
this.stateService.activeAccountUnlocked$
|
this.stateService.activeAccountUnlocked$
|
||||||
@ -24,8 +26,10 @@ export class SettingsService implements SettingsServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await this.stateService.getSettings();
|
const data = await this.stateService.getSettings();
|
||||||
|
const disableFavicon = await this.stateService.getDisableFavicon();
|
||||||
|
|
||||||
this._settings.next(data);
|
this._settings.next(data);
|
||||||
|
this._disableFavicon.next(disableFavicon);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
@ -61,6 +65,15 @@ export class SettingsService implements SettingsServiceAbstraction {
|
|||||||
return new Set(result);
|
return new Set(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setDisableFavicon(value: boolean) {
|
||||||
|
this._disableFavicon.next(value);
|
||||||
|
await this.stateService.setDisableFavicon(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisableFavicon(): boolean {
|
||||||
|
return this._disableFavicon.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
async clear(userId?: string): Promise<void> {
|
async clear(userId?: string): Promise<void> {
|
||||||
if (userId == null || userId == (await this.stateService.getUserId())) {
|
if (userId == null || userId == (await this.stateService.getUserId())) {
|
||||||
this._settings.next({});
|
this._settings.next({});
|
||||||
|
@ -103,7 +103,6 @@ export class StateService<
|
|||||||
} else if (userId == null) {
|
} else if (userId == null) {
|
||||||
this.activeAccountUnlockedSubject.next(false);
|
this.activeAccountUnlockedSubject.next(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This should be refactored into AuthService or a similar service,
|
// FIXME: This should be refactored into AuthService or a similar service,
|
||||||
// as checking for the existence of the crypto key is a low level
|
// as checking for the existence of the crypto key is a low level
|
||||||
// implementation detail.
|
// implementation detail.
|
||||||
@ -130,6 +129,7 @@ export class StateService<
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
await this.initAccountState();
|
await this.initAccountState();
|
||||||
|
|
||||||
this.hasBeenInited = true;
|
this.hasBeenInited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user