diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 027b6618..b0672fdc 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -2,11 +2,9 @@ import {
BodyOutputType,
Toast,
ToasterConfig,
- ToasterContainerComponent,
ToasterService,
} from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
-import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
import {
Component,
@@ -16,7 +14,6 @@ import {
SecurityContext,
Type,
ViewChild,
- ViewContainerRef,
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Router } from '@angular/router';
@@ -52,10 +49,16 @@ import { UserService } from 'jslib/abstractions/user.service';
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
import { ConstantsService } from 'jslib/services/constants.service';
-import { NativeMessagingService } from '../services/nativeMessaging.service';
+
+import { CipherType } from 'jslib/enums/cipherType';
+
+import { ExportComponent } from './vault/export.component';
+import { FolderAddEditComponent } from './vault/folder-add-edit.component';
+import { PasswordGeneratorComponent } from './vault/password-generator.component';
const BroadcasterSubscriptionId = 'AppComponent';
const IdleTimeout = 60000 * 10; // 10 minutes
+const SyncInterval = 6 * 60 * 60 * 1000; // 6 hours
@Component({
selector: 'app-root',
@@ -65,12 +68,18 @@ const IdleTimeout = 60000 * 10; // 10 minutes
+
+
+
`,
})
export class AppComponent implements OnInit {
@ViewChild('settings', { read: ViewContainerRef, static: true }) settingsRef: ViewContainerRef;
@ViewChild('premium', { read: ViewContainerRef, static: true }) premiumRef: ViewContainerRef;
@ViewChild('passwordHistory', { read: ViewContainerRef, static: true }) passwordHistoryRef: ViewContainerRef;
+ @ViewChild('exportVault', { read: ViewContainerRef, static: true }) exportVaultModalRef: ViewContainerRef;
+ @ViewChild('appFolderAddEdit', { read: ViewContainerRef, static: true }) folderAddEditModalRef: ViewContainerRef;
+ @ViewChild('appPasswordGenerator', { read: ViewContainerRef, static: true }) passwordGeneratorModalRef: ViewContainerRef;
toasterConfig: ToasterConfig = new ToasterConfig({
showCloseButton: true,
@@ -84,8 +93,7 @@ export class AppComponent implements OnInit {
private idleTimer: number = null;
private isIdle = false;
- constructor(private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics,
- private broadcasterService: BroadcasterService, private userService: UserService,
+ constructor(private broadcasterService: BroadcasterService, private userService: UserService,
private tokenService: TokenService, private folderService: FolderService,
private settingsService: SettingsService, private syncService: SyncService,
private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService,
@@ -98,7 +106,7 @@ export class AppComponent implements OnInit {
private searchService: SearchService, private notificationsService: NotificationsService,
private platformUtilsService: PlatformUtilsService, private systemService: SystemService,
private stateService: StateService, private eventService: EventService,
- private policyService: PolicyService, private nativeMessagingService: NativeMessagingService) { }
+ private policyService: PolicyService) { }
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
@@ -173,7 +181,7 @@ export class AppComponent implements OnInit {
this.i18nService.t('fingerprintPhrase'), this.i18nService.t('learnMore'),
this.i18nService.t('close'));
if (result) {
- this.platformUtilsService.launchUri(
+ this.platformUtilsService.launchUri(
'https://help.bitwarden.com/article/fingerprint-phrase/');
}
break;
@@ -205,7 +213,55 @@ export class AppComponent implements OnInit {
this.openModal(PremiumComponent, this.premiumRef);
}
break;
+ case 'syncVault':
+ try {
+ await this.syncService.fullSync(true, true);
+ this.toasterService.popAsync('success', null, this.i18nService.t('syncingComplete'));
+ this.analytics.eventTrack.next({ action: 'Synced Full' });
+ } catch {
+ this.toasterService.popAsync('error', null, this.i18nService.t('syncingFailed'));
+ }
+ break;
+ case 'checkSyncVault':
+ try {
+ const lastSync = await this.syncService.getLastSync();
+ let lastSyncAgo = SyncInterval + 1;
+ if (lastSync != null) {
+ lastSyncAgo = new Date().getTime() - lastSync.getTime();
+ }
+
+ if (lastSyncAgo >= SyncInterval) {
+ await this.syncService.fullSync(false);
+ }
+ } catch { }
+ this.messagingService.send('scheduleNextSync');
+ break;
+ case 'exportVault':
+ await this.openExportVault();
+ break;
+ case 'newLogin':
+ this.routeToVault('add', CipherType.Login);
+ break;
+ case 'newCard':
+ this.routeToVault('add', CipherType.Card);
+ break;
+ case 'newIdentity':
+ this.routeToVault('add', CipherType.Identity);
+ break;
+ case 'newSecureNote':
+ this.routeToVault('add', CipherType.SecureNote);
+ break;
default:
+ break;
+ case 'newFolder':
+ await this.addFolder();
+ break;
+ case 'openPasswordGenerator':
+ // openPasswordGenerator has extended functionality if called in the vault
+ if (!this.router.url.includes('vault')) {
+ await this.openPasswordGenerator();
+ }
+ break;
}
});
});
@@ -215,6 +271,59 @@ export class AppComponent implements OnInit {
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
}
+ async openExportVault() {
+ if (this.modal != null) {
+ this.modal.close();
+ }
+
+ const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
+ this.modal = this.exportVaultModalRef.createComponent(factory).instance;
+ const childComponent = this.modal.show(ExportComponent, this.exportVaultModalRef);
+
+ childComponent.onSaved.subscribe(() => {
+ this.modal.close();
+ });
+
+ this.modal.onClosed.subscribe(() => {
+ this.modal = null;
+ });
+ }
+
+ async addFolder() {
+ if (this.modal != null) {
+ this.modal.close();
+ }
+
+ const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
+ this.modal = this.folderAddEditModalRef.createComponent(factory).instance;
+ const childComponent = this.modal.show(
+ FolderAddEditComponent, this.folderAddEditModalRef, true, comp => comp.folderId = null);
+
+ childComponent.onSavedFolder.subscribe(async () => {
+ this.modal.close();
+ this.syncService.fullSync(false);
+ });
+
+ this.modal.onClosed.subscribe(() => {
+ this.modal = null;
+ });
+ }
+
+ async openPasswordGenerator() {
+ if (this.modal != null) {
+ this.modal.close();
+ }
+
+ const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
+ this.modal = this.passwordGeneratorModalRef.createComponent(factory).instance;
+ this.modal.show(PasswordGeneratorComponent,
+ this.passwordGeneratorModalRef, true, comp => comp.showSelect = false);
+
+ this.modal.onClosed.subscribe(() => {
+ this.modal = null;
+ });
+ }
+
private async updateAppMenu() {
this.messagingService.send('updateAppMenu', {
isAuthenticated: await this.userService.isAuthenticated(),
@@ -328,4 +437,16 @@ export class AppComponent implements OnInit {
}
this.toasterService.popAsync(toast);
}
+
+ private routeToVault(action: string, cipherType: CipherType) {
+ if (!this.router.url.includes('vault')) {
+ this.router.navigate(['/vault'], {
+ queryParams: {
+ action: action,
+ addType: cipherType,
+ },
+ replaceUrl: true,
+ });
+ }
+ }
}
diff --git a/src/app/vault/vault.component.html b/src/app/vault/vault.component.html
index e6740c1d..9c7cef1e 100644
--- a/src/app/vault/vault.component.html
+++ b/src/app/vault/vault.component.html
@@ -38,4 +38,3 @@
-
diff --git a/src/app/vault/vault.component.ts b/src/app/vault/vault.component.ts
index 34e543f4..4f8980f3 100644
--- a/src/app/vault/vault.component.ts
+++ b/src/app/vault/vault.component.ts
@@ -49,7 +49,6 @@ import { SyncService } from 'jslib/abstractions/sync.service';
import { TotpService } from 'jslib/abstractions/totp.service';
import { UserService } from 'jslib/abstractions/user.service';
-const SyncInterval = 6 * 60 * 60 * 1000; // 6 hours
const BroadcasterSubscriptionId = 'VaultComponent';
@Component({
@@ -63,11 +62,10 @@ export class VaultComponent implements OnInit, OnDestroy {
@ViewChild(GroupingsComponent, { static: true }) groupingsComponent: GroupingsComponent;
@ViewChild('passwordGenerator', { read: ViewContainerRef, static: true }) passwordGeneratorModalRef: ViewContainerRef;
@ViewChild('attachments', { read: ViewContainerRef, static: true }) attachmentsModalRef: ViewContainerRef;
- @ViewChild('folderAddEdit', { read: ViewContainerRef, static: true }) folderAddEditModalRef: ViewContainerRef;
@ViewChild('passwordHistory', { read: ViewContainerRef, static: true }) passwordHistoryModalRef: ViewContainerRef;
- @ViewChild('exportVault', { read: ViewContainerRef, static: true }) exportVaultModalRef: ViewContainerRef;
@ViewChild('share', { read: ViewContainerRef, static: true }) shareModalRef: ViewContainerRef;
@ViewChild('collections', { read: ViewContainerRef, static: true }) collectionsModalRef: ViewContainerRef;
+ @ViewChild('folderAddEdit', { read: ViewContainerRef, static: true }) folderAddEditModalRef: ViewContainerRef;
action: string;
cipherId: string = null;
@@ -111,9 +109,6 @@ export class VaultComponent implements OnInit, OnDestroy {
case 'newSecureNote':
await this.addCipher(CipherType.SecureNote);
break;
- case 'newFolder':
- await this.addFolder();
- break;
case 'focusSearch':
(document.querySelector('#search') as HTMLInputElement).select();
detectChanges = false;
@@ -121,33 +116,6 @@ export class VaultComponent implements OnInit, OnDestroy {
case 'openPasswordGenerator':
await this.openPasswordGenerator(false);
break;
- case 'exportVault':
- await this.openExportVault();
- break;
- case 'syncVault':
- try {
- await this.syncService.fullSync(true, true);
- this.toasterService.popAsync('success', null, this.i18nService.t('syncingComplete'));
- this.analytics.eventTrack.next({ action: 'Synced Full' });
- } catch {
- this.toasterService.popAsync('error', null, this.i18nService.t('syncingFailed'));
- }
- break;
- case 'checkSyncVault':
- try {
- const lastSync = await this.syncService.getLastSync();
- let lastSyncAgo = SyncInterval + 1;
- if (lastSync != null) {
- lastSyncAgo = new Date().getTime() - lastSync.getTime();
- }
-
- if (lastSyncAgo >= SyncInterval) {
- await this.syncService.fullSync(false);
- }
- } catch { }
-
- this.messagingService.send('scheduleNextSync');
- break;
case 'syncCompleted':
await this.load();
break;
@@ -230,7 +198,28 @@ export class VaultComponent implements OnInit, OnDestroy {
await this.viewCipher(cipherView);
}
} else if (params.action === 'add') {
- await this.addCipher();
+ switch (params.addType) {
+ case 'Login':
+ case '1':
+ this.addType = CipherType.Login;
+ break;
+ case 'SecureNote':
+ case '2':
+ this.addType = CipherType.SecureNote;
+ break;
+ case 'Card':
+ case '3':
+ this.addType = CipherType.Card;
+ break;
+ case 'Identity':
+ case '4':
+ this.addType = CipherType.Identity;
+ break;
+ default:
+ this.addType = CipherType.Login;
+ break;
+ }
+ this.addCipher(this.addType);
}
if (params.deleted) {
@@ -239,7 +228,7 @@ export class VaultComponent implements OnInit, OnDestroy {
} else if (params.favorites) {
this.groupingsComponent.selectedFavorites = true;
await this.filterFavorites();
- } else if (params.type) {
+ } else if (params.type && params.action !== 'add') {
const t = parseInt(params.type, null);
this.groupingsComponent.selectedType = t;
await this.filterCipherType(t);
@@ -593,42 +582,8 @@ export class VaultComponent implements OnInit, OnDestroy {
});
}
- async openExportVault() {
- if (this.modal != null) {
- this.modal.close();
- }
-
- const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
- this.modal = this.exportVaultModalRef.createComponent(factory).instance;
- const childComponent = this.modal.show(ExportComponent, this.exportVaultModalRef);
-
- childComponent.onSaved.subscribe(() => {
- this.modal.close();
- });
-
- this.modal.onClosed.subscribe(() => {
- this.modal = null;
- });
- }
-
async addFolder() {
- if (this.modal != null) {
- this.modal.close();
- }
-
- const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
- this.modal = this.folderAddEditModalRef.createComponent(factory).instance;
- const childComponent = this.modal.show(
- FolderAddEditComponent, this.folderAddEditModalRef, true, comp => comp.folderId = null);
-
- childComponent.onSavedFolder.subscribe(async (folder: FolderView) => {
- this.modal.close();
- await this.groupingsComponent.loadFolders();
- });
-
- this.modal.onClosed.subscribe(() => {
- this.modal = null;
- });
+ this.messagingService.send('newFolder');
}
async editFolder(folderId: string) {