mirror of
https://github.com/bitwarden/browser
synced 2026-01-11 21:13:34 +00:00
* 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
108 lines
3.6 KiB
TypeScript
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();
|
|
}
|
|
}
|