From b796fe094f544f15407e3f095dcc5b3da7c763a5 Mon Sep 17 00:00:00 2001 From: Addison Beck Date: Wed, 19 Jan 2022 11:00:28 -0500 Subject: [PATCH] [Bug] [Account Switching] Improve State Management Performance (#1237) * [dep] Implement new StateService factory parameter from jslib * [bug] Ensure setLastActive uses the correct userId Sometimes, because of how often it fires, setLastActive can cause accounts to override each other. To make sure the correct userId is always used we now subscribe to activeUser in the appComponent and pass that value into any setLastActive calls. * [bug] Show loader when logging out When logging out of a large vault the application can appear to hang. This commit turns on the app component loader while logout is doing work. * [bug] Stop tracking activity without an active user * [style] Ran prettier * [chore] Update jslib --- jslib | 2 +- src/app/app.component.ts | 20 ++++++++++++++------ src/app/services.module.ts | 18 +++++++++++++++++- src/main.ts | 10 +++++++++- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/jslib b/jslib index 957e0100..ccd715d7 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 957e010036c89cfbcb0b526eea99c4b9e292b1f8 +Subproject commit ccd715d7b84545bc1c8f41faf3120d337ce714c3 diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 3c4ba213..1517a967 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -122,15 +122,21 @@ export class AppComponent implements OnInit { ) {} ngOnInit() { + let activeUserId: string = null; + this.stateService.activeAccount.subscribe((userId) => { + activeUserId = userId; + }); this.ngZone.runOutsideAngular(() => { setTimeout(async () => { await this.updateAppMenu(); }, 1000); - window.ontouchstart = () => this.recordActivity(); - window.onmousedown = () => this.recordActivity(); - window.onscroll = () => this.recordActivity(); - window.onkeypress = () => this.recordActivity(); + if (activeUserId != null) { + window.ontouchstart = () => this.recordActivity(activeUserId); + window.onmousedown = () => this.recordActivity(activeUserId); + window.onscroll = () => this.recordActivity(activeUserId); + window.onkeypress = () => this.recordActivity(activeUserId); + } }); this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { @@ -155,7 +161,9 @@ export class AppComponent implements OnInit { this.router.navigate(["login"]); break; case "logout": + this.loading = true; await this.logOut(!!message.expired, message.userId); + this.loading = false; break; case "lockVault": await this.vaultTimeoutService.lock(true, message.userId); @@ -479,14 +487,14 @@ export class AppComponent implements OnInit { await this.updateAppMenu(); } - private async recordActivity() { + private async recordActivity(userId: string) { const now = new Date().getTime(); if (this.lastActivity != null && now - this.lastActivity < 250) { return; } this.lastActivity = now; - await this.stateService.setLastActive(now); + await this.stateService.setLastActive(now, { userId: userId }); // Idle states if (this.isIdle) { diff --git a/src/app/services.module.ts b/src/app/services.module.ts index 385d97be..e7b367b7 100644 --- a/src/app/services.module.ts +++ b/src/app/services.module.ts @@ -45,6 +45,10 @@ import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-com import { ThemeType } from "jslib-common/enums/themeType"; +import { Account } from "../models/account"; + +import { AccountFactory } from "jslib-common/models/domain/account"; + export function initFactory( window: Window, environmentService: EnvironmentServiceAbstraction, @@ -173,7 +177,19 @@ export function initFactory( }, { provide: StateServiceAbstraction, - useClass: StateService, + useFactory: ( + storageService: StorageServiceAbstraction, + secureStorageService: StorageServiceAbstraction, + logService: LogServiceAbstraction, + stateMigrationService: StateMigrationServiceAbstraction + ) => + new StateService( + storageService, + secureStorageService, + logService, + stateMigrationService, + new AccountFactory(Account) + ), deps: [ StorageServiceAbstraction, "SECURE_STORAGE", diff --git a/src/main.ts b/src/main.ts index afc4f7d7..c2be3d9d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -22,6 +22,8 @@ import { NativeMessagingMain } from "./main/nativeMessaging.main"; import { StateService } from "jslib-common/services/state.service"; +import { Account, AccountFactory } from "jslib-common/models/domain/account"; + export class Main { logService: ElectronLogService; i18nService: I18nService; @@ -79,7 +81,13 @@ export class Main { // TODO: this state service will have access to on disk storage, but not in memory storage. // If we could get this to work using the stateService singleton that the rest of the app uses we could save // ourselves from some hacks, like having to manually update the app menu vs. the menu subscribing to events. - this.stateService = new StateService(this.storageService, null, this.logService, null); + this.stateService = new StateService( + this.storageService, + null, + this.logService, + null, + new AccountFactory(Account) + ); this.windowMain = new WindowMain( this.stateService,