1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-07 04:03:29 +00:00
Files
browser/libs/angular/src/vault/components/icon.component.ts
Jason Ng 2ef8b1a6bf [PM-18066] new item details view (#15311)
* update item details v2 in libs for new view design. targets web, browser, and desktop
2025-08-07 13:21:24 -04:00

66 lines
2.2 KiB
TypeScript

import { ChangeDetectionStrategy, Component, input, signal } from "@angular/core";
import { toObservable } from "@angular/core/rxjs-interop";
import {
combineLatest,
distinctUntilChanged,
map,
tap,
Observable,
startWith,
pairwise,
} from "rxjs";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { buildCipherIcon, CipherIconDetails } from "@bitwarden/common/vault/icon/build-cipher-icon";
import { CipherViewLike } from "@bitwarden/common/vault/utils/cipher-view-like-utils";
@Component({
selector: "app-vault-icon",
templateUrl: "icon.component.html",
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false,
})
export class IconComponent {
/**
* The cipher to display the icon for.
*/
cipher = input.required<CipherViewLike>();
/**
* coloredIcon will adjust the size of favicons and the colors of the text icon when user is in the item details view.
*/
coloredIcon = input<boolean>(false);
imageLoaded = signal(false);
protected data$: Observable<CipherIconDetails>;
constructor(
private environmentService: EnvironmentService,
private domainSettingsService: DomainSettingsService,
) {
const iconSettings$ = combineLatest([
this.environmentService.environment$.pipe(map((e) => e.getIconsUrl())),
this.domainSettingsService.showFavicons$.pipe(distinctUntilChanged()),
]).pipe(
map(([iconsUrl, showFavicon]) => ({ iconsUrl, showFavicon })),
startWith({ iconsUrl: null, showFavicon: false }), // Start with a safe default to avoid flickering icons
distinctUntilChanged(),
);
this.data$ = combineLatest([iconSettings$, toObservable(this.cipher)]).pipe(
map(([{ iconsUrl, showFavicon }, cipher]) => buildCipherIcon(iconsUrl, cipher, showFavicon)),
startWith(null),
pairwise(),
tap(([prev, next]) => {
if (prev?.image !== next?.image) {
// The image changed, reset the loaded state to not show an empty icon
this.imageLoaded.set(false);
}
}),
map(([_, next]) => next!),
);
}
}