Skip to content

Commit

Permalink
-Prevent multiple instances of the app launching which was a potentia…
Browse files Browse the repository at this point in the history
…lly large problem on Windows

-True minimizing "to" the Windows Tray
  • Loading branch information
chrisknepper committed Jun 28, 2018
1 parent f5fd71a commit 166ebe0
Showing 1 changed file with 118 additions and 100 deletions.
218 changes: 118 additions & 100 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,116 +17,134 @@ import { IS_MAC, IS_WINDOWS, IS_LINUX, IS_DEV } from './constants';
// in config/env_xxx.json file.
import env from 'env';

let tray; // Must declare reference to instance of Tray as a variable, not a const, or bad/weird things happen
let mainWindow = null;

// Prevent multiple instances of the app which causes many problems with an app like ours
// Without this, if an instance were minimized to the tray in Windows, clicking a shortcut would launch another instance, icky
// Adapted from https://github.com/electron/electron/blob/v2.0.2/docs/api/app.md#appmakesingleinstancecallback
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, let's show our existing instance instead
if (mainWindow) {
if (!mainWindow.isVisible()) {
mainWindow.show();
}
}
});

const setApplicationMenu = () => {
const menus = baseMenuTemplate;
if (isSecondInstance) {
app.quit()
} else {
let tray; // Must declare reference to instance of Tray as a variable, not a const, or bad/weird things happen

const setApplicationMenu = () => {
const menus = baseMenuTemplate;
if (env.name !== 'production') {
menus.push(devMenuTemplate);
}
menus.push(helpMenuTemplate);
Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
};

// Save userData in separate folders for each environment.
// Thanks to this you can use production and development versions of the app
// on same machine like those are two separate apps.
if (env.name !== 'production') {
menus.push(devMenuTemplate);
const userDataPath = app.getPath('userData');
app.setPath('userData', `${userDataPath} (${env.name})`);
}
menus.push(helpMenuTemplate);
Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
};

// Save userData in separate folders for each environment.
// Thanks to this you can use production and development versions of the app
// on same machine like those are two separate apps.
if (env.name !== 'production') {
const userDataPath = app.getPath('userData');
app.setPath('userData', `${userDataPath} (${env.name})`);
}

if (IS_WINDOWS) {
// Stupid, DUMB calls that have to be made to let notifications come through on Windows (only Windows 10?)
// See: https://github.com/electron/electron/issues/10864#issuecomment-382519150
app.setAppUserModelId('com.knepper.android-messages-desktop');
app.setAsDefaultProtocolClient('android-messages-desktop');
}

app.on('ready', () => {
setApplicationMenu();
autoUpdater.checkForUpdatesAndNotify();

const mainWindow = createWindow('main', {
width: 1100,
height: 800
});

mainWindow.loadURL(
url.format({
pathname: path.join(__dirname, 'app.html'),
protocol: 'file:',
slashes: true
})
);

app.mainWindow = mainWindow; // Quick and dirty way for renderer process to access mainWindow for communication

if (IS_MAC) {
let quitViaContext = false;
app.on('before-quit', () => {
quitViaContext = true;
});

mainWindow.on('close', (event) => {
if (!quitViaContext) {
event.preventDefault();
mainWindow.hide();
}
});

app.on('activate', () => {
mainWindow.show();
});
if (IS_WINDOWS) {
// Stupid, DUMB calls that have to be made to let notifications come through on Windows (only Windows 10?)
// See: https://github.com/electron/electron/issues/10864#issuecomment-382519150
app.setAppUserModelId('com.knepper.android-messages-desktop');
app.setAsDefaultProtocolClient('android-messages-desktop');
}

if (IS_WINDOWS) {
mainWindow.on('close', (event) => {
app.quit();
});
app.on('ready', () => {
setApplicationMenu();
autoUpdater.checkForUpdatesAndNotify();

tray = new Tray(__dirname + '../../resources/icon.ico');
mainWindow = createWindow('main', {
width: 1100,
height: 800
});

let contextMenu = Menu.buildFromTemplate([
{
label: 'Show',
click: () => {
mainWindow.show();
mainWindow.loadURL(
url.format({
pathname: path.join(__dirname, 'app.html'),
protocol: 'file:',
slashes: true
})
);

app.mainWindow = mainWindow; // Quick and dirty way for renderer process to access mainWindow for communication

if (IS_MAC) {
let quitViaContext = false;
app.on('before-quit', () => {
quitViaContext = true;
});

mainWindow.on('close', (event) => {
if (!quitViaContext) {
event.preventDefault();
mainWindow.hide();
}
},
{
label: 'Quit',
click: () => {
app.quit();
});

app.on('activate', () => {
mainWindow.show();
});
}

if (IS_WINDOWS) {
mainWindow.on('close', (event) => {
app.quit();
});

tray = new Tray(__dirname + '../../resources/icon.ico');

let contextMenu = Menu.buildFromTemplate([
{
label: 'Show',
click: () => {
mainWindow.show();
}
},
{
label: 'Quit',
click: () => {
app.quit();
}
}
}
]);

tray.setContextMenu(contextMenu);
]);

tray.on('double-click', (event) => {
event.preventDefault();
mainWindow.show();
});

mainWindow.on('minimize', (event) => {
event.preventDefault();
// TODO: Hide the window via mainWindow.hide() instead of minimizing?
// Hiding would allow the icon to disappear from the taskbar if it's not pinned,
// but if it's pinned, hidden, then clicked, results in a duplicate instance of the app...
// Possible solution: https://github.com/electron/electron/blob/v0.36.10/docs/api/app.md#appmakesingleinstancecallback
mainWindow.minimize();
});
}
tray.setContextMenu(contextMenu);

// TODO: Better UX for Linux...likely similar to Windows as far as tray behavior
if (IS_LINUX) {
app.on('window-all-closed', (event) => {
app.quit();
});
}
tray.on('double-click', (event) => {
event.preventDefault();
mainWindow.show();
});

if (IS_DEV) {
mainWindow.openDevTools();
}
});
mainWindow.on('minimize', (event) => {
event.preventDefault();
// TODO: Hide the window via mainWindow.hide() instead of minimizing?
// Hiding would allow the icon to disappear from the taskbar if it's not pinned,
// but if it's pinned, hidden, then clicked, results in a duplicate instance of the app...
// Possible solution: https://github.com/electron/electron/blob/v0.36.10/docs/api/app.md#appmakesingleinstancecallback
mainWindow.hide();
});
}

// TODO: Better UX for Linux...likely similar to Windows as far as tray behavior
if (IS_LINUX) {
app.on('window-all-closed', (event) => {
app.quit();
});
}

if (IS_DEV) {
mainWindow.openDevTools();
}
});
}

0 comments on commit 166ebe0

Please sign in to comment.