diff --git a/jslib b/jslib index 0e9e73ce95..1beb30d111 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 0e9e73ce95a321ee05edbb62c50f9e1828f69c5a +Subproject commit 1beb30d11193bcb2e57fbdb8a147ddcb0c0ddbc2 diff --git a/src/app/accounts/lock.component.ts b/src/app/accounts/lock.component.ts index 33b6d5ae80..24cc7a1022 100644 --- a/src/app/accounts/lock.component.ts +++ b/src/app/accounts/lock.component.ts @@ -1,4 +1,7 @@ -import { Component } from '@angular/core'; +import { + Component, + NgZone, +} from '@angular/core'; import { ActivatedRoute, Router, @@ -15,8 +18,12 @@ import { StorageService } from 'jslib/abstractions/storage.service'; import { UserService } from 'jslib/abstractions/user.service'; import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service'; +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + import { LockComponent as BaseLockComponent } from 'jslib/angular/components/lock.component'; +const BroadcasterSubscriptionId = 'LockComponent'; + @Component({ selector: 'app-lock', templateUrl: 'lock.component.html', @@ -27,7 +34,8 @@ export class LockComponent extends BaseLockComponent { userService: UserService, cryptoService: CryptoService, storageService: StorageService, vaultTimeoutService: VaultTimeoutService, environmentService: EnvironmentService, stateService: StateService, - apiService: ApiService, private route: ActivatedRoute) { + apiService: ApiService, private route: ActivatedRoute, + private broadcasterService: BroadcasterService, private ngZone: NgZone) { super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService, storageService, vaultTimeoutService, environmentService, stateService, apiService); } @@ -39,5 +47,20 @@ export class LockComponent extends BaseLockComponent { setTimeout(() => this.unlockBiometric(), 1000); } }); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case 'windowHidden': + this.onWindowHidden(); + break; + + default: + } + }); + }); + } + + onWindowHidden() { + this.showPassword = false; } } diff --git a/src/app/accounts/login.component.ts b/src/app/accounts/login.component.ts index 1b06d85b5b..4affb59122 100644 --- a/src/app/accounts/login.component.ts +++ b/src/app/accounts/login.component.ts @@ -1,6 +1,7 @@ import { Component, ComponentFactoryResolver, + NgZone, ViewChild, ViewContainerRef, } from '@angular/core'; @@ -19,9 +20,13 @@ import { StateService } from 'jslib/abstractions/state.service'; import { StorageService } from 'jslib/abstractions/storage.service'; import { SyncService } from 'jslib/abstractions/sync.service'; +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/login.component'; import { ModalComponent } from 'jslib/angular/components/modal.component'; +const BroadcasterSubscriptionId = 'LoginComponent'; + @Component({ selector: 'app-login', templateUrl: 'login.component.html', @@ -35,7 +40,8 @@ export class LoginComponent extends BaseLoginComponent { syncService: SyncService, private componentFactoryResolver: ComponentFactoryResolver, platformUtilsService: PlatformUtilsService, stateService: StateService, environmentService: EnvironmentService, passwordGenerationService: PasswordGenerationService, - cryptoFunctionService: CryptoFunctionService, storageService: StorageService) { + cryptoFunctionService: CryptoFunctionService, storageService: StorageService, + private broadcasterService: BroadcasterService, private ngZone: NgZone) { super(authService, router, platformUtilsService, i18nService, stateService, environmentService, passwordGenerationService, cryptoFunctionService, storageService); super.onSuccessfulLogin = () => { @@ -43,6 +49,21 @@ export class LoginComponent extends BaseLoginComponent { }; } + async ngOnInit() { + await super.ngOnInit(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case 'windowHidden': + this.onWindowHidden(); + break; + + default: + } + }); + }); + } + settings() { const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); const modal = this.environmentModal.createComponent(factory).instance; @@ -61,4 +82,8 @@ export class LoginComponent extends BaseLoginComponent { modal.close(); }); } + + onWindowHidden() { + this.showPassword = false; + } } diff --git a/src/app/accounts/register.component.ts b/src/app/accounts/register.component.ts index 19fa0c1962..ce43790b3b 100644 --- a/src/app/accounts/register.component.ts +++ b/src/app/accounts/register.component.ts @@ -1,4 +1,8 @@ -import { Component } from '@angular/core'; +import { + Component, + OnInit, + NgZone, +} from '@angular/core'; import { Router } from '@angular/router'; import { ApiService } from 'jslib/abstractions/api.service'; @@ -9,18 +13,41 @@ import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { StateService } from 'jslib/abstractions/state.service'; +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + import { RegisterComponent as BaseRegisterComponent } from 'jslib/angular/components/register.component'; +const BroadcasterSubscriptionId = 'RegisterComponent'; + @Component({ selector: 'app-register', templateUrl: 'register.component.html', }) -export class RegisterComponent extends BaseRegisterComponent { +export class RegisterComponent extends BaseRegisterComponent implements OnInit { constructor(authService: AuthService, router: Router, i18nService: I18nService, cryptoService: CryptoService, apiService: ApiService, stateService: StateService, - platformUtilsService: PlatformUtilsService, passwordGenerationService: PasswordGenerationService) { + platformUtilsService: PlatformUtilsService, passwordGenerationService: PasswordGenerationService, + private broadcasterService: BroadcasterService, private ngZone: NgZone) { super(authService, router, i18nService, cryptoService, apiService, stateService, platformUtilsService, passwordGenerationService); } + + async ngOnInit() { + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case 'windowHidden': + this.onWindowHidden(); + break; + + default: + } + }); + }); + } + + onWindowHidden() { + this.showPassword = false; + } } diff --git a/src/app/accounts/set-password.component.ts b/src/app/accounts/set-password.component.ts index 295ded430f..b0b0827ca2 100644 --- a/src/app/accounts/set-password.component.ts +++ b/src/app/accounts/set-password.component.ts @@ -1,4 +1,7 @@ -import { Component } from '@angular/core'; +import { + Component, + NgZone, +} from '@angular/core'; import { ActivatedRoute, @@ -15,6 +18,10 @@ import { PolicyService } from 'jslib/abstractions/policy.service'; import { SyncService } from 'jslib/abstractions/sync.service'; import { UserService } from 'jslib/abstractions/user.service'; +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + +const BroadcasterSubscriptionId = 'SetPasswordComponent'; + import { SetPasswordComponent as BaseSetPasswordComponent, } from 'jslib/angular/components/set-password.component'; @@ -28,7 +35,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent { cryptoService: CryptoService, messagingService: MessagingService, userService: UserService, passwordGenerationService: PasswordGenerationService, platformUtilsService: PlatformUtilsService, policyService: PolicyService, router: Router, - syncService: SyncService, route: ActivatedRoute) { + syncService: SyncService, route: ActivatedRoute, + private broadcasterService: BroadcasterService, private ngZone: NgZone) { super(i18nService, cryptoService, messagingService, userService, passwordGenerationService, platformUtilsService, policyService, router, apiService, syncService, route); } @@ -62,4 +70,23 @@ export class SetPasswordComponent extends BaseSetPasswordComponent { return this.masterPasswordScore != null ? this.i18nService.t('weak') : null; } } + + async ngOnInit() { + await super.ngOnInit(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case 'windowHidden': + this.onWindowHidden(); + break; + + default: + } + }); + }); + } + + onWindowHidden() { + this.showPassword = false; + } } diff --git a/src/app/vault/add-edit.component.ts b/src/app/vault/add-edit.component.ts index ed0d529d84..699d155e89 100644 --- a/src/app/vault/add-edit.component.ts +++ b/src/app/vault/add-edit.component.ts @@ -1,6 +1,7 @@ import { Component, OnChanges, + NgZone, } from '@angular/core'; import { AuditService } from 'jslib/abstractions/audit.service'; @@ -14,8 +15,12 @@ import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { StateService } from 'jslib/abstractions/state.service'; import { UserService } from 'jslib/abstractions/user.service'; +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + import { AddEditComponent as BaseAddEditComponent } from 'jslib/angular/components/add-edit.component'; +const BroadcasterSubscriptionId = 'AddEditComponent'; + @Component({ selector: 'app-vault-add-edit', templateUrl: 'add-edit.component.html', @@ -25,13 +30,25 @@ export class AddEditComponent extends BaseAddEditComponent implements OnChanges i18nService: I18nService, platformUtilsService: PlatformUtilsService, auditService: AuditService, stateService: StateService, userService: UserService, collectionService: CollectionService, - messagingService: MessagingService, eventService: EventService) { + messagingService: MessagingService, eventService: EventService, + private broadcasterService: BroadcasterService, private ngZone: NgZone) { super(cipherService, folderService, i18nService, platformUtilsService, auditService, stateService, userService, collectionService, messagingService, eventService); } async ngOnInit() { - // We use ngOnChanges instead. + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case 'windowHidden': + this.onWindowHidden(); + break; + + default: + } + }); + }); + // We use ngOnChanges for everything else instead. } async ngOnChanges() { @@ -46,4 +63,14 @@ export class AddEditComponent extends BaseAddEditComponent implements OnChanges } super.load(); } + + onWindowHidden() { + this.showPassword = false; + this.showCardCode = false; + if (this.cipher !== null && this.cipher.hasFields) { + this.cipher.fields.forEach(field => { + field.showValue = false; + }); + } + } } diff --git a/src/app/vault/export.component.ts b/src/app/vault/export.component.ts index eac41c806e..5b43cf7c1c 100644 --- a/src/app/vault/export.component.ts +++ b/src/app/vault/export.component.ts @@ -1,4 +1,8 @@ -import { Component } from '@angular/core'; +import { + Component, + OnInit, + NgZone, +} from '@angular/core'; import { CryptoService } from 'jslib/abstractions/crypto.service'; import { EventService } from 'jslib/abstractions/event.service'; @@ -6,16 +10,39 @@ import { ExportService } from 'jslib/abstractions/export.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; + import { ExportComponent as BaseExportComponent } from 'jslib/angular/components/export.component'; +const BroadcasterSubscriptionId = 'ExportComponent'; + @Component({ selector: 'app-export', templateUrl: 'export.component.html', }) -export class ExportComponent extends BaseExportComponent { +export class ExportComponent extends BaseExportComponent implements OnInit { constructor(cryptoService: CryptoService, i18nService: I18nService, platformUtilsService: PlatformUtilsService, exportService: ExportService, - eventService: EventService) { + eventService: EventService, private broadcasterService: BroadcasterService, + private ngZone: NgZone) { super(cryptoService, i18nService, platformUtilsService, exportService, eventService, window); } + + async ngOnInit() { + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case 'windowHidden': + this.onWindowHidden(); + break; + + default: + } + }); + }); + } + + onWindowHidden() { + this.showPassword = false; + } } diff --git a/src/app/vault/view.component.ts b/src/app/vault/view.component.ts index 60c4c0dba9..73e260110c 100644 --- a/src/app/vault/view.component.ts +++ b/src/app/vault/view.component.ts @@ -25,6 +25,8 @@ import { ViewComponent as BaseViewComponent } from 'jslib/angular/components/vie import { CipherView } from 'jslib/models/view/cipherView'; +const BroadcasterSubscriptionId = 'ViewComponent'; + @Component({ selector: 'app-vault-view', templateUrl: 'view.component.html', @@ -42,6 +44,20 @@ export class ViewComponent extends BaseViewComponent implements OnChanges { super(cipherService, totpService, tokenService, i18nService, cryptoService, platformUtilsService, auditService, window, broadcasterService, ngZone, changeDetectorRef, userService, eventService); } + ngOnInit() { + super.ngOnInit(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case 'windowHidden': + this.onWindowHidden(); + break; + + default: + } + }); + }); + } async ngOnChanges() { await super.load(); @@ -56,4 +72,14 @@ export class ViewComponent extends BaseViewComponent implements OnChanges { super.copy(value, typeI18nKey, aType); this.messagingService.send('minimizeOnCopy'); } + + onWindowHidden() { + this.showPassword = false; + this.showCardCode = false; + if (this.cipher !== null && this.cipher.hasFields) { + this.cipher.fields.forEach(field => { + field.showValue = false; + }); + } + } } diff --git a/src/main.ts b/src/main.ts index e582c4cffc..2388577fc8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -149,6 +149,14 @@ export class Main { event.preventDefault(); this.processDeepLink([url]); }); + + // Handle window visibility events + this.windowMain.win.on('hide', () => { + this.messagingService.send('windowHidden'); + }); + this.windowMain.win.on('minimize', () => { + this.messagingService.send('windowHidden'); + }); }, (e: any) => { // tslint:disable-next-line console.error(e);