Rudimentary implementation of tray minimization(WIP)

Minimize app to tray

@kauffj I was not sure about which icon to use so I used a 96x96 png as
a placeholder. The feature is working well.

Fixes #374

3 small changes

Broken Minimization

Fixed App-minization finally

Bug fix and compatibility check

Added Alt+F4 accelerator to quit the app

Small features and fixes

Homerun: Added Quit to Menu

Fixes and changes
This commit is contained in:
hackrush 2017-09-14 13:06:41 +05:30 committed by Jeremy Kauffman
parent b858614902
commit 7a0a0c468e
6 changed files with 153 additions and 20 deletions

View file

@ -10,6 +10,7 @@ Web UI version numbers should always match the corresponding version of LBRY App
### Added
* Added new window menu options for reloading and help.
* Rewards are now marked in transaction history (#660)
* Minimize LBRY app to tray (issue #374)
*
### Changed

View file

@ -1,4 +1,5 @@
const {app, BrowserWindow, ipcMain} = require('electron');
module.exports = { safeQuit }
const {app, BrowserWindow, ipcMain, Menu, Tray, globalShortcut} = require('electron');
const url = require('url');
const isDebug = process.env.NODE_ENV === 'development';
const setMenu = require('./menu/main-menu.js');
@ -55,6 +56,13 @@ let readyToQuit = false;
// sendCredits it to, it's cached in this variable.
let openUri = null;
// Set this to true to minimize on clicking close
// false for normal action
let minimize = true;
// Keep the tray also, it is getting GC'd if put in createTray()
let tray = null;
function processRequestedUri(uri) {
// Windows normalizes URIs when they're passed in from other apps. On Windows,
// this function tries to restore the original URI that was typed.
@ -167,10 +175,47 @@ function createWindow () {
});
}
win.removeAllListeners();
win.on('close', function(event) {
if (minimize) {
event.preventDefault();
win.hide();
}
})
win.on('closed', () => {
win = null
})
win.on("hide", () => {
// Checks what to show in the tray icon menu
if (minimize) updateTray();
});
win.on("show", () => {
// Checks what to show in the tray icon menu
if (minimize) updateTray();
});
win.on("blur", () => {
// Checks what to show in the tray icon menu
if (minimize) updateTray();
// Unregisters Alt+F4 shortcut
globalShortcut.unregister('Alt+F4');
});
win.on("focus", () => {
// Checks what to show in the tray icon menu
if (minimize) updateTray();
// Registers shortcut for closing(quitting) the app
globalShortcut.register('Alt+F4', () => safeQuit());
win.webContents.send('window-is-focussed', null);
});
// Menu bar
win.setAutoHideMenuBar(true);
win.setMenuBarVisibility(isDebug);
@ -178,14 +223,61 @@ function createWindow () {
};
function createTray () {
// Minimize to tray logic follows:
// Set the tray icon
const iconPath = path.join(app.getAppPath(), "/dist/img/fav/32x32.png");
tray = new Tray(iconPath);
tray.setToolTip("LBRY App");
tray.setTitle("LBRY");
tray.on('double-click', () => {
win.show()
})
}
// This needs to be done as for linux the context menu doesn't update automatically(docs)
function updateTray() {
let contextMenu = Menu.buildFromTemplate(getMenuTemplate());
tray.setContextMenu(contextMenu);
}
function getMenuTemplate () {
return [
getToggleItem(),
{
label: "Quit",
click: () => safeQuit(),
},
]
function getToggleItem () {
if (win.isVisible() && win.isFocused()) {
return {
label: 'Hide LBRY App',
click: () => win.hide()
}
} else {
return {
label: 'Show LBRY App',
click: () => win.show()
}
}
}
}
function handleOpenUriRequested(uri) {
if (!win) {
// Window not created yet, so store up requested URI for when it is
openUri = processRequestedUri(uri);
} else {
if (win.isMinimized()) {
win.restore();
win.restore()
} else if (!win.isVisible()) {
win.show()
}
win.focus();
win.webContents.send('open-uri-requested', processRequestedUri(uri));
}
@ -224,6 +316,15 @@ function launchDaemon() {
daemonSubprocess.on('exit', handleDaemonSubprocessExited);
}
/*
* Quits by first killing the daemon, the calling quitting for real.
*/
function safeQuit() {
minimize = false;
app.quit();
}
/*
* Quits without any preparation. When a quit is requested (either through the
* interface or through app.quit()), we abort the quit, try to shut down the daemon,
@ -231,7 +332,7 @@ function launchDaemon() {
*/
function quitNow() {
readyToQuit = true;
app.quit();
safeQuit();
}
const isSecondaryInstance = app.makeSingleInstance((argv) => {
@ -240,6 +341,8 @@ const isSecondaryInstance = app.makeSingleInstance((argv) => {
} else if (win) {
if (win.isMinimized()) {
win.restore();
} else if (!win.isVisible()) {
win.show();
}
win.focus();
}
@ -252,6 +355,14 @@ if (isSecondaryInstance) { // We're not in the original process, so quit
app.on('ready', function(){
launchDaemonIfNotRunning();
if (process.platform === "linux") {
checkLinuxTraySupport( err => {
if (!err) createTray();
else minimize = false;
})
} else {
createTray();
}
createWindow();
});
@ -385,6 +496,22 @@ function upgrade(event, installerPath) {
console.log('After the install is complete, please reopen the app.');
}
// Taken from webtorrent-desktop
function checkLinuxTraySupport (cb) {
// Check that we're on Ubuntu (or another debian system) and that we have
// libappindicator1.
child_process.exec('dpkg --get-selections libappindicator1', function (err, stdout) {
if (err) return cb(err)
// Unfortunately there's no cleaner way, as far as I can tell, to check
// whether a debian package is installed:
if (stdout.endsWith('\tinstall\n')) {
cb(null)
} else {
cb(new Error('debian package not installed'))
}
})
}
ipcMain.on('upgrade', upgrade);
app.setAsDefaultProtocolClient('lbry');

View file

@ -1,6 +1,18 @@
const { app, shell, Menu } = require('electron');
const { safeQuit } = require('../main.js')
const baseTemplate = [
{
label: 'File',
submenu: [
{
label: 'Quit',
accelerator: "CommandOrControl+Q",
click: () => safeQuit(),
},
]
},
{
label: 'Edit',
submenu: [

BIN
ui/dist/img/fav/32x32.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -37,6 +37,14 @@ ipcRenderer.on("open-menu", (event, uri) => {
}
});
const dock = remote.app.dock;
ipcRenderer.on("window-is-focussed", (event, data) => {
if (!dock) return;
app.store.dispatch({ type: types.WINDOW_FOCUSED });
dock.setBadge("");
});
document.addEventListener("click", event => {
var target = event.target;
while (target && target !== document) {
@ -52,21 +60,6 @@ document.addEventListener("click", event => {
}
});
const application = remote.app;
const dock = application.dock;
const win = remote.getCurrentWindow();
// Tear down previous event listeners when reload
win.removeAllListeners();
// Clear the badge when the window is focused
win.on("focus", () => {
if (!dock) return;
app.store.dispatch({ type: types.WINDOW_FOCUSED });
dock.setBadge("");
});
const initialState = app.store.getState();
var init = function() {

View file

@ -311,13 +311,13 @@ debug@2.2.0:
dependencies:
ms "0.7.1"
debug@2.6.0, debug@^2.3.2, debug@^2.6.0:
debug@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b"
dependencies:
ms "0.7.2"
debug@^2.1.3, debug@^2.2.0, debug@^2.6.8:
debug@^2.1.3, debug@^2.2.0, debug@^2.3.2, debug@^2.6.0, debug@^2.6.8:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies: