mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 06:13:38 +00:00
[PM-18707] Fix desktop live sync (#13624)
* [PM-18707] Remove redundant cipherService subscription * [PM-18707] Add artificial tick delay to cipherService to allow for ElectronStore storage service to fully save before continuing
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { BehaviorSubject, Subject, firstValueFrom, from, switchMap, takeUntil } from "rxjs";
|
||||||
import { BehaviorSubject, Subject, firstValueFrom, from, map, switchMap, takeUntil } from "rxjs";
|
|
||||||
|
|
||||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
@@ -22,11 +21,9 @@ export class VaultItemsComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
loaded = false;
|
loaded = false;
|
||||||
ciphers: CipherView[] = [];
|
ciphers: CipherView[] = [];
|
||||||
searchPlaceholder: string = null;
|
|
||||||
filter: (cipher: CipherView) => boolean = null;
|
filter: (cipher: CipherView) => boolean = null;
|
||||||
deleted = false;
|
deleted = false;
|
||||||
organization: Organization;
|
organization: Organization;
|
||||||
accessEvents = false;
|
|
||||||
|
|
||||||
protected searchPending = false;
|
protected searchPending = false;
|
||||||
|
|
||||||
@@ -45,20 +42,7 @@ export class VaultItemsComponent implements OnInit, OnDestroy {
|
|||||||
protected searchService: SearchService,
|
protected searchService: SearchService,
|
||||||
protected cipherService: CipherService,
|
protected cipherService: CipherService,
|
||||||
protected accountService: AccountService,
|
protected accountService: AccountService,
|
||||||
) {
|
) {}
|
||||||
this.accountService.activeAccount$
|
|
||||||
.pipe(
|
|
||||||
getUserId,
|
|
||||||
switchMap((userId) =>
|
|
||||||
this.cipherService.cipherViews$(userId).pipe(map((ciphers) => ({ userId, ciphers }))),
|
|
||||||
),
|
|
||||||
takeUntilDestroyed(),
|
|
||||||
)
|
|
||||||
.subscribe(({ userId, ciphers }) => {
|
|
||||||
void this.doSearch(ciphers, userId);
|
|
||||||
this.loaded = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this._searchText$
|
this._searchText$
|
||||||
|
|||||||
@@ -980,10 +980,14 @@ export class CipherService implements CipherServiceAbstraction {
|
|||||||
|
|
||||||
async upsert(cipher: CipherData | CipherData[]): Promise<Record<CipherId, CipherData>> {
|
async upsert(cipher: CipherData | CipherData[]): Promise<Record<CipherId, CipherData>> {
|
||||||
const ciphers = cipher instanceof CipherData ? [cipher] : cipher;
|
const ciphers = cipher instanceof CipherData ? [cipher] : cipher;
|
||||||
return await this.updateEncryptedCipherState((current) => {
|
const res = await this.updateEncryptedCipherState((current) => {
|
||||||
ciphers.forEach((c) => (current[c.id as CipherId] = c));
|
ciphers.forEach((c) => (current[c.id as CipherId] = c));
|
||||||
return current;
|
return current;
|
||||||
});
|
});
|
||||||
|
// Some state storage providers (e.g. Electron) don't update the state immediately, wait for next tick
|
||||||
|
// Otherwise, subscribers to cipherViews$ can get stale data
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async replace(ciphers: { [id: string]: CipherData }, userId: UserId): Promise<any> {
|
async replace(ciphers: { [id: string]: CipherData }, userId: UserId): Promise<any> {
|
||||||
@@ -1000,13 +1004,16 @@ export class CipherService implements CipherServiceAbstraction {
|
|||||||
userId: UserId = null,
|
userId: UserId = null,
|
||||||
): Promise<Record<CipherId, CipherData>> {
|
): Promise<Record<CipherId, CipherData>> {
|
||||||
userId ||= await firstValueFrom(this.stateProvider.activeUserId$);
|
userId ||= await firstValueFrom(this.stateProvider.activeUserId$);
|
||||||
await this.clearDecryptedCiphersState(userId);
|
await this.clearCache(userId);
|
||||||
const updatedCiphers = await this.stateProvider
|
const updatedCiphers = await this.stateProvider
|
||||||
.getUser(userId, ENCRYPTED_CIPHERS)
|
.getUser(userId, ENCRYPTED_CIPHERS)
|
||||||
.update((current) => {
|
.update((current) => {
|
||||||
const result = update(current ?? {});
|
const result = update(current ?? {});
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
// Some state storage providers (e.g. Electron) don't update the state immediately, wait for next tick
|
||||||
|
// Otherwise, subscribers to cipherViews$ can get stale data
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
return updatedCiphers;
|
return updatedCiphers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user