Save app state when closing to tray
This commit is contained in:
parent
fcc26a1930
commit
47e0f7c992
5 changed files with 67 additions and 110 deletions
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"appId": "io.lbry.LBRY",
|
"appId": "io.lbry.LBRY",
|
||||||
"publish": {
|
// "publish": {
|
||||||
"provider": "s3",
|
// "provider": "s3",
|
||||||
"bucket": "releases.lbry.io",
|
// "bucket": "releases.lbry.io",
|
||||||
"path": "app/latest"
|
// "path": "app/latest"
|
||||||
},
|
// },
|
||||||
"mac": {
|
"mac": {
|
||||||
"category": "public.app-category.entertainment"
|
"category": "public.app-category.entertainment"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
import { app, Menu, Tray as ElectronTray } from 'electron';
|
|
||||||
import path from 'path';
|
|
||||||
import createWindow from './createWindow';
|
|
||||||
|
|
||||||
export default class Tray {
|
|
||||||
window;
|
|
||||||
updateAttachedWindow;
|
|
||||||
tray;
|
|
||||||
|
|
||||||
constructor(window, updateAttachedWindow) {
|
|
||||||
this.window = window;
|
|
||||||
this.updateAttachedWindow = updateAttachedWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
create() {
|
|
||||||
let iconPath;
|
|
||||||
switch (process.platform) {
|
|
||||||
case 'darwin': {
|
|
||||||
iconPath = path.join(__static, '/img/tray/mac/trayTemplate.png');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'win32': {
|
|
||||||
iconPath = path.join(__static, '/img/tray/windows/tray.ico');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
iconPath = path.join(__static, '/img/tray/default/tray.png');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tray = new ElectronTray(iconPath);
|
|
||||||
|
|
||||||
this.tray.on('double-click', () => {
|
|
||||||
if (!this.window || this.window.isDestroyed()) {
|
|
||||||
this.window = createWindow();
|
|
||||||
this.updateAttachedWindow(this.window);
|
|
||||||
} else {
|
|
||||||
this.window.show();
|
|
||||||
this.window.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.tray.setToolTip('LBRY App');
|
|
||||||
|
|
||||||
const template = [
|
|
||||||
{
|
|
||||||
label: `Open ${app.getName()}`,
|
|
||||||
click: () => {
|
|
||||||
if (!this.window || this.window.isDestroyed()) {
|
|
||||||
this.window = createWindow();
|
|
||||||
this.updateAttachedWindow(this.window);
|
|
||||||
} else {
|
|
||||||
this.window.show();
|
|
||||||
this.window.focus();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ role: 'quit' },
|
|
||||||
];
|
|
||||||
const contextMenu = Menu.buildFromTemplate(template);
|
|
||||||
this.tray.setContextMenu(contextMenu);
|
|
||||||
}
|
|
||||||
}
|
|
41
src/main/createTray.js
Normal file
41
src/main/createTray.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import { app, Menu, Tray as ElectronTray } from 'electron';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
export default window => {
|
||||||
|
let iconPath;
|
||||||
|
switch (process.platform) {
|
||||||
|
case 'darwin': {
|
||||||
|
iconPath = path.join(__static, '/img/tray/mac/trayTemplate.png');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'win32': {
|
||||||
|
iconPath = path.join(__static, '/img/tray/windows/tray.ico');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
iconPath = path.join(__static, '/img/tray/default/tray.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tray = new ElectronTray(iconPath);
|
||||||
|
|
||||||
|
tray.on('double-click', () => {
|
||||||
|
window.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
tray.setToolTip('LBRY App');
|
||||||
|
|
||||||
|
const template = [
|
||||||
|
{
|
||||||
|
label: `Open ${app.getName()}`,
|
||||||
|
click: () => {
|
||||||
|
window.show();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ role: 'quit' },
|
||||||
|
];
|
||||||
|
const contextMenu = Menu.buildFromTemplate(template);
|
||||||
|
tray.setContextMenu(contextMenu);
|
||||||
|
|
||||||
|
return tray;
|
||||||
|
};
|
|
@ -2,7 +2,7 @@ import { app, BrowserWindow, dialog } from 'electron';
|
||||||
import setupBarMenu from './menu/setupBarMenu';
|
import setupBarMenu from './menu/setupBarMenu';
|
||||||
import setupContextMenu from './menu/setupContextMenu';
|
import setupContextMenu from './menu/setupContextMenu';
|
||||||
|
|
||||||
export default deepLinkingURIArg => {
|
export default appState => {
|
||||||
let windowConfiguration = {
|
let windowConfiguration = {
|
||||||
backgroundColor: '#155B4A',
|
backgroundColor: '#155B4A',
|
||||||
minWidth: 800,
|
minWidth: 800,
|
||||||
|
@ -35,11 +35,7 @@ export default deepLinkingURIArg => {
|
||||||
|
|
||||||
let deepLinkingURI;
|
let deepLinkingURI;
|
||||||
// Protocol handler for win32
|
// Protocol handler for win32
|
||||||
if (
|
if (process.platform === 'win32' && String(process.argv[1]).startsWith('lbry')) {
|
||||||
!deepLinkingURIArg &&
|
|
||||||
process.platform === 'win32' &&
|
|
||||||
String(process.argv[1]).startsWith('lbry')
|
|
||||||
) {
|
|
||||||
// Keep only command line / deep linked arguments
|
// Keep only command line / deep linked arguments
|
||||||
// Windows normalizes URIs when they're passed in from other apps. On Windows, this tries to
|
// Windows normalizes URIs when they're passed in from other apps. On Windows, this tries to
|
||||||
// restore the original URI that was typed.
|
// restore the original URI that was typed.
|
||||||
|
@ -48,15 +44,16 @@ export default deepLinkingURIArg => {
|
||||||
// - In a URI with a claim ID, like lbry://channel#claimid, Windows interprets the hash mark as
|
// - In a URI with a claim ID, like lbry://channel#claimid, Windows interprets the hash mark as
|
||||||
// an anchor and converts it to lbry://channel/#claimid. We remove the slash here as well.
|
// an anchor and converts it to lbry://channel/#claimid. We remove the slash here as well.
|
||||||
deepLinkingURI = process.argv[1].replace(/\/$/, '').replace('/#', '#');
|
deepLinkingURI = process.argv[1].replace(/\/$/, '').replace('/#', '#');
|
||||||
} else {
|
|
||||||
deepLinkingURI = deepLinkingURIArg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupBarMenu();
|
setupBarMenu();
|
||||||
setupContextMenu(window);
|
setupContextMenu(window);
|
||||||
|
|
||||||
window.on('closed', () => {
|
window.on('close', event => {
|
||||||
window = null;
|
if (!appState.isQuitting) {
|
||||||
|
event.preventDefault();
|
||||||
|
window.hide();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.on('focus', () => {
|
window.on('focus', () => {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import https from 'https';
|
||||||
import { shell, app, ipcMain, dialog } from 'electron';
|
import { shell, app, ipcMain, dialog } from 'electron';
|
||||||
import { autoUpdater } from 'electron-updater';
|
import { autoUpdater } from 'electron-updater';
|
||||||
import Daemon from './Daemon';
|
import Daemon from './Daemon';
|
||||||
import Tray from './Tray';
|
import createTray from './createTray';
|
||||||
import createWindow from './createWindow';
|
import createWindow from './createWindow';
|
||||||
|
|
||||||
autoUpdater.autoDownload = true;
|
autoUpdater.autoDownload = true;
|
||||||
|
@ -32,11 +32,7 @@ let rendererWindow;
|
||||||
let tray;
|
let tray;
|
||||||
let daemon;
|
let daemon;
|
||||||
|
|
||||||
let isQuitting;
|
const appState = {};
|
||||||
|
|
||||||
const updateRendererWindow = window => {
|
|
||||||
rendererWindow = window;
|
|
||||||
};
|
|
||||||
|
|
||||||
const installExtensions = async () => {
|
const installExtensions = async () => {
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies,global-require
|
// eslint-disable-next-line import/no-extraneous-dependencies,global-require
|
||||||
|
@ -64,7 +60,7 @@ app.on('ready', async () => {
|
||||||
daemon = new Daemon();
|
daemon = new Daemon();
|
||||||
daemon.on('exit', () => {
|
daemon.on('exit', () => {
|
||||||
daemon = null;
|
daemon = null;
|
||||||
if (!isQuitting) {
|
if (!appState.isQuitting) {
|
||||||
dialog.showErrorBox(
|
dialog.showErrorBox(
|
||||||
'Daemon has Exited',
|
'Daemon has Exited',
|
||||||
'The daemon may have encountered an unexpected error, or another daemon instance is already running.'
|
'The daemon may have encountered an unexpected error, or another daemon instance is already running.'
|
||||||
|
@ -77,15 +73,12 @@ app.on('ready', async () => {
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
await installExtensions();
|
await installExtensions();
|
||||||
}
|
}
|
||||||
rendererWindow = createWindow();
|
rendererWindow = createWindow(appState);
|
||||||
tray = new Tray(rendererWindow, updateRendererWindow);
|
tray = createTray(rendererWindow);
|
||||||
tray.create();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('activate', () => {
|
app.on('activate', () => {
|
||||||
// On macOS it's common to re-create a window in the app when the
|
rendererWindow.show();
|
||||||
// dock icon is clicked and there are no other windows open.
|
|
||||||
if (!rendererWindow) rendererWindow = createWindow();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('will-quit', event => {
|
app.on('will-quit', event => {
|
||||||
|
@ -117,7 +110,7 @@ app.on('will-quit', event => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
isQuitting = true;
|
appState.isQuitting = true;
|
||||||
if (daemon) daemon.quit();
|
if (daemon) daemon.quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -126,18 +119,13 @@ app.on('will-finish-launching', () => {
|
||||||
// Protocol handler for macOS
|
// Protocol handler for macOS
|
||||||
app.on('open-url', (event, URL) => {
|
app.on('open-url', (event, URL) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (rendererWindow && !rendererWindow.isDestroyed()) {
|
rendererWindow.webContents.send('open-uri-requested', URL);
|
||||||
rendererWindow.webContents.send('open-uri-requested', URL);
|
rendererWindow.show();
|
||||||
rendererWindow.show();
|
|
||||||
rendererWindow.focus();
|
|
||||||
} else {
|
|
||||||
rendererWindow = createWindow(URL);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('before-quit', () => {
|
||||||
// Subscribe to event so the app doesn't quit when closing the window.
|
appState.isQuitting = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('upgrade', (event, installerPath) => {
|
ipcMain.on('upgrade', (event, installerPath) => {
|
||||||
|
@ -224,7 +212,7 @@ ipcMain.on('set-auth-token', (event, token) => {
|
||||||
|
|
||||||
process.on('uncaughtException', error => {
|
process.on('uncaughtException', error => {
|
||||||
dialog.showErrorBox('Error Encountered', `Caught error: ${error}`);
|
dialog.showErrorBox('Error Encountered', `Caught error: ${error}`);
|
||||||
isQuitting = true;
|
appState.isQuitting = true;
|
||||||
if (daemon) daemon.quit();
|
if (daemon) daemon.quit();
|
||||||
app.exit(1);
|
app.exit(1);
|
||||||
});
|
});
|
||||||
|
@ -240,14 +228,8 @@ const isSecondInstance = app.makeSingleInstance(argv => {
|
||||||
URI = argv[1].replace(/\/$/, '').replace('/#', '#');
|
URI = argv[1].replace(/\/$/, '').replace('/#', '#');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rendererWindow && !rendererWindow.isDestroyed()) {
|
rendererWindow.webContents.send('open-uri-requested', URI);
|
||||||
rendererWindow.webContents.send('open-uri-requested', URI);
|
rendererWindow.show();
|
||||||
|
|
||||||
rendererWindow.show();
|
|
||||||
rendererWindow.focus();
|
|
||||||
} else {
|
|
||||||
rendererWindow = createWindow(URI);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isSecondInstance) {
|
if (isSecondInstance) {
|
||||||
|
|
Loading…
Reference in a new issue