mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-17 15:37:57 +01:00
menu with messages back to app
This commit is contained in:
parent
5e8ccd19c5
commit
c76b4821c6
@ -6,6 +6,7 @@ import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
NgZone,
|
||||||
OnInit,
|
OnInit,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
@ -21,6 +22,7 @@ import { CryptoService } from 'jslib/abstractions/crypto.service';
|
|||||||
import { FolderService } from 'jslib/abstractions/folder.service';
|
import { FolderService } from 'jslib/abstractions/folder.service';
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||||
|
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
import { SettingsService } from 'jslib/abstractions/settings.service';
|
import { SettingsService } from 'jslib/abstractions/settings.service';
|
||||||
import { SyncService } from 'jslib/abstractions/sync.service';
|
import { SyncService } from 'jslib/abstractions/sync.service';
|
||||||
import { TokenService } from 'jslib/abstractions/token.service';
|
import { TokenService } from 'jslib/abstractions/token.service';
|
||||||
@ -47,14 +49,44 @@ export class AppComponent implements OnInit {
|
|||||||
private settingsService: SettingsService, private syncService: SyncService,
|
private settingsService: SettingsService, private syncService: SyncService,
|
||||||
private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService,
|
private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService,
|
||||||
private authService: AuthService, private router: Router, private analytics: Angulartics2,
|
private authService: AuthService, private router: Router, private analytics: Angulartics2,
|
||||||
private toasterService: ToasterService, private i18nService: I18nService) { }
|
private toasterService: ToasterService, private i18nService: I18nService,
|
||||||
|
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.broadcasterService.subscribe(async (message: any) => {
|
this.broadcasterService.subscribe((message: any) => {
|
||||||
|
this.ngZone.run(async () => {
|
||||||
switch (message.command) {
|
switch (message.command) {
|
||||||
case 'loggedIn':
|
case 'loggedIn':
|
||||||
break;
|
break;
|
||||||
case 'logout':
|
case 'logout':
|
||||||
|
this.logOut(message.expired);
|
||||||
|
break;
|
||||||
|
case 'doneLoggingOut':
|
||||||
|
this.doneLoggingOut(message.expired);
|
||||||
|
break;
|
||||||
|
case 'locked':
|
||||||
|
break;
|
||||||
|
case 'unlocked':
|
||||||
|
break;
|
||||||
|
case 'syncStarted':
|
||||||
|
break;
|
||||||
|
case 'syncCompleted':
|
||||||
|
break;
|
||||||
|
case 'confirmLogout':
|
||||||
|
const logoutConfirmed = await this.platformUtilsService.showDialog(
|
||||||
|
this.i18nService.t('logOutConfirmation'), this.i18nService.t('logOut'),
|
||||||
|
this.i18nService.t('logOut'), this.i18nService.t('cancel'));
|
||||||
|
if (logoutConfirmed) {
|
||||||
|
this.logOut(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async logOut(expired: boolean) {
|
||||||
const userId = await this.userService.getUserId();
|
const userId = await this.userService.getUserId();
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@ -68,22 +100,7 @@ export class AppComponent implements OnInit {
|
|||||||
this.passwordGenerationService.clear(),
|
this.passwordGenerationService.clear(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.doneLoggingOut(message.expired);
|
this.doneLoggingOut(expired);
|
||||||
break;
|
|
||||||
case 'doneLoggingOut':
|
|
||||||
this.doneLoggingOut(message.expired);
|
|
||||||
break;
|
|
||||||
case 'locked':
|
|
||||||
break;
|
|
||||||
case 'unlocked':
|
|
||||||
break;
|
|
||||||
case 'syncStarted':
|
|
||||||
break;
|
|
||||||
case 'syncCompleted':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private doneLoggingOut(expired: boolean) {
|
private doneLoggingOut(expired: boolean) {
|
||||||
|
@ -35,6 +35,7 @@ import { SecureNoteView } from 'jslib/models/view/secureNoteView';
|
|||||||
export class AddEditComponent implements OnChanges {
|
export class AddEditComponent implements OnChanges {
|
||||||
@Input() folderId: string;
|
@Input() folderId: string;
|
||||||
@Input() cipherId: string;
|
@Input() cipherId: string;
|
||||||
|
@Input() type: CipherType;
|
||||||
@Output() onSavedCipher = new EventEmitter<CipherView>();
|
@Output() onSavedCipher = new EventEmitter<CipherView>();
|
||||||
@Output() onDeletedCipher = new EventEmitter<CipherView>();
|
@Output() onDeletedCipher = new EventEmitter<CipherView>();
|
||||||
@Output() onCancelled = new EventEmitter<CipherView>();
|
@Output() onCancelled = new EventEmitter<CipherView>();
|
||||||
@ -119,7 +120,7 @@ export class AddEditComponent implements OnChanges {
|
|||||||
this.title = this.i18nService.t('addItem');
|
this.title = this.i18nService.t('addItem');
|
||||||
this.cipher = new CipherView();
|
this.cipher = new CipherView();
|
||||||
this.cipher.folderId = this.folderId;
|
this.cipher.folderId = this.folderId;
|
||||||
this.cipher.type = CipherType.Login;
|
this.cipher.type = this.type == null ? CipherType.Login : this.type;
|
||||||
this.cipher.login = new LoginView();
|
this.cipher.login = new LoginView();
|
||||||
this.cipher.card = new CardView();
|
this.cipher.card = new CardView();
|
||||||
this.cipher.identity = new IdentityView();
|
this.cipher.identity = new IdentityView();
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
<app-vault-add-edit id="details"
|
<app-vault-add-edit id="details"
|
||||||
*ngIf="action === 'add' || action === 'edit'"
|
*ngIf="action === 'add' || action === 'edit'"
|
||||||
[folderId]="action === 'add' && folderId !== 'none' ? folderId : null"
|
[folderId]="action === 'add' && folderId !== 'none' ? folderId : null"
|
||||||
|
[type]="action === 'add' ? addType : null"
|
||||||
[cipherId]="action === 'edit' ? cipherId : null"
|
[cipherId]="action === 'edit' ? cipherId : null"
|
||||||
(onSavedCipher)="savedCipher($event)"
|
(onSavedCipher)="savedCipher($event)"
|
||||||
(onDeletedCipher)="deletedCipher($event)"
|
(onDeletedCipher)="deletedCipher($event)"
|
||||||
|
@ -2,8 +2,10 @@ import * as template from './vault.component.html';
|
|||||||
|
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import {
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
Component,
|
Component,
|
||||||
ComponentFactoryResolver,
|
ComponentFactoryResolver,
|
||||||
|
NgZone,
|
||||||
OnInit,
|
OnInit,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
@ -15,6 +17,8 @@ import {
|
|||||||
|
|
||||||
import { ModalComponent } from '../modal.component';
|
import { ModalComponent } from '../modal.component';
|
||||||
|
|
||||||
|
import { BroadcasterService } from '../services/broadcaster.service';
|
||||||
|
|
||||||
import { AddEditComponent } from './add-edit.component';
|
import { AddEditComponent } from './add-edit.component';
|
||||||
import { AttachmentsComponent } from './attachments.component';
|
import { AttachmentsComponent } from './attachments.component';
|
||||||
import { CiphersComponent } from './ciphers.component';
|
import { CiphersComponent } from './ciphers.component';
|
||||||
@ -48,12 +52,46 @@ export class VaultComponent implements OnInit {
|
|||||||
type: CipherType = null;
|
type: CipherType = null;
|
||||||
folderId: string = null;
|
folderId: string = null;
|
||||||
collectionId: string = null;
|
collectionId: string = null;
|
||||||
|
addType: CipherType = null;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private router: Router, private location: Location,
|
constructor(private route: ActivatedRoute, private router: Router, private location: Location,
|
||||||
private componentFactoryResolver: ComponentFactoryResolver, private i18nService: I18nService) {
|
private componentFactoryResolver: ComponentFactoryResolver, private i18nService: I18nService,
|
||||||
|
private broadcasterService: BroadcasterService, private changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private ngZone: NgZone) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
this.broadcasterService.subscribe((message: any) => {
|
||||||
|
this.ngZone.run(async () => {
|
||||||
|
let detectChanges = true;
|
||||||
|
|
||||||
|
switch (message.command) {
|
||||||
|
case 'newLogin':
|
||||||
|
this.addCipher(CipherType.Login);
|
||||||
|
break;
|
||||||
|
case 'newCard':
|
||||||
|
this.addCipher(CipherType.Card);
|
||||||
|
break;
|
||||||
|
case 'newIdentity':
|
||||||
|
this.addCipher(CipherType.Identity);
|
||||||
|
break;
|
||||||
|
case 'newSecureNote':
|
||||||
|
this.addCipher(CipherType.SecureNote);
|
||||||
|
break;
|
||||||
|
case 'newFolder':
|
||||||
|
await this.addFolder();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
detectChanges = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detectChanges) {
|
||||||
|
this.changeDetectorRef.detectChanges();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.route.queryParams.subscribe(async (params) => {
|
this.route.queryParams.subscribe(async (params) => {
|
||||||
if (params.cipherId) {
|
if (params.cipherId) {
|
||||||
const cipherView = new CipherView();
|
const cipherView = new CipherView();
|
||||||
@ -108,11 +146,12 @@ export class VaultComponent implements OnInit {
|
|||||||
this.go();
|
this.go();
|
||||||
}
|
}
|
||||||
|
|
||||||
addCipher() {
|
addCipher(type: CipherType = null) {
|
||||||
if (this.action === 'add') {
|
if (this.action === 'add') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.addType = type;
|
||||||
this.action = 'add';
|
this.action = 'add';
|
||||||
this.cipherId = null;
|
this.cipherId = null;
|
||||||
this.go();
|
this.go();
|
||||||
|
@ -600,5 +600,11 @@
|
|||||||
},
|
},
|
||||||
"loginExpired": {
|
"loginExpired": {
|
||||||
"message": "Your login session has expired."
|
"message": "Your login session has expired."
|
||||||
|
},
|
||||||
|
"logOutConfirmation": {
|
||||||
|
"message": "Are you sure you want to log out?"
|
||||||
|
},
|
||||||
|
"logOut": {
|
||||||
|
"message": "Log Out"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,9 @@ if (watch) {
|
|||||||
const i18nService = new I18nService('en', './locales/');
|
const i18nService = new I18nService('en', './locales/');
|
||||||
i18nService.init().then(() => { });
|
i18nService.init().then(() => { });
|
||||||
|
|
||||||
let win: BrowserWindow;
|
const windowMain = new WindowMain(dev);
|
||||||
const messagingMain = new MessagingMain();
|
const messagingMain = new MessagingMain();
|
||||||
const menuMain = new MenuMain();
|
const menuMain = new MenuMain(windowMain);
|
||||||
const windowMain = new WindowMain(win, dev);
|
|
||||||
|
|
||||||
messagingMain.init();
|
messagingMain.init();
|
||||||
menuMain.init();
|
menuMain.init();
|
||||||
|
@ -1,10 +1,69 @@
|
|||||||
import { app, Menu, MenuItemConstructorOptions } from 'electron';
|
import {
|
||||||
|
app,
|
||||||
|
BrowserWindow,
|
||||||
|
Menu,
|
||||||
|
MenuItemConstructorOptions,
|
||||||
|
ipcMain,
|
||||||
|
} from 'electron';
|
||||||
|
|
||||||
|
import { WindowMain } from './window.main';
|
||||||
|
|
||||||
export class MenuMain {
|
export class MenuMain {
|
||||||
constructor() { }
|
constructor(private windowMain: WindowMain) { }
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
const template: MenuItemConstructorOptions[] = [
|
const template: MenuItemConstructorOptions[] = [
|
||||||
|
{
|
||||||
|
label: 'bitwarden'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'File',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: 'New Item',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: 'New Login',
|
||||||
|
click() {
|
||||||
|
self.send('newLogin');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'New Card',
|
||||||
|
click() {
|
||||||
|
self.send('newCard');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'New Identity',
|
||||||
|
click() {
|
||||||
|
self.send('newIdentity');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'New Secure Note',
|
||||||
|
click() {
|
||||||
|
self.send('newSecureNote');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'New Login',
|
||||||
|
click() {
|
||||||
|
self.send('newLogin');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'New Folder',
|
||||||
|
click() {
|
||||||
|
self.send('newFolder');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
submenu: [
|
submenu: [
|
||||||
@ -33,6 +92,17 @@ export class MenuMain {
|
|||||||
{ role: 'togglefullscreen' }
|
{ role: 'togglefullscreen' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Account',
|
||||||
|
submenu: [
|
||||||
|
{
|
||||||
|
label: 'Log Out',
|
||||||
|
click() {
|
||||||
|
self.send('confirmLogout');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
role: 'window',
|
role: 'window',
|
||||||
submenu: [
|
submenu: [
|
||||||
@ -52,9 +122,20 @@ export class MenuMain {
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
template.unshift({
|
template[0].submenu = [
|
||||||
label: app.getName(),
|
{
|
||||||
submenu: [
|
label: 'Settings',
|
||||||
|
click() {
|
||||||
|
self.send('openSettings');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Lock',
|
||||||
|
click() {
|
||||||
|
self.send('lockApp');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
{ role: 'about' },
|
{ role: 'about' },
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{ role: 'services', submenu: [] },
|
{ role: 'services', submenu: [] },
|
||||||
@ -64,20 +145,41 @@ export class MenuMain {
|
|||||||
{ role: 'unhide' },
|
{ role: 'unhide' },
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{ role: 'quit' }
|
{ role: 'quit' }
|
||||||
]
|
];
|
||||||
})
|
|
||||||
|
|
||||||
// Window menu
|
// Window menu
|
||||||
template[3].submenu = [
|
template[4].submenu = [
|
||||||
{ role: 'close' },
|
{ role: 'close' },
|
||||||
{ role: 'minimize' },
|
{ role: 'minimize' },
|
||||||
{ role: 'zoom' },
|
{ role: 'zoom' },
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{ role: 'front' }
|
{ role: 'front' }
|
||||||
]
|
]
|
||||||
};
|
} else {
|
||||||
|
template[0].submenu = [
|
||||||
|
{
|
||||||
|
label: 'Settings',
|
||||||
|
click() {
|
||||||
|
self.send('openSettings');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Lock',
|
||||||
|
click() {
|
||||||
|
self.send('lockApp');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
const menu = Menu.buildFromTemplate(template);
|
const menu = Menu.buildFromTemplate(template);
|
||||||
Menu.setApplicationMenu(menu);
|
Menu.setApplicationMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
send(command: string, message?: any) {
|
||||||
|
this.windowMain.win.webContents.send('messagingService', {
|
||||||
|
command: command,
|
||||||
|
message: message,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ export class MessagingMain {
|
|||||||
case 'logout':
|
case 'logout':
|
||||||
break;
|
break;
|
||||||
case 'syncCompleted':
|
case 'syncCompleted':
|
||||||
console.log('sync completed!!');
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -3,7 +3,9 @@ import * as path from 'path';
|
|||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
|
|
||||||
export class WindowMain {
|
export class WindowMain {
|
||||||
constructor(private win: BrowserWindow, private dev: boolean) { }
|
win: BrowserWindow;
|
||||||
|
|
||||||
|
constructor(private dev: boolean) { }
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
try {
|
try {
|
||||||
|
@ -5,7 +5,13 @@ import { MessagingService } from 'jslib/abstractions';
|
|||||||
import { BroadcasterService } from '../app/services/broadcaster.service';
|
import { BroadcasterService } from '../app/services/broadcaster.service';
|
||||||
|
|
||||||
export class DesktopMessagingService implements MessagingService {
|
export class DesktopMessagingService implements MessagingService {
|
||||||
constructor(private broadcasterService: BroadcasterService) { }
|
constructor(private broadcasterService: BroadcasterService) {
|
||||||
|
ipcRenderer.on('messagingService', async (event: any, message: any) => {
|
||||||
|
if (message.command) {
|
||||||
|
this.send(message.command, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
send(subscriber: string, arg: any = {}) {
|
send(subscriber: string, arg: any = {}) {
|
||||||
const message = Object.assign({}, { command: subscriber }, arg);
|
const message = Object.assign({}, { command: subscriber }, arg);
|
||||||
|
Loading…
Reference in New Issue
Block a user