From 7c877e66ffca92dfdf93b4b9094049204323e7dd Mon Sep 17 00:00:00 2001 From: tigerbot Date: Thu, 20 Apr 2017 12:54:01 -0600 Subject: [PATCH] implemented basic tray --- images/daplie-logo.png | Bin 0 -> 40336 bytes index.js | 36 ++++++++++------ package.json | 2 +- tray.js | 94 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 15 deletions(-) create mode 100644 images/daplie-logo.png create mode 100644 tray.js diff --git a/images/daplie-logo.png b/images/daplie-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6d968ca9707ef660e7fcbcbb9b4d93f07f14a3f7 GIT binary patch literal 40336 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 literal 0 HcmV?d00001 diff --git a/index.js b/index.js index 1f2e3b9..db7d685 100644 --- a/index.js +++ b/index.js @@ -12,6 +12,9 @@ function createWindow () { // Create the browser window. win = new BrowserWindow({width: 800, height: 600}); + var tray = require('./tray'); + tray.init(win); + // and load the index.html of the app. win.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), @@ -23,11 +26,19 @@ function createWindow () { win.webContents.openDevTools(); // Emitted when the window is closed. - win.on('closed', function () { - // Dereference the window object, usually you would store windows - // in an array if your app supports multi windows, this is the time - // when you should delete the corresponding element. - win = null; + win.on('close', function (e) { + if (process.platform !== 'darwin') { + if (!tray.hasTray()) { + app.quit(); + return; + } + } + // We are either on Mac with a dock, or a system where we want to minimize to the tray, so + // don't actually close, just hide the window. + if (!app.isQuitting) { + e.preventDefault(); + win.hide(); + } }); } @@ -36,20 +47,17 @@ function createWindow () { // Some APIs can only be used after this event occurs. app.on('ready', createWindow); -// Quit when all windows are closed. -app.on('window-all-closed', function () { - // On macOS it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== 'darwin') { - app.quit(); - } +// Mark the application as quitting so the logic we have to minimize to the tray on window +// close doesn't prevent the proper exitting of the application. +app.on('before-quit', function () { + app.isQuitting = true; }); app.on('activate', function () { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. - if (win === null) { - createWindow(); + if (win) { + win.show(); } }); diff --git a/package.json b/package.json index f9a4f4b..a28286d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron-demo", - "version": "0.0.1", + "version": "0.0.2", "description": "Demo Electron app to use all the 'sexy' features", "maintainers": [ "seth.gibelyou@daplie.com" diff --git a/tray.js b/tray.js new file mode 100644 index 0000000..c5697b5 --- /dev/null +++ b/tray.js @@ -0,0 +1,94 @@ +var electron = require('electron'); +var app = electron.app; + +var win, tray; + +function updateTrayMenu () { + if (!tray) { + return; + } + + var menuTemplate = []; + + if (win.isVisible()) { + menuTemplate.push({ + label: 'Hide to tray', + click: function () { win.hide(); }, + }); + } else { + menuTemplate.push({ + label: 'Electron Demo App', + click: function () { win.show(); }, + }); + } + + menuTemplate.push({ + label: 'Quit', + click: function () { app.quit(); }, + }); + tray.setContextMenu(electron.Menu.buildFromTemplate(menuTemplate)); +} + +// Check to see if the tray is supported on this system. This code was mostly copied from +// the Webtorrent project. +function checkLinuxTraySupport (cb) { + var cp = require('child_process'); + + cp.exec('dpkg --get-selections libappindicator1', function (err, stdout) { + // Unfortunately there's no cleaner way, as far as I can tell, to check + // whether a debian package is installed: + if (err) { + cb(err); + } else if (stdout.endsWith('\tinstall\n')) { + cb(null); + } else { + cb(new Error('debian package not installed')); + } + }); +} + +function createTray() { + tray = new electron.Tray('./images/daplie-logo.png'); + tray.on('click', function () { win.show(); }); + updateTrayMenu(); +} + + +function initLinux () { + checkLinuxTraySupport(function (err) { + if (!err) { + createTray(); + } + }); +} +function initWin32 () { + createTray(); +} + +function init(window) { + if (win) { + console.error("can't initialize the tray mulitple times"); + return; + } + + win = window; + win.on('blur', updateTrayMenu); + win.on('focus', updateTrayMenu); + win.on('hide', updateTrayMenu); + win.on('show', updateTrayMenu); + + // Mac apps generally do not have menu bar icons + if (process.platform === 'linux') { + initLinux(); + } + if (process.platform === 'win32') { + initWin32(); + } +} + +function hasTray() { + return !!tray; +} + +module.exports.init = init; +module.exports.hasTray = hasTray;