mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 08:13:42 +00:00
Auth/PM-7077 - Browser Extension - UI Refresh - Account Switcher Component (#10268)
* PM-7077 - (1) Convert app-header to standalone (2) Convert account-switcher to standalone (3) Start wiring up extension refresh feature flag and fixing deps. * PM-7077 WIP * PM-7077 - Mostly get account switcher and account component converted to CL components. * PM-7077 - Apply semibold classes to section headers to match storybook * PM-7077 - AccountSwitcher - (1) Fix margin per design call (2) Add missing lockAll call * PM-7077 - Remove test code.
This commit is contained in:
@@ -1,3 +1,95 @@
|
|||||||
|
<ng-container *ngIf="extensionRefreshFlag">
|
||||||
|
<popup-page [loading]="loading">
|
||||||
|
<popup-header slot="header" pageTitle="{{ 'switchAccounts' | i18n }}" showBackButton>
|
||||||
|
<ng-container slot="end">
|
||||||
|
<app-pop-out></app-pop-out>
|
||||||
|
<app-current-account></app-current-account>
|
||||||
|
</ng-container>
|
||||||
|
</popup-header>
|
||||||
|
|
||||||
|
<ng-container *ngIf="availableAccounts$ | async as availableAccounts">
|
||||||
|
<bit-section>
|
||||||
|
<ng-container *ngFor="let availableAccount of availableAccounts; first as isFirst">
|
||||||
|
<div *ngIf="availableAccount.isActive" class="tw-mb-6">
|
||||||
|
<auth-account
|
||||||
|
[account]="availableAccount"
|
||||||
|
[extensionRefreshFlag]="extensionRefreshFlag"
|
||||||
|
(loading)="loading = $event"
|
||||||
|
></auth-account>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<bit-section-header *ngIf="isFirst">
|
||||||
|
<h2 bitTypography="h6" class="tw-font-semibold">{{ "availableAccounts" | i18n }}</h2>
|
||||||
|
</bit-section-header>
|
||||||
|
|
||||||
|
<div *ngIf="!availableAccount.isActive">
|
||||||
|
<auth-account
|
||||||
|
[account]="availableAccount"
|
||||||
|
[extensionRefreshFlag]="extensionRefreshFlag"
|
||||||
|
(loading)="loading = $event"
|
||||||
|
></auth-account>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If the user has not reached the account limit, the last 'availableAccount' will have an 'id' of
|
||||||
|
'SPECIAL_ADD_ACCOUNT_ID'. Since we don't want to count this as one of the actual accounts,
|
||||||
|
we check to make sure the 'id' of the last 'availableAccount' is not equal to 'SPECIAL_ADD_ACCOUNT_ID'
|
||||||
|
-->
|
||||||
|
<p
|
||||||
|
class="tw-text-sm tw-text-muted"
|
||||||
|
*ngIf="
|
||||||
|
availableAccounts.length >= accountLimit &&
|
||||||
|
availableAccounts[availableAccounts.length - 1].id !== specialAddAccountId
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ "accountLimitReached" | i18n }}
|
||||||
|
</p>
|
||||||
|
</bit-section>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<div class="tw-mt-8" *ngIf="currentAccount$ | async as currentAccount">
|
||||||
|
<bit-section>
|
||||||
|
<bit-section-header>
|
||||||
|
<h2 bitTypography="h6" class="tw-font-semibold">
|
||||||
|
{{ "options" | i18n }}
|
||||||
|
</h2>
|
||||||
|
</bit-section-header>
|
||||||
|
|
||||||
|
<bit-item>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bit-item-content
|
||||||
|
(click)="lock(currentAccount.id)"
|
||||||
|
[disabled]="currentAccount.status === lockedStatus || !activeUserCanLock"
|
||||||
|
[title]="!activeUserCanLock ? ('unlockMethodNeeded' | i18n) : ''"
|
||||||
|
>
|
||||||
|
<i slot="start" class="bwi bwi-lock tw-text-2xl tw-text-main" aria-hidden="true"></i>
|
||||||
|
{{ "lockNow" | i18n }}
|
||||||
|
</button>
|
||||||
|
</bit-item>
|
||||||
|
<bit-item>
|
||||||
|
<button type="button" bit-item-content (click)="logOut(currentAccount.id)">
|
||||||
|
<i
|
||||||
|
slot="start"
|
||||||
|
class="bwi bwi-sign-out tw-text-2xl tw-text-main"
|
||||||
|
aria-hidden="true"
|
||||||
|
></i>
|
||||||
|
{{ "logOut" | i18n }}
|
||||||
|
</button>
|
||||||
|
</bit-item>
|
||||||
|
<bit-item>
|
||||||
|
<button type="button" bit-item-content (click)="lockAll()">
|
||||||
|
<i slot="start" class="bwi bwi-lock tw-text-2xl tw-text-main" aria-hidden="true"></i>
|
||||||
|
{{ "lockAll" | i18n }}
|
||||||
|
</button>
|
||||||
|
</bit-item>
|
||||||
|
</bit-section>
|
||||||
|
</div>
|
||||||
|
</popup-page>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!extensionRefreshFlag">
|
||||||
<app-header>
|
<app-header>
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<button type="button" (click)="back()">{{ "close" | i18n }}</button>
|
<button type="button" (click)="back()">{{ "close" | i18n }}</button>
|
||||||
@@ -17,13 +109,19 @@
|
|||||||
<ul class="tw-grid tw-list-none tw-gap-2" role="listbox">
|
<ul class="tw-grid tw-list-none tw-gap-2" role="listbox">
|
||||||
<ng-container *ngFor="let availableAccount of availableAccounts; first as isFirst">
|
<ng-container *ngFor="let availableAccount of availableAccounts; first as isFirst">
|
||||||
<li *ngIf="availableAccount.isActive" class="tw-mb-4" role="option">
|
<li *ngIf="availableAccount.isActive" class="tw-mb-4" role="option">
|
||||||
<auth-account [account]="availableAccount" (loading)="loading = $event"></auth-account>
|
<auth-account
|
||||||
|
[account]="availableAccount"
|
||||||
|
(loading)="loading = $event"
|
||||||
|
></auth-account>
|
||||||
</li>
|
</li>
|
||||||
<div *ngIf="isFirst" class="tw-uppercase tw-text-muted">
|
<div *ngIf="isFirst" class="tw-uppercase tw-text-muted">
|
||||||
{{ "availableAccounts" | i18n }}
|
{{ "availableAccounts" | i18n }}
|
||||||
</div>
|
</div>
|
||||||
<li *ngIf="!availableAccount.isActive" role="option">
|
<li *ngIf="!availableAccount.isActive" role="option">
|
||||||
<auth-account [account]="availableAccount" (loading)="loading = $event"></auth-account>
|
<auth-account
|
||||||
|
[account]="availableAccount"
|
||||||
|
(loading)="loading = $event"
|
||||||
|
></auth-account>
|
||||||
</li>
|
</li>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -76,3 +174,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
</ng-container>
|
||||||
|
|||||||
@@ -1,22 +1,54 @@
|
|||||||
import { Location } from "@angular/common";
|
import { CommonModule, Location } from "@angular/common";
|
||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { Subject, firstValueFrom, map, of, switchMap, takeUntil } from "rxjs";
|
import { Subject, firstValueFrom, map, of, switchMap, takeUntil } from "rxjs";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import {
|
||||||
|
AvatarModule,
|
||||||
|
ButtonModule,
|
||||||
|
DialogService,
|
||||||
|
ItemModule,
|
||||||
|
SectionComponent,
|
||||||
|
SectionHeaderComponent,
|
||||||
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { PopOutComponent } from "../../../platform/popup/components/pop-out.component";
|
||||||
|
import { HeaderComponent } from "../../../platform/popup/header.component";
|
||||||
|
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
|
||||||
|
import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component";
|
||||||
|
|
||||||
|
import { AccountComponent } from "./account.component";
|
||||||
|
import { CurrentAccountComponent } from "./current-account.component";
|
||||||
import { AccountSwitcherService } from "./services/account-switcher.service";
|
import { AccountSwitcherService } from "./services/account-switcher.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
standalone: true,
|
||||||
templateUrl: "account-switcher.component.html",
|
templateUrl: "account-switcher.component.html",
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
JslibModule,
|
||||||
|
ButtonModule,
|
||||||
|
ItemModule,
|
||||||
|
AvatarModule,
|
||||||
|
PopupPageComponent,
|
||||||
|
PopupHeaderComponent,
|
||||||
|
HeaderComponent,
|
||||||
|
PopOutComponent,
|
||||||
|
CurrentAccountComponent,
|
||||||
|
AccountComponent,
|
||||||
|
SectionComponent,
|
||||||
|
SectionHeaderComponent,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
||||||
readonly lockedStatus = AuthenticationStatus.Locked;
|
readonly lockedStatus = AuthenticationStatus.Locked;
|
||||||
@@ -24,17 +56,18 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
loading = false;
|
loading = false;
|
||||||
activeUserCanLock = false;
|
activeUserCanLock = false;
|
||||||
|
extensionRefreshFlag = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private accountSwitcherService: AccountSwitcherService,
|
private accountSwitcherService: AccountSwitcherService,
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
private vaultTimeoutService: VaultTimeoutService,
|
private vaultTimeoutService: VaultTimeoutService,
|
||||||
private messagingService: MessagingService,
|
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private location: Location,
|
private location: Location,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
private configService: ConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get accountLimit() {
|
get accountLimit() {
|
||||||
@@ -55,6 +88,10 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
this.extensionRefreshFlag = await this.configService.getFeatureFlag(
|
||||||
|
FeatureFlag.ExtensionRefresh,
|
||||||
|
);
|
||||||
|
|
||||||
const availableVaultTimeoutActions = await firstValueFrom(
|
const availableVaultTimeoutActions = await firstValueFrom(
|
||||||
this.vaultTimeoutSettingsService.availableVaultTimeoutActions$(),
|
this.vaultTimeoutSettingsService.availableVaultTimeoutActions$(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,53 @@
|
|||||||
|
<ng-container *ngIf="extensionRefreshFlag">
|
||||||
|
<bit-item *ngIf="account.id !== specialAccountAddId">
|
||||||
|
<button bit-item-content type="button" (click)="selectAccount(account.id)">
|
||||||
|
<bit-avatar
|
||||||
|
slot="start"
|
||||||
|
[id]="account.id"
|
||||||
|
[text]="account.name"
|
||||||
|
[color]="account.avatarColor"
|
||||||
|
size="small"
|
||||||
|
aria-hidden="true"
|
||||||
|
></bit-avatar>
|
||||||
|
|
||||||
|
<span class="tw-sr-only" *ngIf="status.text === 'active'">
|
||||||
|
{{ "activeAccount" | i18n }}:
|
||||||
|
</span>
|
||||||
|
<span class="tw-sr-only" *ngIf="status.text !== 'active'">
|
||||||
|
{{ "switchToAccount" | i18n }}
|
||||||
|
</span>
|
||||||
|
<div class="tw-max-w-64 tw-truncate">
|
||||||
|
{{ account.email }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container slot="secondary">
|
||||||
|
<div class="tw-max-w-64 tw-truncate tw-text-sm">
|
||||||
|
<span class="tw-sr-only">{{ "hostedAt" | i18n }}</span>
|
||||||
|
{{ account.server }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tw-text-sm tw-italic" [attr.aria-hidden]="status.text === 'active'">
|
||||||
|
<span class="tw-sr-only">(</span>
|
||||||
|
<span [ngClass]="status.text === 'active' ? 'tw-font-bold tw-text-success' : ''">{{
|
||||||
|
status.text
|
||||||
|
}}</span>
|
||||||
|
<span class="tw-sr-only">)</span>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<i slot="end" class="bwi tw-text-2xl" [ngClass]="status.icon" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</bit-item>
|
||||||
|
|
||||||
|
<bit-item *ngIf="account.id === specialAccountAddId">
|
||||||
|
<button type="button" bit-item-content (click)="selectAccount(account.id)">
|
||||||
|
<i slot="start" class="bwi bwi-plus tw-text-2xl tw-text-main" aria-hidden="true"></i>
|
||||||
|
{{ account.name | i18n }}
|
||||||
|
</button>
|
||||||
|
</bit-item>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!extensionRefreshFlag">
|
||||||
<button
|
<button
|
||||||
*ngIf="account.id !== specialAccountAddId"
|
*ngIf="account.id !== specialAccountAddId"
|
||||||
type="button"
|
type="button"
|
||||||
@@ -14,17 +64,21 @@
|
|||||||
></bit-avatar>
|
></bit-avatar>
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-text-left">
|
<div class="tw-text-left">
|
||||||
<span class="tw-sr-only" *ngIf="status.text === 'active'"> {{ "activeAccount" | i18n }}: </span>
|
<span class="tw-sr-only" *ngIf="status.text === 'active'">
|
||||||
|
{{ "activeAccount" | i18n }}:
|
||||||
|
</span>
|
||||||
<span class="tw-sr-only" *ngIf="status.text !== 'active'">
|
<span class="tw-sr-only" *ngIf="status.text !== 'active'">
|
||||||
{{ "switchToAccount" | i18n }}
|
{{ "switchToAccount" | i18n }}
|
||||||
</span>
|
</span>
|
||||||
<div class="tw-max-w-64 tw-truncate">
|
<div class="tw-max-w-64 tw-truncate">
|
||||||
{{ account.email }}
|
{{ account.email }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="account-switcher-row-details tw-max-w-64 tw-truncate tw-text-sm">
|
<div class="account-switcher-row-details tw-max-w-64 tw-truncate tw-text-sm">
|
||||||
<span class="tw-sr-only">{{ "hostedAt" | i18n }}</span>
|
<span class="tw-sr-only">{{ "hostedAt" | i18n }}</span>
|
||||||
{{ account.server }}
|
{{ account.server }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="account-switcher-row-details tw-text-sm tw-italic"
|
class="account-switcher-row-details tw-text-sm tw-italic"
|
||||||
[attr.aria-hidden]="status.text === 'active'"
|
[attr.aria-hidden]="status.text === 'active'"
|
||||||
@@ -52,3 +106,4 @@
|
|||||||
{{ account.name | i18n }}
|
{{ account.name | i18n }}
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
</ng-container>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
|
|||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { AvatarModule } from "@bitwarden/components";
|
import { AvatarModule, ItemModule } from "@bitwarden/components";
|
||||||
|
|
||||||
import { AccountSwitcherService, AvailableAccount } from "./services/account-switcher.service";
|
import { AccountSwitcherService, AvailableAccount } from "./services/account-switcher.service";
|
||||||
|
|
||||||
@@ -13,10 +13,11 @@ import { AccountSwitcherService, AvailableAccount } from "./services/account-swi
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
selector: "auth-account",
|
selector: "auth-account",
|
||||||
templateUrl: "account.component.html",
|
templateUrl: "account.component.html",
|
||||||
imports: [CommonModule, JslibModule, AvatarModule],
|
imports: [CommonModule, JslibModule, AvatarModule, ItemModule],
|
||||||
})
|
})
|
||||||
export class AccountComponent {
|
export class AccountComponent {
|
||||||
@Input() account: AvailableAccount;
|
@Input() account: AvailableAccount;
|
||||||
|
@Input() extensionRefreshFlag: boolean = false;
|
||||||
@Output() loading = new EventEmitter<boolean>();
|
@Output() loading = new EventEmitter<boolean>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component, Input } from "@angular/core";
|
import { Component, Input } from "@angular/core";
|
||||||
import { Observable, map, of, switchMap } from "rxjs";
|
import { Observable, map, of, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
|
|
||||||
|
import { CurrentAccountComponent } from "../../auth/popup/account-switching/current-account.component";
|
||||||
import { enableAccountSwitching } from "../flags";
|
import { enableAccountSwitching } from "../flags";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-header",
|
selector: "app-header",
|
||||||
templateUrl: "header.component.html",
|
templateUrl: "header.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule, CurrentAccountComponent],
|
||||||
})
|
})
|
||||||
export class HeaderComponent {
|
export class HeaderComponent {
|
||||||
@Input() noTheme = false;
|
@Input() noTheme = false;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { ColorPasswordPipe } from "@bitwarden/angular/pipes/color-password.pipe"
|
|||||||
import { UserVerificationDialogComponent } from "@bitwarden/auth/angular";
|
import { UserVerificationDialogComponent } from "@bitwarden/auth/angular";
|
||||||
import { AvatarModule, ButtonModule, ToastModule } from "@bitwarden/components";
|
import { AvatarModule, ButtonModule, ToastModule } from "@bitwarden/components";
|
||||||
|
|
||||||
import { AccountSwitcherComponent } from "../auth/popup/account-switching/account-switcher.component";
|
|
||||||
import { AccountComponent } from "../auth/popup/account-switching/account.component";
|
import { AccountComponent } from "../auth/popup/account-switching/account.component";
|
||||||
import { CurrentAccountComponent } from "../auth/popup/account-switching/current-account.component";
|
import { CurrentAccountComponent } from "../auth/popup/account-switching/current-account.component";
|
||||||
import { EnvironmentComponent } from "../auth/popup/environment.component";
|
import { EnvironmentComponent } from "../auth/popup/environment.component";
|
||||||
@@ -123,6 +122,7 @@ import "../platform/popup/locales";
|
|||||||
PopupTabNavigationComponent,
|
PopupTabNavigationComponent,
|
||||||
PopupFooterComponent,
|
PopupFooterComponent,
|
||||||
PopupHeaderComponent,
|
PopupHeaderComponent,
|
||||||
|
HeaderComponent,
|
||||||
UserVerificationDialogComponent,
|
UserVerificationDialogComponent,
|
||||||
CurrentAccountComponent,
|
CurrentAccountComponent,
|
||||||
],
|
],
|
||||||
@@ -145,7 +145,6 @@ import "../platform/popup/locales";
|
|||||||
FolderAddEditComponent,
|
FolderAddEditComponent,
|
||||||
FoldersComponent,
|
FoldersComponent,
|
||||||
VaultFilterComponent,
|
VaultFilterComponent,
|
||||||
HeaderComponent,
|
|
||||||
HintComponent,
|
HintComponent,
|
||||||
HomeComponent,
|
HomeComponent,
|
||||||
LockComponent,
|
LockComponent,
|
||||||
@@ -184,8 +183,8 @@ import "../platform/popup/locales";
|
|||||||
Fido2Component,
|
Fido2Component,
|
||||||
AutofillV1Component,
|
AutofillV1Component,
|
||||||
EnvironmentSelectorComponent,
|
EnvironmentSelectorComponent,
|
||||||
AccountSwitcherComponent,
|
|
||||||
],
|
],
|
||||||
|
exports: [],
|
||||||
providers: [CurrencyPipe, DatePipe],
|
providers: [CurrencyPipe, DatePipe],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user