1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-08 04:33:38 +00:00

feat(billing): Add vault dialog launch logic

This commit is contained in:
Stephon Brown
2025-10-02 12:14:00 -04:00
parent 60e32fb1c8
commit 1a4d4d6bef

View File

@@ -32,6 +32,7 @@ import {
Unassigned,
} from "@bitwarden/admin-console/common";
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
import { VaultProfileService } from "@bitwarden/angular/vault/services/vault-profile.service";
import {
NoResults,
DeactivatedOrg,
@@ -52,7 +53,9 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
import { EventType } from "@bitwarden/common/enums";
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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -103,6 +106,10 @@ import {
CollectionDialogTabType,
openCollectionDialog,
} from "../../admin-console/organizations/shared/components/collection-dialog";
import {
UnifiedUpgradeDialogComponent,
UnifiedUpgradeDialogResult,
} from "../../billing/individual/upgrade/unified-upgrade-dialog/unified-upgrade-dialog.component";
import { SharedModule } from "../../shared/shared.module";
import { AssignCollectionsWebComponent } from "../components/assign-collections";
import {
@@ -205,6 +212,8 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
private vaultItemDialogRef?: DialogRef<VaultItemDialogResult> | undefined;
protected showAddCipherBtn: boolean = false;
private unifiedDialogRef?: DialogRef<UnifiedUpgradeDialogResult>;
organizations$ = this.accountService.activeAccount$
.pipe(map((a) => a?.id))
.pipe(switchMap((id) => this.organizationService.organizations$(id)));
@@ -306,6 +315,8 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
private restrictedItemTypesService: RestrictedItemTypesService,
private cipherArchiveService: CipherArchiveService,
private organizationWarningsService: OrganizationWarningsService,
private vaultProfileService: VaultProfileService,
private configService: ConfigService,
) {}
async ngOnInit() {
@@ -606,6 +617,58 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
this.changeDetectorRef.markForCheck();
},
);
const showUpgradeDialog$: Observable<boolean> = combineLatest([
this.accountService.activeAccount$,
this.configService.getFeatureFlag$(FeatureFlag.PM24996_ImplementUpgradeFromFreeDialog),
this.billingAccountProfileStateService.hasPremiumFromAnySource$(activeUserId),
]).pipe(
switchMap(async ([account, isFlagEnabled, hasPremium]) => {
// If user already has premium, no need to check profile age
if (hasPremium || !isFlagEnabled) {
return false;
}
const isProfileLessThanFiveMinutesOld = await this.isProfileLessThanFiveMinutesOld(
account?.id,
);
return isFlagEnabled && !hasPremium && isProfileLessThanFiveMinutesOld;
}),
);
showUpgradeDialog$.pipe(takeUntil(this.destroy$)).subscribe((show) => {
if (show && this.unifiedDialogRef == null) {
this.launchUpgradeDialogFlow().catch((err) => {
this.logService.error("Error in upgrade dialog flow", err);
});
}
});
}
private async isProfileLessThanFiveMinutesOld(userId: string): Promise<boolean> {
const createdAtDate = await this.vaultProfileService.getProfileCreationDate(userId);
if (!createdAtDate) {
return false;
}
const createdAtInMs = createdAtDate.getTime();
const nowInMs = new Date().getTime();
const differenceInMs = nowInMs - createdAtInMs;
const msInAMinute = 1000 * 60; // Milliseconds in a minute for conversion 1 minute = 60 seconds * 1000 ms
const differenceInMinutes = Math.round(differenceInMs / msInAMinute);
return differenceInMinutes <= 5;
}
private async launchUpgradeDialogFlow(): Promise<void> {
const account = await firstValueFrom(this.accountService.activeAccount$);
this.unifiedDialogRef = UnifiedUpgradeDialogComponent.open(this.dialogService, {
data: { account: account },
});
await lastValueFrom(this.unifiedDialogRef.closed);
this.unifiedDialogRef = undefined;
}
ngOnDestroy() {