mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 21:33:27 +00:00
[PM-18903] Desktop sync issues (#13681)
* [PM-18707] Use different BroadcasterSubscriptionId in base view component to avoid collision with desktop view component * [PM-18707] Use userId instead of payloadUserId for cipher notification syncs * [PM-19032] Live Sync on Desktop (#13851) * migrate the vault-items to an observables rather than async/promises - this helps keep data in sync with the service state and avoids race conditions * migrate the view component to an observables rather than async/promises - this helps keep data in sync with the service state and avoids race conditions * decrypt saved cipher from server * bump timeout for upserting ciphers * mark `go` as async in desktop vault - previously it was a floating promise * Revert "mark `go` as async in desktop vault" This reverts commitfd28f40b18. * Revert "bump timeout for upserting ciphers" This reverts commite963acc377. * move vault utilities to `common` rather than `lib` to avoid circular dependencies * use `perUserCache$` for `cipherViews$` to avoid new subscriptions from being created * use userId from observable rather than locally set to be the most up to date * [PM-18707] Add clearBuffer$ input to perUserCache$ helper so that the internal share replay buffers can be cleared * [PM-18707] Rework forceCipherViews$ to clearBuffer$ refactor - Add dependency for cipherDecryptionKeys$ for the cipherViews so that decryption is never attempted without keys * [PM-18707] Add overload to perUserCache to satisfy type checker * [PM-18707] Fix overloads * [PM-18707] Add check for empty failed to decrypt ciphers * [PM-18707] Mark vault component for check after observable emits. The cipherViews$ observable now persists between subscriptions, meaning that updates via the sync push notifications can occur outside the AngularZone causing delays in updating the view. --------- Co-authored-by: Nick Krantz <125900171+nick-livefront@users.noreply.github.com> Co-authored-by: Nick Krantz <nick@livefront.com>
This commit is contained in:
@@ -27,9 +27,6 @@ export class VaultItemsComponent extends BaseVaultItemsComponent {
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
searchBarService.searchText$.pipe(distinctUntilChanged()).subscribe((searchText) => {
|
||||
this.searchText = searchText;
|
||||
// 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.search(200);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -126,9 +126,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro
|
||||
}
|
||||
|
||||
async ngOnChanges() {
|
||||
await super.load();
|
||||
|
||||
if (this.cipher.decryptionFailure) {
|
||||
if (this.cipher?.decryptionFailure) {
|
||||
DecryptionFailureDialogComponent.open(this.dialogService, {
|
||||
cipherIds: [this.cipherId as CipherId],
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
Subject,
|
||||
} from "rxjs";
|
||||
import {
|
||||
catchError,
|
||||
concatMap,
|
||||
debounceTime,
|
||||
filter,
|
||||
@@ -23,7 +24,6 @@ import {
|
||||
take,
|
||||
takeUntil,
|
||||
tap,
|
||||
catchError,
|
||||
} from "rxjs/operators";
|
||||
|
||||
import {
|
||||
@@ -64,6 +64,7 @@ import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-repromp
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { ServiceUtils } from "@bitwarden/common/vault/service-utils";
|
||||
import { filterOutNullish } from "@bitwarden/common/vault/utils/observable-utilities";
|
||||
import { DialogRef, DialogService, Icons, ToastService } from "@bitwarden/components";
|
||||
import {
|
||||
AddEditFolderDialogComponent,
|
||||
@@ -138,7 +139,6 @@ const SearchTextDebounceInterval = 200;
|
||||
VaultFilterModule,
|
||||
VaultItemsModule,
|
||||
SharedModule,
|
||||
DecryptionFailureDialogComponent,
|
||||
],
|
||||
providers: [
|
||||
RoutedVaultFilterService,
|
||||
@@ -348,9 +348,8 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
]).pipe(
|
||||
filter(([ciphers, filter]) => ciphers != undefined && filter != undefined),
|
||||
concatMap(async ([ciphers, filter, searchText]) => {
|
||||
const failedCiphers = await firstValueFrom(
|
||||
this.cipherService.failedToDecryptCiphers$(activeUserId),
|
||||
);
|
||||
const failedCiphers =
|
||||
(await firstValueFrom(this.cipherService.failedToDecryptCiphers$(activeUserId))) ?? [];
|
||||
const filterFunction = createFilterFunction(filter);
|
||||
// Append any failed to decrypt ciphers to the top of the cipher list
|
||||
const allCiphers = [...failedCiphers, ...ciphers];
|
||||
@@ -472,6 +471,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
firstSetup$
|
||||
.pipe(
|
||||
switchMap(() => this.cipherService.failedToDecryptCiphers$(activeUserId)),
|
||||
filterOutNullish(),
|
||||
map((ciphers) => ciphers.filter((c) => !c.isDeleted)),
|
||||
filter((ciphers) => ciphers.length > 0),
|
||||
take(1),
|
||||
@@ -528,6 +528,10 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
this.isEmpty = collections?.length === 0 && ciphers?.length === 0;
|
||||
this.performingInitialLoad = false;
|
||||
this.refreshing = false;
|
||||
|
||||
// Explicitly mark for check to ensure the view is updated
|
||||
// Some sources are not always emitted within the Angular zone (e.g. ciphers updated via WS notifications)
|
||||
this.changeDetectorRef.markForCheck();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user