2016-11-02 14:49:28 -04:00
|
|
|
/*
|
2016-11-03 13:06:41 -04:00
|
|
|
Copyright 2016 Aviral Dasgupta
|
|
|
|
Copyright 2016 OpenMarket Ltd
|
2017-06-04 10:30:44 -04:00
|
|
|
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
2016-11-02 14:49:28 -04:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2016-12-05 09:08:27 -05:00
|
|
|
// Squirrel on windows starts the app with various flags
|
|
|
|
// as hooks to tell us when we've been installed/uninstalled
|
|
|
|
// etc.
|
2017-05-22 14:21:52 -04:00
|
|
|
const checkSquirrelHooks = require('./squirrelhooks');
|
|
|
|
if (checkSquirrelHooks()) return;
|
2016-12-01 06:35:26 -05:00
|
|
|
|
2017-05-26 04:45:30 -04:00
|
|
|
const argv = require('minimist')(process.argv);
|
2016-12-05 09:08:27 -05:00
|
|
|
const electron = require('electron');
|
2017-05-24 10:52:08 -04:00
|
|
|
const AutoLaunch = require('auto-launch');
|
2016-11-02 14:49:28 -04:00
|
|
|
|
2017-01-19 09:29:07 -05:00
|
|
|
const tray = require('./tray');
|
2017-05-22 14:21:52 -04:00
|
|
|
const vectorMenu = require('./vectormenu');
|
2017-05-25 07:42:53 -04:00
|
|
|
const webContentsHandler = require('./webcontents-handler');
|
2017-06-11 11:43:20 -04:00
|
|
|
const updater = require('./updater');
|
2016-11-02 14:49:28 -04:00
|
|
|
|
2017-04-12 13:13:25 -04:00
|
|
|
const windowStateKeeper = require('electron-window-state');
|
|
|
|
|
2017-05-26 04:45:30 -04:00
|
|
|
if (argv.profile) {
|
|
|
|
electron.app.setPath('userData', `${electron.app.getPath('userData')}-${argv.profile}`);
|
|
|
|
}
|
|
|
|
|
2016-11-08 06:07:36 -05:00
|
|
|
let vectorConfig = {};
|
|
|
|
try {
|
2016-11-25 15:09:21 -05:00
|
|
|
vectorConfig = require('../../webapp/config.json');
|
2016-11-08 06:07:36 -05:00
|
|
|
} catch (e) {
|
|
|
|
// it would be nice to check the error code here and bail if the config
|
|
|
|
// is unparseable, but we get MODULE_NOT_FOUND in the case of a missing
|
|
|
|
// file or invalid json, so node is just very unhelpful.
|
|
|
|
// Continue with the defaults (ie. an empty config)
|
|
|
|
}
|
|
|
|
|
2016-11-02 14:49:28 -04:00
|
|
|
let mainWindow = null;
|
2017-06-11 11:43:20 -04:00
|
|
|
global.appQuitting = false;
|
2016-11-02 14:49:28 -04:00
|
|
|
|
2016-11-08 06:07:36 -05:00
|
|
|
|
|
|
|
// handle uncaught errors otherwise it displays
|
|
|
|
// stack traces in popup dialogs, which is terrible (which
|
|
|
|
// it will do any time the auto update poke fails, and there's
|
|
|
|
// no other way to catch this error).
|
|
|
|
// Assuming we generally run from the console when developing,
|
|
|
|
// this is far preferable.
|
2017-05-17 05:39:43 -04:00
|
|
|
process.on('uncaughtException', function(error) {
|
2017-05-22 14:21:52 -04:00
|
|
|
console.log('Unhandled exception', error);
|
2016-11-08 06:07:36 -05:00
|
|
|
});
|
|
|
|
|
2017-05-17 05:39:43 -04:00
|
|
|
let focusHandlerAttached = false;
|
|
|
|
electron.ipcMain.on('setBadgeCount', function(ev, count) {
|
|
|
|
electron.app.setBadgeCount(count);
|
2017-05-31 19:00:00 -04:00
|
|
|
if (count === 0) {
|
|
|
|
mainWindow.flashFrame(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
electron.ipcMain.on('loudNotification', function() {
|
|
|
|
if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) {
|
|
|
|
mainWindow.flashFrame(true);
|
|
|
|
mainWindow.once('focus', () => {
|
2017-05-17 05:39:43 -04:00
|
|
|
mainWindow.flashFrame(false);
|
2017-05-31 19:00:00 -04:00
|
|
|
focusHandlerAttached = false;
|
|
|
|
});
|
|
|
|
focusHandlerAttached = true;
|
2017-05-17 05:39:43 -04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-05-22 13:32:39 -04:00
|
|
|
let powerSaveBlockerId;
|
|
|
|
electron.ipcMain.on('app_onAction', function(ev, payload) {
|
|
|
|
switch (payload.action) {
|
|
|
|
case 'call_state':
|
2017-09-18 19:53:44 -04:00
|
|
|
if (powerSaveBlockerId && electron.powerSaveBlocker.isStarted(powerSaveBlockerId)) {
|
2017-05-22 13:32:39 -04:00
|
|
|
if (payload.state === 'ended') {
|
|
|
|
electron.powerSaveBlocker.stop(powerSaveBlockerId);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (payload.state === 'connected') {
|
|
|
|
powerSaveBlockerId = electron.powerSaveBlocker.start('prevent-display-sleep');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2017-01-10 13:39:21 -05:00
|
|
|
electron.app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
|
|
|
|
|
2017-01-19 11:01:37 -05:00
|
|
|
const shouldQuit = electron.app.makeSingleInstance((commandLine, workingDirectory) => {
|
|
|
|
// Someone tried to run a second instance, we should focus our window.
|
|
|
|
if (mainWindow) {
|
|
|
|
if (!mainWindow.isVisible()) mainWindow.show();
|
|
|
|
if (mainWindow.isMinimized()) mainWindow.restore();
|
|
|
|
mainWindow.focus();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (shouldQuit) {
|
2017-05-22 14:21:52 -04:00
|
|
|
console.log('Other instance detected: exiting');
|
2017-05-26 04:49:23 -04:00
|
|
|
electron.app.exit();
|
2017-01-19 11:01:37 -05:00
|
|
|
}
|
|
|
|
|
2017-05-24 10:52:08 -04:00
|
|
|
|
|
|
|
const launcher = new AutoLaunch({
|
|
|
|
name: vectorConfig.brand || 'Riot',
|
|
|
|
isHidden: true,
|
2017-05-30 05:53:01 -04:00
|
|
|
mac: {
|
|
|
|
useLaunchAgent: true,
|
|
|
|
},
|
2017-05-24 10:52:08 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
const settings = {
|
|
|
|
'auto-launch': {
|
|
|
|
get: launcher.isEnabled,
|
|
|
|
set: function(bool) {
|
|
|
|
if (bool) {
|
|
|
|
return launcher.enable();
|
|
|
|
} else {
|
|
|
|
return launcher.disable();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
electron.ipcMain.on('settings_get', async function(ev) {
|
|
|
|
const data = {};
|
|
|
|
|
|
|
|
try {
|
|
|
|
await Promise.all(Object.keys(settings).map(async function (setting) {
|
|
|
|
data[setting] = await settings[setting].get();
|
|
|
|
}));
|
|
|
|
|
|
|
|
ev.sender.send('settings', data);
|
|
|
|
} catch(e) { console.error(e); }
|
|
|
|
});
|
|
|
|
|
|
|
|
electron.ipcMain.on('settings_set', function(ev, key, value) {
|
|
|
|
console.log(key, value);
|
|
|
|
if (settings[key] && settings[key].set) {
|
|
|
|
settings[key].set(value);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-11-08 06:07:36 -05:00
|
|
|
electron.app.on('ready', () => {
|
2017-06-04 10:30:44 -04:00
|
|
|
|
|
|
|
if (argv.devtools) {
|
|
|
|
try {
|
|
|
|
const { default: installExtension, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer');
|
|
|
|
installExtension(REACT_DEVELOPER_TOOLS)
|
|
|
|
.then((name) => console.log(`Added Extension: ${name}`))
|
|
|
|
.catch((err) => console.log('An error occurred: ', err));
|
|
|
|
installExtension(REACT_PERF)
|
|
|
|
.then((name) => console.log(`Added Extension: ${name}`))
|
|
|
|
.catch((err) => console.log('An error occurred: ', err));
|
|
|
|
} catch(e) {console.log(e);}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-05 09:08:27 -05:00
|
|
|
if (vectorConfig.update_base_url) {
|
2017-05-22 14:21:52 -04:00
|
|
|
console.log(`Starting auto update with base URL: ${vectorConfig.update_base_url}`);
|
2017-06-20 09:05:17 -04:00
|
|
|
updater.start(vectorConfig.update_base_url);
|
2016-12-05 09:08:27 -05:00
|
|
|
} else {
|
2017-05-22 14:21:52 -04:00
|
|
|
console.log('No update_base_url is defined: auto update is disabled');
|
2016-12-05 09:08:27 -05:00
|
|
|
}
|
2016-11-02 14:49:28 -04:00
|
|
|
|
2017-05-22 14:21:52 -04:00
|
|
|
const iconPath = `${__dirname}/../img/riot.${process.platform === 'win32' ? 'ico' : 'png'}`;
|
2016-12-07 06:19:51 -05:00
|
|
|
|
2017-04-12 13:13:25 -04:00
|
|
|
// Load the previous window state with fallback to defaults
|
2017-05-22 14:21:52 -04:00
|
|
|
const mainWindowState = windowStateKeeper({
|
2017-04-12 13:13:25 -04:00
|
|
|
defaultWidth: 1024,
|
|
|
|
defaultHeight: 768,
|
|
|
|
});
|
|
|
|
|
2017-06-12 08:47:29 -04:00
|
|
|
mainWindow = global.mainWindow = new electron.BrowserWindow({
|
2017-05-22 14:21:52 -04:00
|
|
|
icon: iconPath,
|
2016-12-06 04:45:31 -05:00
|
|
|
show: false,
|
2017-01-18 05:39:59 -05:00
|
|
|
autoHideMenuBar: true,
|
2017-04-12 13:13:25 -04:00
|
|
|
|
|
|
|
x: mainWindowState.x,
|
|
|
|
y: mainWindowState.y,
|
|
|
|
width: mainWindowState.width,
|
|
|
|
height: mainWindowState.height,
|
2016-11-02 14:49:28 -04:00
|
|
|
});
|
2016-11-08 10:46:21 -05:00
|
|
|
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`);
|
2017-05-22 14:21:52 -04:00
|
|
|
electron.Menu.setApplicationMenu(vectorMenu);
|
2016-11-02 14:49:28 -04:00
|
|
|
|
2017-05-30 07:33:32 -04:00
|
|
|
// explicitly hide because setApplicationMenu on Linux otherwise shows...
|
|
|
|
// https://github.com/electron/electron/issues/9621
|
|
|
|
mainWindow.hide();
|
|
|
|
|
2017-01-19 09:29:07 -05:00
|
|
|
// Create trayIcon icon
|
2017-06-12 08:47:29 -04:00
|
|
|
tray.create({
|
2017-05-22 14:21:52 -04:00
|
|
|
icon_path: iconPath,
|
|
|
|
brand: vectorConfig.brand || 'Riot',
|
2017-01-19 09:29:07 -05:00
|
|
|
});
|
|
|
|
|
2017-05-26 04:45:30 -04:00
|
|
|
if (!argv.hidden) {
|
2017-04-17 17:10:56 -04:00
|
|
|
mainWindow.once('ready-to-show', () => {
|
|
|
|
mainWindow.show();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-11-02 14:49:28 -04:00
|
|
|
mainWindow.on('closed', () => {
|
2017-06-12 08:47:29 -04:00
|
|
|
mainWindow = global.mainWindow = null;
|
2016-11-02 14:49:28 -04:00
|
|
|
});
|
|
|
|
mainWindow.on('close', (e) => {
|
2017-06-11 11:43:20 -04:00
|
|
|
if (!global.appQuitting && (tray.hasTray() || process.platform === 'darwin')) {
|
2016-11-02 14:49:28 -04:00
|
|
|
// On Mac, closing the window just hides it
|
|
|
|
// (this is generally how single-window Mac apps
|
|
|
|
// behave, eg. Mail.app)
|
|
|
|
e.preventDefault();
|
|
|
|
mainWindow.hide();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-08-03 10:03:50 -04:00
|
|
|
if (process.platform === 'win32') {
|
|
|
|
// Handle forward/backward mouse buttons in Windows
|
|
|
|
mainWindow.on('app-command', (e, cmd) => {
|
|
|
|
if (cmd === 'browser-backward' && mainWindow.webContents.canGoBack()) {
|
|
|
|
mainWindow.webContents.goBack();
|
|
|
|
} else if (cmd === 'browser-forward' && mainWindow.webContents.canGoForward()) {
|
|
|
|
mainWindow.webContents.goForward();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-05-25 07:42:53 -04:00
|
|
|
webContentsHandler(mainWindow.webContents);
|
2017-04-12 13:13:25 -04:00
|
|
|
mainWindowState.manage(mainWindow);
|
2016-11-02 14:49:28 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
electron.app.on('window-all-closed', () => {
|
|
|
|
electron.app.quit();
|
|
|
|
});
|
|
|
|
|
|
|
|
electron.app.on('activate', () => {
|
|
|
|
mainWindow.show();
|
|
|
|
});
|
|
|
|
|
|
|
|
electron.app.on('before-quit', () => {
|
2017-06-11 11:43:20 -04:00
|
|
|
global.appQuitting = true;
|
2017-06-22 13:25:19 -04:00
|
|
|
if (mainWindow) {
|
|
|
|
mainWindow.webContents.send('before-quit');
|
|
|
|
}
|
2016-11-02 14:49:28 -04:00
|
|
|
});
|
2016-12-06 08:28:59 -05:00
|
|
|
|
|
|
|
// Set the App User Model ID to match what the squirrel
|
|
|
|
// installer uses for the shortcut icon.
|
|
|
|
// This makes notifications work on windows 8.1 (and is
|
|
|
|
// a noop on other platforms).
|
|
|
|
electron.app.setAppUserModelId('com.squirrel.riot-web.Riot');
|