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"
},