1
0
mirror of https://github.com/bitwarden/desktop.git synced 2024-09-27 03:53:00 +02:00

more tray icon options

This commit is contained in:
Kyle Spearrin 2018-05-05 00:29:02 -04:00
parent 4fd597fc05
commit 9d969929de
8 changed files with 127 additions and 37 deletions

2
jslib

@ -1 +1 @@
Subproject commit 61e13daefafe53c4c4b33fa9419052bfc2cfc9cd Subproject commit c6c5dd6d46526a36b65de3f5069e56d131843f7d

View File

@ -32,6 +32,16 @@
</div> </div>
<small class="help-block">{{'disableFaviconDesc' | i18n}}</small> <small class="help-block">{{'disableFaviconDesc' | i18n}}</small>
</div> </div>
<div class="form-group">
<div class="checkbox">
<label for="enableTray">
<input id="enableTray" type="checkbox" name="EnableTray"
[(ngModel)]="enableTray" (change)="saveTray()">
{{'enableTray' | i18n}}
</label>
</div>
<small class="help-block">{{'enableTrayDesc' | i18n}}</small>
</div>
<div class="form-group"> <div class="form-group">
<div class="checkbox"> <div class="checkbox">
<label for="enableMinToTray"> <label for="enableMinToTray">

View File

