diff --git a/jslib b/jslib index aed1c5e9..9bd8b73e 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit aed1c5e92762f1d2fa037aa9eb4d2b8e82f45707 +Subproject commit 9bd8b73e27429b70a11e0016f794d1a976076c9f diff --git a/package-lock.json b/package-lock.json index 48111035..e911ed47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,6 +102,11 @@ "tslib": "^1.7.1" } }, + "@aspnet/signalr": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@aspnet/signalr/-/signalr-1.0.2.tgz", + "integrity": "sha512-sXleqUCCbodCOqUA8MjLSvtAgDTvDhEq6j3JyAq/w4RMJhpZ+dXK9+6xEMbzag2hisq5e/8vDC82JYutkcOISQ==" + }, "@ngtools/webpack": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.10.2.tgz", diff --git a/package.json b/package.json index 7ee00f53..3eda35bc 100644 --- a/package.json +++ b/package.json @@ -238,6 +238,7 @@ "@angular/platform-browser-dynamic": "5.2.0", "@angular/router": "5.2.0", "@angular/upgrade": "5.2.0", + "@aspnet/signalr": "1.0.2", "angular2-toaster": "4.0.2", "angulartics2": "5.0.1", "core-js": "2.4.1", diff --git a/src/app/accounts/environment.component.html b/src/app/accounts/environment.component.html index 772c2941..b653e1e0 100644 --- a/src/app/accounts/environment.component.html +++ b/src/app/accounts/environment.component.html @@ -38,6 +38,11 @@ +
+ + +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 57f3bd7d..9fb1915e 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -31,6 +31,7 @@ import { FolderService } from 'jslib/abstractions/folder.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { LockService } from 'jslib/abstractions/lock.service'; import { MessagingService } from 'jslib/abstractions/messaging.service'; +import { NotificationsService } from 'jslib/abstractions/notifications.service'; import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { SearchService } from 'jslib/abstractions/search.service'; @@ -80,7 +81,7 @@ export class AppComponent implements OnInit { private lockService: LockService, private storageService: StorageService, private cryptoService: CryptoService, private componentFactoryResolver: ComponentFactoryResolver, private messagingService: MessagingService, private collectionService: CollectionService, - private searchService: SearchService) { + private searchService: SearchService, private notificationsService: NotificationsService) { (window as any).BitwardenToasterService = toasterService; } @@ -102,8 +103,11 @@ export class AppComponent implements OnInit { this.ngZone.run(async () => { switch (message.command) { case 'loggedIn': - case 'unlocked': case 'loggedOut': + this.notificationsService.updateConnection(); + this.updateAppMenu(); + break; + case 'unlocked': this.updateAppMenu(); break; case 'logout': diff --git a/src/app/services.module.ts b/src/app/services.module.ts index 38608a90..4468414f 100644 --- a/src/app/services.module.ts +++ b/src/app/services.module.ts @@ -36,6 +36,7 @@ import { ExportService } from 'jslib/services/export.service'; import { FolderService } from 'jslib/services/folder.service'; import { LockService } from 'jslib/services/lock.service'; import { LowdbStorageService } from 'jslib/services/lowdbStorage.service'; +import { NotificationsService } from 'jslib/services/notifications.service'; import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service'; import { SearchService } from 'jslib/services/search.service'; import { SettingsService } from 'jslib/services/settings.service'; @@ -61,6 +62,7 @@ import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.s import { LockService as LockServiceAbstraction } from 'jslib/abstractions/lock.service'; import { LogService as LogServiceAbstraction } from 'jslib/abstractions/log.service'; import { MessagingService as MessagingServiceAbstraction } from 'jslib/abstractions/messaging.service'; +import { NotificationsService as NotificationsServiceAbstraction } from 'jslib/abstractions/notifications.service'; import { PasswordGenerationService as PasswordGenerationServiceAbstraction, } from 'jslib/abstractions/passwordGeneration.service'; @@ -111,19 +113,20 @@ const authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService, i18nService, platformUtilsService, messagingService); const exportService = new ExportService(folderService, cipherService, apiService); const auditService = new AuditService(cryptoFunctionService, apiService); +const notificationsService = new NotificationsService(userService, tokenService, syncService, appIdService); const analytics = new Analytics(window, () => isDev(), platformUtilsService, storageService, appIdService); containerService.attachToWindow(window); -environmentService.setUrlsFromStorage().then(() => { - return syncService.fullSync(true); -}); export function initFactory(): Function { return async () => { + await environmentService.setUrlsFromStorage(); + syncService.fullSync(true); lockService.init(true); const locale = await storageService.get(ConstantsService.localeKey); await i18nService.init(locale); await authService.init(); + setTimeout(() => notificationsService.init(environmentService), 3000); const htmlEl = window.document.documentElement; htmlEl.classList.add('os_' + platformUtilsService.getDeviceString()); htmlEl.classList.add('locale_' + i18nService.translationLocale); @@ -186,6 +189,7 @@ export function initFactory(): Function { { provide: LogServiceAbstraction, useValue: logService }, { provide: ExportServiceAbstraction, useValue: exportService }, { provide: SearchServiceAbstraction, useValue: searchService }, + { provide: NotificationsServiceAbstraction, useValue: notificationsService }, { provide: APP_INITIALIZER, useFactory: initFactory, diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index 3addc13b..7278c440 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -593,6 +593,9 @@ "identityUrl": { "message": "Identity Server URL" }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, "iconsUrl": { "message": "Icons Server URL" },