diff --git a/libs/angular/src/tools/send/add-edit.component.ts b/libs/angular/src/tools/send/add-edit.component.ts index 2e4b2cd57b..9742de1a7b 100644 --- a/libs/angular/src/tools/send/add-edit.component.ts +++ b/libs/angular/src/tools/send/add-edit.component.ts @@ -1,7 +1,7 @@ import { DatePipe } from "@angular/common"; import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; -import { Subject, map, takeUntil } from "rxjs"; +import { BehaviorSubject, Subject, concatMap, firstValueFrom, map, takeUntil } from "rxjs"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyType } from "@bitwarden/common/admin-console/enums"; @@ -167,7 +167,7 @@ export class AddEditComponent implements OnInit, OnDestroy { } }); - this.formGroup.controls.type.valueChanges.subscribe((val) => { + this.formGroup.controls.type.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((val) => { this.type = val; this.typeChanged(); }); @@ -210,28 +210,46 @@ export class AddEditComponent implements OnInit, OnDestroy { this.type = !this.canAccessPremium || !this.emailVerified ? SendType.Text : SendType.File; if (this.send == null) { - if (this.editMode) { - const send = this.loadSend(); - this.send = await send.decrypt(); - this.type = this.send.type; - this.updateFormValues(); - } else { - this.send = new SendView(); - this.send.type = this.type; - this.send.file = new SendFileView(); - this.send.text = new SendTextView(); - this.send.deletionDate = new Date(); - this.send.deletionDate.setDate(this.send.deletionDate.getDate() + 7); - this.formGroup.controls.type.patchValue(this.send.type); + const send = new BehaviorSubject(this.send); + send.subscribe({ + next: (decryptedSend: SendView | undefined) => { + if (!(decryptedSend instanceof SendView)) { + return; + } - this.formGroup.patchValue({ - selectedDeletionDatePreset: DatePreset.SevenDays, - selectedExpirationDatePreset: DatePreset.Never, - }); + this.send = decryptedSend; + decryptedSend.type = decryptedSend.type ?? this.type; + this.type = this.send.type; + this.updateFormValues(); + this.hasPassword = this.send.password != null && this.send.password.trim() !== ""; + }, + error: (error: unknown) => { + const errorMessage = (error as Error).message ?? "An unknown error occurred"; + this.logService.error("Failed to decrypt send: " + errorMessage); + }, + }); + + if (this.editMode) { + this.sendService + .get$(this.sendId) + .pipe( + //Promise.reject will complete the BehaviourSubject, if desktop starts relying only on BehaviourSubject, this should be changed. + concatMap((s) => + s instanceof Send ? s.decrypt() : Promise.reject(new Error("Failed to load send.")), + ), + takeUntil(this.destroy$), + ) + .subscribe(send); + } else { + const sendView = new SendView(); + sendView.type = this.type; + sendView.file = new SendFileView(); + sendView.text = new SendTextView(); + sendView.deletionDate = new Date(); + sendView.deletionDate.setDate(sendView.deletionDate.getDate() + 7); + send.next(sendView); } } - - this.hasPassword = this.send.password != null && this.send.password.trim() !== ""; } async submit(): Promise { @@ -376,8 +394,8 @@ export class AddEditComponent implements OnInit, OnDestroy { this.showOptions = !this.showOptions; } - protected loadSend(): Send { - return this.sendService.get(this.sendId); + protected loadSend(): Promise { + return firstValueFrom(this.sendService.get$(this.sendId)); } protected async encryptSend(file: File): Promise<[Send, EncArrayBuffer]> {