mirror of
https://github.com/bitwarden/browser
synced 2025-01-22 17:22:56 +01:00
62ad39e697
* Create tracker that can await until expected observables are received. * Test dates are almost equal * Remove unused class method * Allow for updating active account in accout service fake * Correct observable tracker behavior Clarify documentation * Transition config service to state provider Updates the config fetching behavior to be lazy and ensure that any emitted value has been updated if older than a configurable value (statically compiled). If desired, config fetching can be ensured fresh through an async. * Update calls to config service in DI and bootstrapping * Migrate account server configs * Fix global config fetching * Test migration rollback * Adhere to implementation naming convention * Adhere to abstract class naming convention * Complete config abstraction rename * Remove unnecessary cli config service * Fix builds * Validate observable does not complete * Use token service to determine authed or unauthed config pull * Remove superfluous factory config * Name describe blocks after the thing they test * Remove implementation documentation Unfortunately the experience when linking to external documentation is quite poor. Instead of following the link and retrieving docs, you get a link that can be clicked to take you out of context to the docs. No link _does_ retrieve docs, but lacks indication in the implementation that documentation exists at all. On the balance, removing the link is the better experience. * Fix storybook
101 lines
3.8 KiB
TypeScript
101 lines
3.8 KiB
TypeScript
import { CommonModule } from "@angular/common";
|
|
import { Component, NgZone, OnDestroy, OnInit } from "@angular/core";
|
|
import { RouterModule } from "@angular/router";
|
|
import { firstValueFrom } from "rxjs";
|
|
|
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
|
import { IconModule, LayoutComponent, NavigationModule } from "@bitwarden/components";
|
|
|
|
import { PaymentMethodWarningsModule } from "../billing/shared";
|
|
|
|
import { PasswordManagerLogo } from "./password-manager-logo";
|
|
|
|
const BroadcasterSubscriptionId = "UserLayoutComponent";
|
|
|
|
@Component({
|
|
selector: "app-user-layout",
|
|
templateUrl: "user-layout.component.html",
|
|
standalone: true,
|
|
imports: [
|
|
CommonModule,
|
|
RouterModule,
|
|
JslibModule,
|
|
LayoutComponent,
|
|
IconModule,
|
|
NavigationModule,
|
|
PaymentMethodWarningsModule,
|
|
],
|
|
})
|
|
export class UserLayoutComponent implements OnInit, OnDestroy {
|
|
protected readonly logo = PasswordManagerLogo;
|
|
hasFamilySponsorshipAvailable: boolean;
|
|
hideSubscription: boolean;
|
|
|
|
protected showPaymentMethodWarningBanners$ = this.configService.getFeatureFlag$(
|
|
FeatureFlag.ShowPaymentMethodWarningBanners,
|
|
false,
|
|
);
|
|
|
|
constructor(
|
|
private broadcasterService: BroadcasterService,
|
|
private ngZone: NgZone,
|
|
private platformUtilsService: PlatformUtilsService,
|
|
private organizationService: OrganizationService,
|
|
private apiService: ApiService,
|
|
private syncService: SyncService,
|
|
private configService: ConfigService,
|
|
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
|
) {}
|
|
|
|
async ngOnInit() {
|
|
document.body.classList.remove("layout_frontend");
|
|
|
|
this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => {
|
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
this.ngZone.run(async () => {
|
|
switch (message.command) {
|
|
case "purchasedPremium":
|
|
await this.load();
|
|
break;
|
|
default:
|
|
}
|
|
});
|
|
});
|
|
|
|
await this.syncService.fullSync(false);
|
|
await this.load();
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
|
}
|
|
|
|
async load() {
|
|
const hasPremiumPersonally = await firstValueFrom(
|
|
this.billingAccountProfileStateService.hasPremiumPersonally$,
|
|
);
|
|
const hasPremiumFromOrg = await firstValueFrom(
|
|
this.billingAccountProfileStateService.hasPremiumFromAnyOrganization$,
|
|
);
|
|
const selfHosted = this.platformUtilsService.isSelfHost();
|
|
|
|
this.hasFamilySponsorshipAvailable = await this.organizationService.canManageSponsorships();
|
|
let billing = null;
|
|
if (!selfHosted) {
|
|
// TODO: We should remove the need to call this!
|
|
billing = await this.apiService.getUserBillingHistory();
|
|
}
|
|
this.hideSubscription =
|
|
!hasPremiumPersonally && hasPremiumFromOrg && (selfHosted || billing?.hasNoHistory);
|
|
}
|
|
}
|