From bf5affa2ae754f2280e8ae4ce217a6b0e6111f25 Mon Sep 17 00:00:00 2001 From: jaasen-livefront Date: Fri, 21 Nov 2025 12:55:10 -0800 Subject: [PATCH] Revert "reduce emissions to vault list" This reverts commit 8354238541aecdc6bd8aed129b82b012fba4a418. --- .../services/vault-popup-items.service.ts | 6 +- .../src/vault/abstractions/cipher.service.ts | 10 --- .../src/vault/services/cipher.service.ts | 79 +++++-------------- 3 files changed, 20 insertions(+), 75 deletions(-) diff --git a/apps/browser/src/vault/popup/services/vault-popup-items.service.ts b/apps/browser/src/vault/popup/services/vault-popup-items.service.ts index 220fbb3ce7e..07c57df1eed 100644 --- a/apps/browser/src/vault/popup/services/vault-popup-items.service.ts +++ b/apps/browser/src/vault/popup/services/vault-popup-items.service.ts @@ -109,10 +109,7 @@ export class VaultPopupItemsService { map((a) => a?.id), filter((userId): userId is UserId => userId != null), switchMap((userId) => - merge( - this.cipherService.ciphers$(userId), - this.cipherService.ciphersWithLocalData$(userId), - ).pipe( + merge(this.cipherService.ciphers$(userId), this.cipherService.localData$(userId)).pipe( runInsideAngular(this.ngZone), tap(() => this._ciphersLoading$.next()), waitUntilSync(this.syncService), @@ -166,7 +163,6 @@ export class VaultPopupItemsService { }), ), ), - shareReplay({ refCount: false, bufferSize: 1 }), ); /** diff --git a/libs/common/src/vault/abstractions/cipher.service.ts b/libs/common/src/vault/abstractions/cipher.service.ts index f5fac9faaf0..9aefd960b2f 100644 --- a/libs/common/src/vault/abstractions/cipher.service.ts +++ b/libs/common/src/vault/abstractions/cipher.service.ts @@ -32,16 +32,6 @@ export abstract class CipherService implements UserKeyRotationDataProvider; abstract ciphers$(userId: UserId): Observable>; abstract localData$(userId: UserId): Observable>; - /** - * Emits decrypted (or list-view) ciphers merged with their LocalData. - * - * The emitted items must be treated as {@link CipherViewLike}, - * since the underlying implementation may emit either `CipherView` - * or `CipherListView` depending on feature flags. - * - * Never emits `null`; always emits an array (empty or populated). - */ - abstract ciphersWithLocalData$(userId: UserId): Observable; /** * An observable monitoring the add/edit cipher info saved to memory. */ diff --git a/libs/common/src/vault/services/cipher.service.ts b/libs/common/src/vault/services/cipher.service.ts index 1ee858f53d0..1e7e5302d41 100644 --- a/libs/common/src/vault/services/cipher.service.ts +++ b/libs/common/src/vault/services/cipher.service.ts @@ -168,57 +168,6 @@ export class CipherService implements CipherServiceAbstraction { ); }); - private cipherListWithoutLocalData$ = perUserCache$((userId: UserId) => { - return this.configService.getFeatureFlag$(FeatureFlag.PM22134SdkCipherListView).pipe( - switchMap((useSdk) => { - if (!useSdk) { - return this.cipherViews$(userId).pipe( - // filter out "null" decrypt-in-progress if it ever appears - filter((ciphers): ciphers is CipherView[] => ciphers != null), - ); - } - - return combineLatest([ - this.encryptedCiphersState(userId).state$, - this.keyService.cipherDecryptionKeys$(userId, true), - ]).pipe( - filter(([cipherDataState, keys]) => cipherDataState != null && keys != null), - map(([cipherDataState]) => Object.values(cipherDataState)), - switchMap(async (cipherDataArray) => { - const ciphers = cipherDataArray.map((c) => new Cipher(c)); - const [decrypted, failures] = await this.decryptCiphersWithSdk(ciphers, userId, false); - await this.setFailedDecryptedCiphers(failures, userId); - return decrypted; - }), - ); - }), - ); - }); - - ciphersWithLocalData$(userId: UserId): Observable { - return combineLatest([this.cipherListViews$(userId), this.localData$(userId)]).pipe( - map(([ciphers, localData]) => { - if (!ciphers) { - return [] as CipherViewLike[]; - } - - return ciphers.map((cipher) => { - const cipherId = uuidAsString(cipher.id) as CipherId; - const local = localData?.[cipherId]; - - if (!local) { - return cipher as CipherViewLike; - } - - return { - ...(cipher as CipherViewLike), - localData: local, - } as CipherViewLike; - }); - }), - ); - } - /** * Observable that emits an array of decrypted ciphers for the active user. * This observable will not emit until the encrypted ciphers have either been loaded from state or after sync. @@ -229,9 +178,10 @@ export class CipherService implements CipherServiceAbstraction { cipherViews$ = perUserCache$((userId: UserId): Observable => { return combineLatest([ this.encryptedCiphersState(userId).state$, + this.localData$(userId), this.keyService.cipherDecryptionKeys$(userId), ]).pipe( - filter(([ciphers, keys]) => ciphers != null && keys != null), + filter(([ciphers, _, keys]) => ciphers != null && keys != null), // Skip if ciphers haven't been loaded yor synced yet switchMap(() => this.getAllDecrypted(userId)), tap(() => { this.messageSender.send("updateOverlayCiphers"); @@ -846,18 +796,27 @@ export class CipherService implements CipherServiceAbstraction { } const cipherId = id as CipherId; - const now = new Date().getTime(); + if (ciphersLocalData[cipherId]) { + ciphersLocalData[cipherId].lastUsedDate = new Date().getTime(); + } else { + ciphersLocalData[cipherId] = { lastUsedDate: new Date().getTime() }; + } - if (ciphersLocalData[cipherId]?.lastUsedDate === now) { + await this.localDataState(userId).update(() => ciphersLocalData); + + const decryptedCipherCache = await this.getDecryptedCiphers(userId); + if (!decryptedCipherCache) { return; } - ciphersLocalData[cipherId] = { - ...(ciphersLocalData[cipherId] ?? {}), - lastUsedDate: now, - }; - - await this.localDataState(userId).update(() => ciphersLocalData); + for (let i = 0; i < decryptedCipherCache.length; i++) { + const cached = decryptedCipherCache[i]; + if (cached.id === id) { + cached.localData = ciphersLocalData[id as CipherId]; + break; + } + } + await this.setDecryptedCiphers(decryptedCipherCache, userId); } async updateLastLaunchedDate(id: string, userId: UserId): Promise {