@ -15,7 +15,7 @@ import { StorageService } from 'jslib/abstractions/storage.service';
import { ConstantsService } from 'jslib/services/constants.service'; import { ConstantsService } from 'jslib/services/constants.service';
import { DesktopConstants } from '../../desktopConstants'; import { ElectronConstants } from 'jslib/electron/electronConstants';
@Component({ @Component({
selector: 'app-settings', selector: 'app-settings',
@ -26,6 +26,7 @@ export class SettingsComponent implements OnInit {
disableGa: boolean = false; disableGa: boolean = false;
disableFavicons: boolean = false; disableFavicons: boolean = false;
enableMinToTray: boolean = false; enableMinToTray: boolean = false;
enableTray: boolean = false;
locale: string; locale: string;
lockOptions: any[]; lockOptions: any[];
localeOptions: any[]; localeOptions: any[];
@ -58,7 +59,8 @@ export class SettingsComponent implements OnInit {
async ngOnInit() { async ngOnInit() {
this.lockOption = await this.storageService.get<number>(ConstantsService.lockOptionKey); this.lockOption = await this.storageService.get<number>(ConstantsService.lockOptionKey);
this.disableFavicons = await this.storageService.get<boolean>(ConstantsService.disableFaviconKey); this.disableFavicons = await this.storageService.get<boolean>(ConstantsService.disableFaviconKey);
this.enableMinToTray = await this.storageService.get<boolean>(DesktopConstants.enableMinimizeToTrayKey); this.enableMinToTray = await this.storageService.get<boolean>(ElectronConstants.enableMinimizeToTrayKey);
this.enableTray = await this.storageService.get<boolean>(ElectronConstants.enableTrayKey);
this.locale = await this.storageService.get<string>(ConstantsService.localeKey); this.locale = await this.storageService.get<string>(ConstantsService.localeKey);
const disableGa = await this.storageService.get<boolean>(ConstantsService.disableGaKey); const disableGa = await this.storageService.get<boolean>(ConstantsService.disableGaKey);
@ -88,10 +90,16 @@ export class SettingsComponent implements OnInit {
} }
async saveMinToTray() { async saveMinToTray() {
await this.storageService.save(DesktopConstants.enableMinimizeToTrayKey, this.enableMinToTray); await this.storageService.save(ElectronConstants.enableMinimizeToTrayKey, this.enableMinToTray);
this.callAnalytics('MinimizeToTray', this.enableMinToTray); this.callAnalytics('MinimizeToTray', this.enableMinToTray);
} }
async saveTray() {
await this.storageService.save(ElectronConstants.enableTrayKey, this.enableTray);
this.callAnalytics('Tray', this.enableTray);
this.messagingService.send(this.enableTray ? 'showTray' : 'removeTray');
}
async saveLocale() { async saveLocale() {
await this.storageService.save(ConstantsService.localeKey, this.locale); await this.storageService.save(ConstantsService.localeKey, this.locale);
this.analytics.eventTrack.next({ action: 'Set Locale ' + this.locale }); this.analytics.eventTrack.next({ action: 'Set Locale ' + this.locale });

View File

@ -1,3 +0,0 @@
export class DesktopConstants {
static readonly enableMinimizeToTrayKey: string = 'enableMinimizeToTray';
}

View File

@ -771,10 +771,16 @@
"message": "Website Icons provide a recognizable image next to each login item in your vault." "message": "Website Icons provide a recognizable image next to each login item in your vault."
}, },
"enableMinToTray": { "enableMinToTray": {
"message": "Minimize to Tray" "message": "Minimize to Tray Icon"
}, },
"enableMinToTrayDesc": { "enableMinToTrayDesc": {
"message": "When minimizing the window, run Bitwarden as a system tray icon." "message": "When minimizing the window, show an icon in the system tray instead."
},
"enableTray": {
"message": "Enable Tray Icon"
},
"enableTrayDesc": {
"message": "Always show an icon in the system tray."
}, },
"language": { "language": {
"message": "Language" "message": "Language"
@ -1037,5 +1043,8 @@
}, },
"default": { "default": {
"message": "Default" "message": "Default"
},
"exit": {
"message": "Exit"
} }
} }

View File

@ -1,4 +1,8 @@
import { app, BrowserWindow } from 'electron'; import {
app,
BrowserWindow,
MenuItemConstructorOptions,
} from 'electron';
import * as path from 'path'; import * as path from 'path';
import { I18nService } from './services/i18n.service'; import { I18nService } from './services/i18n.service';
@ -17,8 +21,6 @@ import { ElectronStorageService } from 'jslib/electron/services/electronStorage.
import { UpdaterMain } from 'jslib/electron/updater.main'; import { UpdaterMain } from 'jslib/electron/updater.main';
import { WindowMain } from 'jslib/electron/window.main'; import { WindowMain } from 'jslib/electron/window.main';
import { DesktopConstants } from './desktopConstants';
export class Main { export class Main {
logService: ElectronLogService; logService: ElectronLogService;
i18nService: I18nService; i18nService: I18nService;
@ -76,9 +78,7 @@ export class Main {
}); });
this.menuMain = new MenuMain(this); this.menuMain = new MenuMain(this);
this.powerMonitorMain = new PowerMonitorMain(this); this.powerMonitorMain = new PowerMonitorMain(this);
this.trayMain = new TrayMain(this.windowMain, 'Bitwarden', async () => { this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.storageService, 'Bitwarden');
return await this.storageService.get<boolean>(DesktopConstants.enableMinimizeToTrayKey);
});
this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => { this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => {
this.messagingMain.onMessage(message); this.messagingMain.onMessage(message);
@ -95,7 +95,12 @@ export class Main {
this.messagingMain.init(); this.messagingMain.init();
this.menuMain.init(); this.menuMain.init();
this.powerMonitorMain.init(); this.powerMonitorMain.init();
this.trayMain.init(); this.trayMain.init([{
label: this.i18nService.t('lockNow'),
enabled: false,
id: 'lockNow',
click: () => this.messagingService.send('lockVault'),
}]);
await this.updaterMain.init(); await this.updaterMain.init();
}, (e: any) => { }, (e: any) => {
// tslint:disable-next-line // tslint:disable-next-line

View File

@ -21,6 +21,16 @@ export class MessagingMain {
break; break;
case 'updateAppMenu': case 'updateAppMenu':
this.main.menuMain.updateApplicationMenuState(message.isAuthenticated, message.isLocked); this.main.menuMain.updateApplicationMenuState(message.isAuthenticated, message.isLocked);
this.updateTrayMenu(message.isAuthenticated, message.isLocked);
break;
case 'showTray':
this.main.trayMain.showTray();
break;
case 'removeTray':
this.main.trayMain.removeTray();
break;
case 'hideToTray':
this.main.trayMain.hideToTray();
break; break;
default: default:
break; break;
@ -42,4 +52,11 @@ export class MessagingMain {
}); });
}, SyncInterval); }, SyncInterval);
} }
private updateTrayMenu(isAuthenticated: boolean, isLocked: boolean) {
const lockNowTrayMenuItem = this.main.trayMain.contextMenu.getMenuItemById('lockNow');
if (lockNowTrayMenuItem != null) {
lockNowTrayMenuItem.enabled = isAuthenticated && !isLocked;
}
}
} }

View File

