1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-11 21:13:34 +00:00
Files
browser/apps/web/src/app/settings/appearance.component.ts
Maciej Zieniuk 021d3e53aa [PM-26056] Consolidated session timeout component (#16988)
* consolidated session timeout settings component

* rename preferences to appearance

* race condition bug on computed signal

* outdated header for browser

* unnecessary padding

* remove required on action, fix build

* rename localization key

* missing user id

* required

* cleanup task

* eslint fix signals rollback

* takeUntilDestroyed, null checks

* move browser specific logic outside shared component

* explicit input type

* input name

* takeUntilDestroyed, no toast

* unit tests

* cleanup

* cleanup, correct link to deprecation jira

* tech debt todo with jira

* missing web localization key when policy is on

* relative import

* extracting timeout options to component service

* duplicate localization key

* fix failing test

* subsequent timeout action selecting opening without dialog on first dialog cancellation

* default locale can be null

* unit tests failing

* rename, simplifications

* one if else feature flag

* timeout input component rendering before async pipe completion
2025-11-11 08:15:36 -06:00

108 lines
3.6 KiB
TypeScript

import { ChangeDetectionStrategy, Component, DestroyRef, OnInit } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { FormBuilder } from "@angular/forms";
import { filter, firstValueFrom, switchMap } from "rxjs";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
import { PermitCipherDetailsPopoverComponent } from "@bitwarden/vault";
import { HeaderModule } from "../layouts/header/header.module";
import { SharedModule } from "../shared";
type LocaleOption = {
name: string;
value: string | null;
};
type ThemeOption = {
name: string;
value: Theme;
};
@Component({
selector: "app-appearance",
templateUrl: "appearance.component.html",
imports: [SharedModule, HeaderModule, PermitCipherDetailsPopoverComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppearanceComponent implements OnInit {
localeOptions: LocaleOption[];
themeOptions: ThemeOption[];
form = this.formBuilder.group({
enableFavicons: true,
theme: [ThemeTypes.Light as Theme],
locale: [null as string | null],
});
constructor(
private formBuilder: FormBuilder,
private i18nService: I18nService,
private themeStateService: ThemeStateService,
private domainSettingsService: DomainSettingsService,
private destroyRef: DestroyRef,
) {
const localeOptions: LocaleOption[] = [];
i18nService.supportedTranslationLocales.forEach((locale) => {
let name = locale;
if (i18nService.localeNames.has(locale)) {
name += " - " + i18nService.localeNames.get(locale);
}
localeOptions.push({ name: name, value: locale });
});
localeOptions.sort(Utils.getSortFunction(i18nService, "name"));
localeOptions.splice(0, 0, { name: i18nService.t("default"), value: null });
this.localeOptions = localeOptions;
this.themeOptions = [
{ name: i18nService.t("themeLight"), value: ThemeTypes.Light },
{ name: i18nService.t("themeDark"), value: ThemeTypes.Dark },
{ name: i18nService.t("themeSystem"), value: ThemeTypes.System },
];
}
async ngOnInit() {
this.form.setValue(
{
enableFavicons: await firstValueFrom(this.domainSettingsService.showFavicons$),
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
locale: (await firstValueFrom(this.i18nService.userSetLocale$)) ?? null,
},
{ emitEvent: false },
);
this.form.controls.enableFavicons.valueChanges
.pipe(
filter((enableFavicons) => enableFavicons != null),
switchMap(async (enableFavicons) => {
await this.domainSettingsService.setShowFavicons(enableFavicons);
}),
takeUntilDestroyed(this.destroyRef),
)
.subscribe();
this.form.controls.theme.valueChanges
.pipe(
filter((theme) => theme != null),
switchMap(async (theme) => {
await this.themeStateService.setSelectedTheme(theme);
}),
takeUntilDestroyed(this.destroyRef),
)
.subscribe();
this.form.controls.locale.valueChanges
.pipe(
switchMap(async (locale) => {
await this.i18nService.setLocale(locale);
window.location.reload();
}),
takeUntilDestroyed(this.destroyRef),
)
.subscribe();
}
}