mirror of
https://github.com/bitwarden/browser
synced 2026-02-09 21:20:27 +00:00
Hide blue header for passkey popouts
This commit is contained in:
@@ -86,7 +86,7 @@ const SyncInterval = 6 * 60 * 60 * 1000; // 6 hours
|
||||
<ng-template #exportVault></ng-template>
|
||||
<ng-template #appGenerator></ng-template>
|
||||
<ng-template #loginApproval></ng-template>
|
||||
<app-header></app-header>
|
||||
<app-header *ngIf="showHeader$ | async"></app-header>
|
||||
|
||||
<div id="container">
|
||||
<div class="loading" *ngIf="loading">
|
||||
@@ -112,6 +112,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
@ViewChild("loginApproval", { read: ViewContainerRef, static: true })
|
||||
loginApprovalModalRef: ViewContainerRef;
|
||||
|
||||
showHeader$ = this.accountService.showHeader$;
|
||||
loading = false;
|
||||
|
||||
private lastActivity: Date = null;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
disableMargin
|
||||
class="tw-border-0 tw-border-b tw-border-solid tw-border-secondary-300"
|
||||
>
|
||||
<bit-section-header class="tw-bg-background">
|
||||
<bit-section-header class="passkey-header tw-bg-background">
|
||||
<div class="tw-flex tw-items-center">
|
||||
<bit-icon [icon]="Icons.BitwardenShield" class="tw-w-10 tw-mt-2 tw-ml-2"></bit-icon>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-close"
|
||||
slot="end"
|
||||
class="tw-mb-4 tw-mr-2"
|
||||
class="passkey-header-close tw-mb-4 tw-mr-2"
|
||||
(click)="closeModal()"
|
||||
>
|
||||
Close
|
||||
|
||||
@@ -67,6 +67,7 @@ export class Fido2CreateComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
await this.accountService.setShowHeader(false);
|
||||
this.session = this.fido2UserInterfaceService.getCurrentSession();
|
||||
const rpid = await this.session.getRpId();
|
||||
const equivalentDomains = await firstValueFrom(
|
||||
@@ -94,6 +95,10 @@ export class Fido2CreateComponent implements OnInit {
|
||||
.catch((error) => this.logService.error(error));
|
||||
}
|
||||
|
||||
async ngOnDestroy() {
|
||||
await this.accountService.setShowHeader(true);
|
||||
}
|
||||
|
||||
async addPasskeyToCipher(cipher: CipherView) {
|
||||
this.session.notifyConfirmCreateCredential(true, cipher);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
disableMargin
|
||||
class="tw-border-0 tw-border-b tw-border-solid tw-border-secondary-300"
|
||||
>
|
||||
<bit-section-header class="tw-bg-background">
|
||||
<bit-section-header class="passkey-header tw-bg-background">
|
||||
<div class="tw-flex tw-items-center">
|
||||
<bit-icon [icon]="Icons.BitwardenShield" class="tw-w-10 tw-mt-2 tw-ml-2"></bit-icon>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-close"
|
||||
slot="end"
|
||||
class="tw-mb-4 tw-mr-2"
|
||||
class="passkey-header-close tw-mb-4 tw-mr-2"
|
||||
(click)="closeModal()"
|
||||
>
|
||||
Close
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, OnInit, OnDestroy } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { RouterModule, Router } from "@angular/router";
|
||||
import { firstValueFrom, map, BehaviorSubject, Observable } from "rxjs";
|
||||
import { firstValueFrom, map, BehaviorSubject, Observable, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { BitwardenShield } from "@bitwarden/auth/angular";
|
||||
@@ -50,6 +49,7 @@ import { DesktopSettingsService } from "../../platform/services/desktop-settings
|
||||
})
|
||||
export class Fido2VaultComponent implements OnInit, OnDestroy {
|
||||
session?: DesktopFido2UserInterfaceSession = null;
|
||||
private destroy$ = new Subject<void>();
|
||||
private ciphersSubject = new BehaviorSubject<CipherView[]>([]);
|
||||
ciphers$: Observable<CipherView[]> = this.ciphersSubject.asObservable();
|
||||
private cipherIdsSubject = new BehaviorSubject<string[]>([]);
|
||||
@@ -67,6 +67,7 @@ export class Fido2VaultComponent implements OnInit, OnDestroy {
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
await this.accountService.setShowHeader(false);
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
@@ -74,7 +75,7 @@ export class Fido2VaultComponent implements OnInit, OnDestroy {
|
||||
this.session = this.fido2UserInterfaceService.getCurrentSession();
|
||||
this.cipherIds$ = this.session?.availableCipherIds$;
|
||||
|
||||
this.cipherIds$.pipe(takeUntilDestroyed()).subscribe((cipherIds) => {
|
||||
this.cipherIds$.pipe(takeUntil(this.destroy$)).subscribe((cipherIds) => {
|
||||
this.cipherService
|
||||
.getAllDecryptedForIds(activeUserId, cipherIds || [])
|
||||
.then((ciphers) => {
|
||||
@@ -84,7 +85,8 @@ export class Fido2VaultComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
async ngOnDestroy() {
|
||||
await this.accountService.setShowHeader(true);
|
||||
this.cipherIdsSubject.complete(); // Clean up the BehaviorSubject
|
||||
}
|
||||
|
||||
|
||||
@@ -232,3 +232,11 @@
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
.passkey-header {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
.passkey-header-close {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ export class FakeAccountService implements AccountService {
|
||||
accountActivitySubject = new ReplaySubject<Record<UserId, Date>>(1);
|
||||
// eslint-disable-next-line rxjs/no-exposed-subjects -- test class
|
||||
accountVerifyDevicesSubject = new ReplaySubject<boolean>(1);
|
||||
// eslint-disable-next-line rxjs/no-exposed-subjects -- test class
|
||||
showHeaderSubject = new ReplaySubject<boolean>(1);
|
||||
private _activeUserId: UserId;
|
||||
get activeUserId() {
|
||||
return this._activeUserId;
|
||||
@@ -55,6 +57,7 @@ export class FakeAccountService implements AccountService {
|
||||
}),
|
||||
);
|
||||
}
|
||||
showHeader$ = this.showHeaderSubject.asObservable();
|
||||
get nextUpAccount$(): Observable<Account> {
|
||||
return combineLatest([this.accounts$, this.activeAccount$, this.sortedUserIds$]).pipe(
|
||||
map(([accounts, activeAccount, sortedUserIds]) => {
|
||||
@@ -114,6 +117,10 @@ export class FakeAccountService implements AccountService {
|
||||
this.accountsSubject.next(updated);
|
||||
await this.mock.clean(userId);
|
||||
}
|
||||
|
||||
async setShowHeader(value: boolean): Promise<void> {
|
||||
this.showHeaderSubject.next(value);
|
||||
}
|
||||
}
|
||||
|
||||
const loggedOutInfo: AccountInfo = {
|
||||
|
||||
@@ -49,6 +49,7 @@ export abstract class AccountService {
|
||||
sortedUserIds$: Observable<UserId[]>;
|
||||
/** Next account that is not the current active account */
|
||||
nextUpAccount$: Observable<Account>;
|
||||
showHeader$: Observable<boolean>;
|
||||
/**
|
||||
* Updates the `accounts$` observable with the new account data.
|
||||
*
|
||||
@@ -102,6 +103,11 @@ export abstract class AccountService {
|
||||
* @param lastActivity
|
||||
*/
|
||||
abstract setAccountActivity(userId: UserId, lastActivity: Date): Promise<void>;
|
||||
/**
|
||||
* Show the account switcher.
|
||||
* @param value
|
||||
*/
|
||||
abstract setShowHeader(visible: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export abstract class InternalAccountService extends AccountService {
|
||||
|
||||
@@ -429,6 +429,24 @@ describe("accountService", () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("setShowHeader", () => {
|
||||
it("should update _showHeader$ when setShowHeader is called", async () => {
|
||||
expect(sut["_showHeader$"].value).toBe(true);
|
||||
|
||||
await sut.setShowHeader(false);
|
||||
expect(sut["_showHeader$"].value).toBe(false);
|
||||
});
|
||||
|
||||
it("should emit values correctly", (done) => {
|
||||
sut.showHeader$.subscribe((value) => {
|
||||
expect(value).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
await sut.setShowHeader(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
distinctUntilChanged,
|
||||
shareReplay,
|
||||
combineLatest,
|
||||
BehaviorSubject,
|
||||
Observable,
|
||||
switchMap,
|
||||
filter,
|
||||
@@ -84,6 +85,7 @@ export const getOptionalUserId = map<Account | null, UserId | null>(
|
||||
export class AccountServiceImplementation implements InternalAccountService {
|
||||
private accountsState: GlobalState<Record<UserId, AccountInfo>>;
|
||||
private activeAccountIdState: GlobalState<UserId | undefined>;
|
||||
private _showHeader$ = new BehaviorSubject<boolean>(true);
|
||||
|
||||
accounts$: Observable<Record<UserId, AccountInfo>>;
|
||||
activeAccount$: Observable<Account | null>;
|
||||
@@ -91,6 +93,7 @@ export class AccountServiceImplementation implements InternalAccountService {
|
||||
accountVerifyNewDeviceLogin$: Observable<boolean>;
|
||||
sortedUserIds$: Observable<UserId[]>;
|
||||
nextUpAccount$: Observable<Account>;
|
||||
showHeader$ = this._showHeader$.asObservable();
|
||||
|
||||
constructor(
|
||||
private messagingService: MessagingService,
|
||||
@@ -260,6 +263,10 @@ export class AccountServiceImplementation implements InternalAccountService {
|
||||
}
|
||||
}
|
||||
|
||||
async setShowHeader(visible: boolean): Promise<void> {
|
||||
this._showHeader$.next(visible);
|
||||
}
|
||||
|
||||
private async setAccountInfo(userId: UserId, update: Partial<AccountInfo>): Promise<void> {
|
||||
function newAccountInfo(oldAccountInfo: AccountInfo): AccountInfo {
|
||||
return { ...oldAccountInfo, ...update };
|
||||
|
||||
Reference in New Issue
Block a user