@ -1,21 +1,26 @@
import { import {
Menu, Menu,
MenuItem,
MenuItemConstructorOptions,
nativeImage, nativeImage,
Tray, Tray,
} from 'electron'; } from 'electron';
import * as path from 'path'; import * as path from 'path';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { ElectronConstants } from 'jslib/electron/electronConstants';
import { WindowMain } from 'jslib/electron/window.main'; import { WindowMain } from 'jslib/electron/window.main';
import { DesktopConstants } from '../desktopConstants';
export class TrayMain { export class TrayMain {
contextMenu: Menu;
private tray: Tray; private tray: Tray;
private menu: Menu;
private icon: string | Electron.NativeImage; private icon: string | Electron.NativeImage;
private pressedIcon: Electron.NativeImage; private pressedIcon: Electron.NativeImage;
constructor(private windowMain: WindowMain, private appName: string, private minToTray: () => Promise<boolean>) { constructor(private windowMain: WindowMain, private i18nService: I18nService,
private storageService: StorageService, private appName: string) {
if (process.platform === 'win32') { if (process.platform === 'win32') {
this.icon = path.join(__dirname, '/images/icon.ico'); this.icon = path.join(__dirname, '/images/icon.ico');
} else if (process.platform === 'darwin') { } else if (process.platform === 'darwin') {
@ -28,52 +33,91 @@ export class TrayMain {
} }
} }
init() { async init(additionalMenuItems: MenuItemConstructorOptions[] = null) {
if (process.platform === 'linux') { const menuItemOptions: MenuItemConstructorOptions[] = [{
this.menu = Menu.buildFromTemplate([{ label: this.appName,
label: this.appName, click: () => this.toggleWindow(),
click: () => this.open(), },
}]); { type: 'separator' },
{
label: this.i18nService.t('exit'),
click: () => this.closeWindow(),
}];
if (additionalMenuItems != null) {
menuItemOptions.splice(1, 0, ...additionalMenuItems);
}
this.contextMenu = Menu.buildFromTemplate(menuItemOptions);
if (await this.storageService.get<boolean>(ElectronConstants.enableTrayKey)) {
this.showTray();
} }
this.windowMain.win.on('minimize', async (e: Event) => { this.windowMain.win.on('minimize', async (e: Event) => {
if (await this.minToTray()) { if (await this.storageService.get<boolean>(ElectronConstants.enableMinimizeToTrayKey)) {
e.preventDefault(); e.preventDefault();
await this.handleHideEvent(); await this.hideToTray();
} }
}); });
this.windowMain.win.on('show', async (e: Event) => { this.windowMain.win.on('show', async (e: Event) => {
await this.handleShowEvent(); const enableTray = await this.storageService.get<boolean>(ElectronConstants.enableTrayKey);
if (!enableTray) {
await this.removeTray(false);
}
}); });
} }
private handleShowEvent() { removeTray(showWindow = true) {
if (this.tray != null) { if (this.tray != null) {
this.tray.destroy(); this.tray.destroy();
this.tray = null; this.tray = null;
} }
if (this.windowMain.win != null && !this.windowMain.win.isVisible()) {
this.windowMain.win.show();
}
} }
private handleHideEvent() { hideToTray() {
this.showTray();
if (this.windowMain.win != null) {
this.windowMain.win.hide();
}
}
showTray() {
if (this.tray != null) {
return;
}
this.tray = new Tray(this.icon); this.tray = new Tray(this.icon);
this.tray.setToolTip(this.appName); this.tray.setToolTip(this.appName);
this.tray.on('click', () => this.toggleWindow());
if (this.pressedIcon != null) { if (this.pressedIcon != null) {
this.tray.setPressedImage(this.pressedIcon); this.tray.setPressedImage(this.pressedIcon);
} }
if (this.menu != null) { if (this.contextMenu != null) {
this.tray.setContextMenu(this.menu); this.tray.setContextMenu(this.contextMenu);
} }
this.tray.on('click', () => open());
this.windowMain.win.hide();
} }
private open() { private toggleWindow() {
if (this.windowMain.win == null) {
return;
}
if (this.windowMain.win.isVisible()) { if (this.windowMain.win.isVisible()) {
this.windowMain.win.hide(); this.windowMain.win.hide();
} else { } else {
this.windowMain.win.show(); this.windowMain.win.show();
} }
} }
private closeWindow() {
if (this.windowMain.win != null) {
this.windowMain.win.close();
}
}
} }