diff --git a/jslib/common/src/abstractions/state.service.ts b/jslib/common/src/abstractions/state.service.ts index ebf94df3..e74470bd 100644 --- a/jslib/common/src/abstractions/state.service.ts +++ b/jslib/common/src/abstractions/state.service.ts @@ -1,4 +1,4 @@ -import { BehaviorSubject } from "rxjs"; +import { Observable } from "rxjs"; import { KdfType } from "../enums/kdfType"; import { ThemeType } from "../enums/themeType"; @@ -25,8 +25,8 @@ import { FolderView } from "../models/view/folderView"; import { SendView } from "../models/view/sendView"; export abstract class StateService { - accounts: BehaviorSubject<{ [userId: string]: T }>; - activeAccount: BehaviorSubject; + accounts$: Observable<{ [userId: string]: T }>; + activeAccount$: Observable; addAccount: (account: T) => Promise; setActiveUser: (userId: string) => Promise; diff --git a/jslib/common/src/services/environment.service.ts b/jslib/common/src/services/environment.service.ts index b13afd59..4ae8749f 100644 --- a/jslib/common/src/services/environment.service.ts +++ b/jslib/common/src/services/environment.service.ts @@ -1,4 +1,4 @@ -import { Observable, Subject } from "rxjs"; +import { concatMap, distinctUntilChanged, Observable, Subject } from "rxjs"; import { EnvironmentService as EnvironmentServiceAbstraction, @@ -21,9 +21,15 @@ export class EnvironmentService implements EnvironmentServiceAbstraction { private keyConnectorUrl: string; constructor(private stateService: StateService) { - this.stateService.activeAccount.subscribe(async () => { - await this.setUrlsFromStorage(); - }); + this.stateService.activeAccount$ + .pipe( + // Use == here to not trigger on undefined -> null transition + distinctUntilChanged((oldUserId: string, newUserId: string) => oldUserId == newUserId), + concatMap(async () => { + await this.setUrlsFromStorage(); + }), + ) + .subscribe(); } hasBaseUrl() { diff --git a/jslib/common/src/services/state.service.ts b/jslib/common/src/services/state.service.ts index 39a08f50..78ddaf82 100644 --- a/jslib/common/src/services/state.service.ts +++ b/jslib/common/src/services/state.service.ts @@ -52,8 +52,11 @@ export class StateService< TAccount extends Account = Account > implements StateServiceAbstraction { - accounts = new BehaviorSubject<{ [userId: string]: TAccount }>({}); - activeAccount = new BehaviorSubject(null); + protected accountsSubject = new BehaviorSubject<{ [userId: string]: TAccount }>({}); + accounts$ = this.accountsSubject.asObservable(); + + protected activeAccountSubject = new BehaviorSubject(null); + activeAccount$ = this.activeAccountSubject.asObservable(); protected state: State = new State( this.createGlobals() @@ -100,7 +103,7 @@ export class StateService< this.state.activeUserId = storedActiveUser; } await this.pushAccounts(); - this.activeAccount.next(this.state.activeUserId); + this.activeAccountSubject.next(this.state.activeUserId); } async syncAccountFromDisk(userId: string) { @@ -120,14 +123,14 @@ export class StateService< await this.scaffoldNewAccountStorage(account); await this.setLastActive(new Date().getTime(), { userId: account.profile.userId }); await this.setActiveUser(account.profile.userId); - this.activeAccount.next(account.profile.userId); + this.activeAccountSubject.next(account.profile.userId); } async setActiveUser(userId: string): Promise { this.clearDecryptedDataForActiveUser(); this.state.activeUserId = userId; await this.storageService.save(keys.activeUserId, userId); - this.activeAccount.next(this.state.activeUserId); + this.activeAccountSubject.next(this.state.activeUserId); await this.pushAccounts(); } @@ -2338,11 +2341,11 @@ export class StateService< protected async pushAccounts(): Promise { await this.pruneInMemoryAccounts(); if (this.state?.accounts == null || Object.keys(this.state.accounts).length < 1) { - this.accounts.next(null); + this.accountsSubject.next(null); return; } - this.accounts.next(this.state.accounts); + this.accountsSubject.next(this.state.accounts); } protected reconcileOptions( diff --git a/jslib/common/src/services/vaultTimeout.service.ts b/jslib/common/src/services/vaultTimeout.service.ts index a6513d65..e5cd1d81 100644 --- a/jslib/common/src/services/vaultTimeout.service.ts +++ b/jslib/common/src/services/vaultTimeout.service.ts @@ -1,3 +1,5 @@ +import { firstValueFrom } from "rxjs"; + import { CipherService } from "../abstractions/cipher.service"; import { CollectionService } from "../abstractions/collection.service"; import { CryptoService } from "../abstractions/crypto.service"; @@ -67,7 +69,8 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { return; } - for (const userId in this.stateService.accounts.getValue()) { + const accounts = await firstValueFrom(this.stateService.accounts$); + for (const userId in accounts) { if (userId != null && (await this.shouldLock(userId))) { await this.executeTimeoutAction(userId); } diff --git a/src/services/state.service.ts b/src/services/state.service.ts index 0d5e75b3..92c37d8d 100644 --- a/src/services/state.service.ts +++ b/src/services/state.service.ts @@ -560,10 +560,10 @@ export class StateService protected async pushAccounts(): Promise { if (this.state?.accounts == null || Object.keys(this.state.accounts).length < 1) { - this.accounts.next(null); + this.accountsSubject.next(null); return; } - this.accounts.next(this.state.accounts); + this.accountsSubject.next(this.state.accounts); } protected async hasTemporaryStorage(): Promise {