2015-10-30 06:30:18 -07:00
|
|
|
|
'use strict';
|
2015-10-23 09:44:10 -07:00
|
|
|
|
|
2016-06-12 05:06:49 -07:00
|
|
|
|
const {
|
|
|
|
|
app,
|
|
|
|
|
Menu,
|
|
|
|
|
Tray,
|
|
|
|
|
ipcMain,
|
|
|
|
|
nativeImage,
|
2016-06-12 05:33:00 -07:00
|
|
|
|
dialog,
|
2016-10-04 11:34:00 -07:00
|
|
|
|
systemPreferences,
|
2018-02-21 11:20:33 -08:00
|
|
|
|
session,
|
2016-06-12 05:06:49 -07:00
|
|
|
|
} = require('electron');
|
2017-10-16 08:54:56 -07:00
|
|
|
|
const os = require('os');
|
|
|
|
|
const path = require('path');
|
2017-03-04 07:27:40 -08:00
|
|
|
|
const isDev = require('electron-is-dev');
|
2017-03-06 06:29:56 -08:00
|
|
|
|
const installExtension = require('electron-devtools-installer');
|
2017-07-10 08:19:28 -07:00
|
|
|
|
const squirrelStartup = require('./main/squirrelStartup');
|
2017-10-16 08:54:56 -07:00
|
|
|
|
const CriticalErrorHandler = require('./main/CriticalErrorHandler');
|
2016-09-25 07:14:01 -07:00
|
|
|
|
|
2017-10-13 21:17:33 -07:00
|
|
|
|
const protocols = require('../electron-builder.json').protocols;
|
|
|
|
|
|
2017-10-16 08:54:56 -07:00
|
|
|
|
const criticalErrorHandler = new CriticalErrorHandler();
|
|
|
|
|
|
|
|
|
|
process.on('uncaughtException', criticalErrorHandler.processUncaughtExceptionHandler.bind(criticalErrorHandler));
|
2016-07-04 00:39:42 -07:00
|
|
|
|
|
2017-03-18 08:07:29 -07:00
|
|
|
|
global.willAppQuit = false;
|
2016-12-22 06:26:18 -08:00
|
|
|
|
|
2016-09-16 07:02:45 -07:00
|
|
|
|
app.setAppUserModelId('com.squirrel.mattermost.Mattermost'); // Use explicit AppUserModelID
|
2017-07-10 08:19:28 -07:00
|
|
|
|
if (squirrelStartup()) {
|
2017-03-18 08:07:29 -07:00
|
|
|
|
global.willAppQuit = true;
|
2016-12-22 06:26:18 -08:00
|
|
|
|
}
|
2016-05-13 12:47:30 -07:00
|
|
|
|
|
2015-12-23 02:25:14 -08:00
|
|
|
|
var settings = require('./common/settings');
|
2016-03-06 04:58:52 -08:00
|
|
|
|
var certificateStore = require('./main/certificateStore').load(path.resolve(app.getPath('userData'), 'certificate.json'));
|
2017-03-18 08:07:29 -07:00
|
|
|
|
const {createMainWindow} = require('./main/mainWindow');
|
2016-09-25 07:14:01 -07:00
|
|
|
|
const appMenu = require('./main/menus/app');
|
|
|
|
|
const trayMenu = require('./main/menus/tray');
|
2017-04-27 06:45:32 -07:00
|
|
|
|
const downloadURL = require('./main/downloadURL');
|
2016-05-23 07:16:26 -07:00
|
|
|
|
const allowProtocolDialog = require('./main/allowProtocolDialog');
|
2017-12-04 06:52:49 -08:00
|
|
|
|
const PermissionManager = require('./main/PermissionManager');
|
2017-10-03 08:16:13 -07:00
|
|
|
|
const permissionRequestHandler = require('./main/permissionRequestHandler');
|
2018-01-17 07:14:33 -08:00
|
|
|
|
const AppStateManager = require('./main/AppStateManager');
|
2015-10-23 09:44:10 -07:00
|
|
|
|
|
2017-04-20 05:32:34 -07:00
|
|
|
|
const SpellChecker = require('./main/SpellChecker');
|
|
|
|
|
|
2016-11-09 06:03:49 -08:00
|
|
|
|
const assetsDir = path.resolve(app.getAppPath(), 'assets');
|
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
// Keep a global reference of the window object, if you don't, the window will
|
|
|
|
|
// be closed automatically when the JavaScript object is garbage collected.
|
|
|
|
|
var mainWindow = null;
|
2017-04-20 05:32:34 -07:00
|
|
|
|
let spellChecker = null;
|
2017-10-25 05:05:17 -07:00
|
|
|
|
let deeplinkingUrl = null;
|
2017-10-24 05:08:52 -07:00
|
|
|
|
let scheme = null;
|
2018-01-17 07:14:33 -08:00
|
|
|
|
let appState = null;
|
2017-12-04 06:52:49 -08:00
|
|
|
|
let permissionManager = null;
|
2016-09-25 07:14:01 -07:00
|
|
|
|
|
|
|
|
|
var argv = require('yargs').parse(process.argv.slice(1));
|
2015-12-12 03:32:06 -08:00
|
|
|
|
|
2016-08-02 12:29:24 -07:00
|
|
|
|
var hideOnStartup;
|
|
|
|
|
if (argv.hidden) {
|
|
|
|
|
hideOnStartup = true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-26 05:55:27 -08:00
|
|
|
|
if (argv['data-dir']) {
|
|
|
|
|
app.setPath('userData', path.resolve(argv['data-dir']));
|
2015-12-12 03:32:06 -08:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-06 06:37:35 -08:00
|
|
|
|
global.isDev = isDev && !argv.disableDevMode;
|
2017-03-06 05:00:21 -08:00
|
|
|
|
|
2016-01-14 05:50:12 -08:00
|
|
|
|
var config = {};
|
2015-12-23 02:25:14 -08:00
|
|
|
|
try {
|
2016-12-26 05:55:27 -08:00
|
|
|
|
const configFile = app.getPath('userData') + '/config.json';
|
2016-01-14 05:50:12 -08:00
|
|
|
|
config = settings.readFileSync(configFile);
|
2018-01-17 07:14:33 -08:00
|
|
|
|
if (config.version !== settings.version) {
|
2017-10-21 07:41:57 -07:00
|
|
|
|
config = settings.upgrade(config);
|
2015-12-23 02:25:14 -08:00
|
|
|
|
settings.writeFileSync(configFile, config);
|
|
|
|
|
}
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} catch (e) {
|
2017-05-03 04:30:23 -07:00
|
|
|
|
const spellCheckerLocale = SpellChecker.getSpellCheckerLocale(app.getLocale());
|
|
|
|
|
config = settings.loadDefault(null, spellCheckerLocale);
|
2016-10-19 02:35:32 -07:00
|
|
|
|
console.log('Failed to read or upgrade config.json', e);
|
2017-09-07 16:20:48 -07:00
|
|
|
|
if (!config.teams.length && config.defaultTeam) {
|
|
|
|
|
config.teams.push(config.defaultTeam);
|
|
|
|
|
|
|
|
|
|
const configFile = app.getPath('userData') + '/config.json';
|
|
|
|
|
settings.writeFileSync(configFile, config);
|
|
|
|
|
}
|
2015-12-23 02:25:14 -08:00
|
|
|
|
}
|
2016-06-17 07:50:41 -07:00
|
|
|
|
ipcMain.on('update-config', () => {
|
2016-12-26 05:55:27 -08:00
|
|
|
|
const configFile = app.getPath('userData') + '/config.json';
|
2016-06-17 07:50:41 -07:00
|
|
|
|
config = settings.readFileSync(configFile);
|
2017-12-04 06:52:49 -08:00
|
|
|
|
const trustedURLs = settings.mergeDefaultTeams(config.teams).map((team) => team.url);
|
|
|
|
|
permissionManager.setTrustedURLs(trustedURLs);
|
2017-04-20 05:32:34 -07:00
|
|
|
|
ipcMain.emit('update-dict', true, config.spellCheckerLocale);
|
2016-06-17 07:50:41 -07:00
|
|
|
|
});
|
2015-12-23 02:25:14 -08:00
|
|
|
|
|
2016-06-12 05:33:00 -07:00
|
|
|
|
// Only for OS X
|
2016-09-25 07:14:01 -07:00
|
|
|
|
function switchMenuIconImages(icons, isDarkMode) {
|
2016-06-12 05:33:00 -07:00
|
|
|
|
if (isDarkMode) {
|
|
|
|
|
icons.normal = icons.clicked.normal;
|
|
|
|
|
icons.unread = icons.clicked.unread;
|
|
|
|
|
icons.mention = icons.clicked.mention;
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} else {
|
2016-06-12 05:33:00 -07:00
|
|
|
|
icons.normal = icons.light.normal;
|
|
|
|
|
icons.unread = icons.light.unread;
|
|
|
|
|
icons.mention = icons.light.mention;
|
|
|
|
|
}
|
2016-09-25 07:14:01 -07:00
|
|
|
|
}
|
2016-06-12 05:33:00 -07:00
|
|
|
|
|
2015-10-30 06:30:18 -07:00
|
|
|
|
var trayIcon = null;
|
2016-09-25 07:14:01 -07:00
|
|
|
|
const trayImages = (() => {
|
2016-04-07 07:15:12 -07:00
|
|
|
|
switch (process.platform) {
|
2016-09-25 07:14:01 -07:00
|
|
|
|
case 'win32':
|
|
|
|
|
return {
|
2016-11-09 06:03:49 -08:00
|
|
|
|
normal: nativeImage.createFromPath(path.resolve(assetsDir, 'windows/tray.ico')),
|
|
|
|
|
unread: nativeImage.createFromPath(path.resolve(assetsDir, 'windows/tray_unread.ico')),
|
2018-02-21 11:20:33 -08:00
|
|
|
|
mention: nativeImage.createFromPath(path.resolve(assetsDir, 'windows/tray_mention.ico')),
|
2016-09-25 07:14:01 -07:00
|
|
|
|
};
|
|
|
|
|
case 'darwin':
|
|
|
|
|
{
|
2016-06-12 05:33:00 -07:00
|
|
|
|
const icons = {
|
|
|
|
|
light: {
|
2016-11-09 06:03:49 -08:00
|
|
|
|
normal: nativeImage.createFromPath(path.resolve(assetsDir, 'osx/MenuIcon.png')),
|
|
|
|
|
unread: nativeImage.createFromPath(path.resolve(assetsDir, 'osx/MenuIconUnread.png')),
|
2018-02-21 11:20:33 -08:00
|
|
|
|
mention: nativeImage.createFromPath(path.resolve(assetsDir, 'osx/MenuIconMention.png')),
|
2016-06-12 05:33:00 -07:00
|
|
|
|
},
|
2016-06-12 04:51:43 -07:00
|
|
|
|
clicked: {
|
2016-11-09 06:03:49 -08:00
|
|
|
|
normal: nativeImage.createFromPath(path.resolve(assetsDir, 'osx/ClickedMenuIcon.png')),
|
|
|
|
|
unread: nativeImage.createFromPath(path.resolve(assetsDir, 'osx/ClickedMenuIconUnread.png')),
|
2018-02-21 11:20:33 -08:00
|
|
|
|
mention: nativeImage.createFromPath(path.resolve(assetsDir, 'osx/ClickedMenuIconMention.png')),
|
|
|
|
|
},
|
2016-04-07 07:15:12 -07:00
|
|
|
|
};
|
2016-06-12 05:33:00 -07:00
|
|
|
|
switchMenuIconImages(icons, systemPreferences.isDarkMode());
|
|
|
|
|
return icons;
|
2016-09-25 07:14:01 -07:00
|
|
|
|
}
|
|
|
|
|
case 'linux':
|
2016-11-09 06:03:49 -08:00
|
|
|
|
{
|
2016-12-10 11:32:04 -08:00
|
|
|
|
const theme = config.trayIconTheme;
|
|
|
|
|
try {
|
|
|
|
|
return {
|
|
|
|
|
normal: nativeImage.createFromPath(path.resolve(assetsDir, 'linux', theme, 'MenuIconTemplate.png')),
|
|
|
|
|
unread: nativeImage.createFromPath(path.resolve(assetsDir, 'linux', theme, 'MenuIconUnreadTemplate.png')),
|
2018-02-21 11:20:33 -08:00
|
|
|
|
mention: nativeImage.createFromPath(path.resolve(assetsDir, 'linux', theme, 'MenuIconMentionTemplate.png')),
|
2016-12-10 11:32:04 -08:00
|
|
|
|
};
|
|
|
|
|
} catch (e) {
|
|
|
|
|
//Fallback for invalid theme setting
|
|
|
|
|
return {
|
|
|
|
|
normal: nativeImage.createFromPath(path.resolve(assetsDir, 'linux', 'light', 'MenuIconTemplate.png')),
|
|
|
|
|
unread: nativeImage.createFromPath(path.resolve(assetsDir, 'linux', 'light', 'MenuIconUnreadTemplate.png')),
|
2018-02-21 11:20:33 -08:00
|
|
|
|
mention: nativeImage.createFromPath(path.resolve(assetsDir, 'linux', 'light', 'MenuIconMentionTemplate.png')),
|
2016-12-10 11:32:04 -08:00
|
|
|
|
};
|
|
|
|
|
}
|
2016-11-09 06:03:49 -08:00
|
|
|
|
}
|
2016-09-25 07:14:01 -07:00
|
|
|
|
default:
|
|
|
|
|
return {};
|
2016-04-07 07:15:12 -07:00
|
|
|
|
}
|
2016-09-25 07:14:01 -07:00
|
|
|
|
})();
|
2015-10-23 09:44:10 -07:00
|
|
|
|
|
2016-08-16 01:28:21 -07:00
|
|
|
|
// If there is already an instance, activate the window in the existing instace and quit this one
|
2017-10-09 09:12:21 -07:00
|
|
|
|
if (app.makeSingleInstance((commandLine/*, workingDirectory*/) => {
|
|
|
|
|
// Protocol handler for win32
|
|
|
|
|
// argv: An array of the second instance’s (command line / deep linked) arguments
|
|
|
|
|
if (process.platform === 'win32') {
|
|
|
|
|
// Keep only command line / deep linked arguments
|
2017-10-09 14:33:02 -07:00
|
|
|
|
if (Array.isArray(commandLine.slice(1)) && commandLine.slice(1).length > 0) {
|
2017-10-25 05:05:17 -07:00
|
|
|
|
setDeeplinkingUrl(commandLine.slice(1)[0]);
|
|
|
|
|
mainWindow.webContents.send('protocol-deeplink', deeplinkingUrl);
|
2017-10-09 14:33:02 -07:00
|
|
|
|
}
|
2017-10-09 09:12:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
// Someone tried to run a second instance, we should focus our window.
|
|
|
|
|
if (mainWindow) {
|
|
|
|
|
if (mainWindow.isMinimized()) {
|
|
|
|
|
mainWindow.restore();
|
|
|
|
|
} else {
|
|
|
|
|
mainWindow.show();
|
2016-08-16 07:34:04 -07:00
|
|
|
|
}
|
2016-09-25 07:14:01 -07:00
|
|
|
|
}
|
|
|
|
|
})) {
|
2017-11-01 08:57:51 -07:00
|
|
|
|
app.exit();
|
2016-08-16 01:28:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-11 05:51:24 -07:00
|
|
|
|
function shouldShowTrayIcon() {
|
|
|
|
|
if (process.platform === 'win32') {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-05-07 13:21:07 -07:00
|
|
|
|
if (['darwin', 'linux'].includes(process.platform) && config.showTrayIcon === true) {
|
2016-04-11 05:51:24 -07:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-17 07:14:33 -08:00
|
|
|
|
function wasUpdated(lastAppVersion) {
|
|
|
|
|
return lastAppVersion !== app.getVersion();
|
2016-10-19 02:35:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearAppCache() {
|
2016-09-25 07:14:01 -07:00
|
|
|
|
if (mainWindow) {
|
2016-10-19 02:35:32 -07:00
|
|
|
|
console.log('Clear cache after update');
|
2016-09-25 07:14:01 -07:00
|
|
|
|
mainWindow.webContents.session.clearCache(() => {
|
2016-10-19 02:35:32 -07:00
|
|
|
|
//Restart after cache clear
|
|
|
|
|
mainWindow.reload();
|
|
|
|
|
});
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} else {
|
|
|
|
|
//Wait for mainWindow
|
|
|
|
|
setTimeout(clearAppCache, 100);
|
2016-10-19 02:35:32 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-23 09:44:10 -07:00
|
|
|
|
// Quit when all windows are closed.
|
2016-09-25 07:14:01 -07:00
|
|
|
|
app.on('window-all-closed', () => {
|
2015-10-23 09:44:10 -07:00
|
|
|
|
// On OS X 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();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2017-04-09 04:15:51 -07:00
|
|
|
|
function getValidWindowPosition(state, screen) {
|
|
|
|
|
// Check if the previous position is out of the viewable area
|
|
|
|
|
// (e.g. because the screen has been plugged off)
|
|
|
|
|
const displays = screen.getAllDisplays();
|
|
|
|
|
let minX = 0;
|
|
|
|
|
let maxX = 0;
|
|
|
|
|
let minY = 0;
|
|
|
|
|
let maxY = 0;
|
|
|
|
|
for (let i = 0; i < displays.length; i++) {
|
|
|
|
|
const display = displays[i];
|
|
|
|
|
maxX = Math.max(maxX, display.bounds.x + display.bounds.width);
|
|
|
|
|
maxY = Math.max(maxY, display.bounds.y + display.bounds.height);
|
|
|
|
|
minX = Math.min(minX, display.bounds.x);
|
|
|
|
|
minY = Math.min(minY, display.bounds.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (state.x > maxX || state.y > maxY || state.x < minX || state.y < minY) {
|
|
|
|
|
Reflect.deleteProperty(state, 'x');
|
|
|
|
|
Reflect.deleteProperty(state, 'y');
|
|
|
|
|
Reflect.deleteProperty(state, 'width');
|
|
|
|
|
Reflect.deleteProperty(state, 'height');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleScreenResize(screen, browserWindow) {
|
|
|
|
|
function handle() {
|
|
|
|
|
const position = browserWindow.getPosition();
|
|
|
|
|
const size = browserWindow.getSize();
|
|
|
|
|
const validPosition = getValidWindowPosition({
|
|
|
|
|
x: position[0],
|
|
|
|
|
y: position[1],
|
|
|
|
|
width: size[0],
|
2018-02-21 11:20:33 -08:00
|
|
|
|
height: size[1],
|
2017-04-09 04:15:51 -07:00
|
|
|
|
}, screen);
|
|
|
|
|
browserWindow.setPosition(validPosition.x || 0, validPosition.y || 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
browserWindow.on('restore', handle);
|
|
|
|
|
handle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app.on('browser-window-created', (e, newWindow) => {
|
|
|
|
|
// Screen cannot be required before app is ready
|
|
|
|
|
const {screen} = require('electron'); // eslint-disable-line global-require
|
|
|
|
|
handleScreenResize(screen, newWindow);
|
|
|
|
|
});
|
|
|
|
|
|
2015-10-23 09:44:10 -07:00
|
|
|
|
// For OSX, show hidden mainWindow when clicking dock icon.
|
2016-09-25 07:14:01 -07:00
|
|
|
|
app.on('activate', () => {
|
2015-10-23 09:44:10 -07:00
|
|
|
|
mainWindow.show();
|
|
|
|
|
});
|
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
app.on('before-quit', () => {
|
2016-07-04 00:19:41 -07:00
|
|
|
|
// Make sure tray icon gets removed if the user exits via CTRL-Q
|
|
|
|
|
if (process.platform === 'win32') {
|
|
|
|
|
trayIcon.destroy();
|
|
|
|
|
}
|
2017-03-18 08:07:29 -07:00
|
|
|
|
global.willAppQuit = true;
|
2015-10-23 09:44:10 -07:00
|
|
|
|
});
|
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
2016-03-06 04:58:52 -08:00
|
|
|
|
if (certificateStore.isTrusted(url, certificate)) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
callback(true);
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} else {
|
2016-03-06 04:58:52 -08:00
|
|
|
|
var detail = `URL: ${url}\nError: ${error}`;
|
|
|
|
|
if (certificateStore.isExisting(url)) {
|
2016-11-30 03:37:39 -08:00
|
|
|
|
detail = 'Certificate is different from previous one.\n\n' + detail;
|
2016-03-06 04:58:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-12 05:06:49 -07:00
|
|
|
|
dialog.showMessageBox(mainWindow, {
|
2016-03-06 04:58:52 -08:00
|
|
|
|
title: 'Certificate error',
|
|
|
|
|
message: `Do you trust certificate from "${certificate.issuerName}"?`,
|
2016-09-25 07:14:01 -07:00
|
|
|
|
detail,
|
2016-03-06 04:58:52 -08:00
|
|
|
|
type: 'warning',
|
|
|
|
|
buttons: [
|
|
|
|
|
'Yes',
|
2018-02-21 11:20:33 -08:00
|
|
|
|
'No',
|
2016-03-06 04:58:52 -08:00
|
|
|
|
],
|
2018-02-21 11:20:33 -08:00
|
|
|
|
cancelId: 1,
|
2016-09-25 07:14:01 -07:00
|
|
|
|
}, (response) => {
|
2016-03-06 04:58:52 -08:00
|
|
|
|
if (response === 0) {
|
|
|
|
|
certificateStore.add(url, certificate);
|
|
|
|
|
certificateStore.save();
|
|
|
|
|
webContents.loadURL(url);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
callback(false);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2017-11-08 06:23:13 -08:00
|
|
|
|
app.on('gpu-process-crashed', (event, killed) => {
|
|
|
|
|
console.log(`The GPU process has crached (killed = ${killed})`);
|
2017-10-16 08:54:56 -07:00
|
|
|
|
});
|
|
|
|
|
|
2016-04-21 06:43:18 -07:00
|
|
|
|
const loginCallbackMap = new Map();
|
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
ipcMain.on('login-credentials', (event, request, user, password) => {
|
2016-04-21 06:43:18 -07:00
|
|
|
|
const callback = loginCallbackMap.get(JSON.stringify(request));
|
|
|
|
|
if (callback != null) {
|
|
|
|
|
callback(user, password);
|
|
|
|
|
}
|
2016-08-29 14:40:11 -07:00
|
|
|
|
});
|
2016-04-21 06:43:18 -07:00
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
app.on('login', (event, webContents, request, authInfo, callback) => {
|
2016-04-21 06:43:18 -07:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
loginCallbackMap.set(JSON.stringify(request), callback);
|
|
|
|
|
mainWindow.webContents.send('login-request', request, authInfo);
|
|
|
|
|
});
|
|
|
|
|
|
2016-05-23 07:16:26 -07:00
|
|
|
|
allowProtocolDialog.init(mainWindow);
|
2016-05-21 21:39:52 -07:00
|
|
|
|
|
2017-04-27 06:45:32 -07:00
|
|
|
|
ipcMain.on('download-url', (event, URL) => {
|
|
|
|
|
downloadURL(mainWindow, URL, (err) => {
|
|
|
|
|
if (err) {
|
2017-04-27 07:33:20 -07:00
|
|
|
|
dialog.showMessageBox(mainWindow, {
|
|
|
|
|
type: 'error',
|
2018-02-21 11:20:33 -08:00
|
|
|
|
message: err.toString(),
|
2017-04-27 07:33:20 -07:00
|
|
|
|
});
|
2017-04-27 06:45:32 -07:00
|
|
|
|
console.log(err);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2017-10-24 05:22:39 -07:00
|
|
|
|
if (isDev) {
|
|
|
|
|
console.log('In development mode, deeplinking is disabled');
|
|
|
|
|
} else if (protocols && protocols[0] &&
|
2017-10-13 21:17:33 -07:00
|
|
|
|
protocols[0].schemes && protocols[0].schemes[0]
|
|
|
|
|
) {
|
|
|
|
|
scheme = protocols[0].schemes[0];
|
|
|
|
|
app.setAsDefaultProtocolClient(scheme);
|
|
|
|
|
}
|
2017-10-09 14:33:02 -07:00
|
|
|
|
|
2017-10-25 05:05:17 -07:00
|
|
|
|
function setDeeplinkingUrl(url) {
|
2017-10-13 21:17:33 -07:00
|
|
|
|
if (scheme) {
|
2017-10-25 05:05:17 -07:00
|
|
|
|
deeplinkingUrl = url.replace(new RegExp('^' + scheme), 'https');
|
2017-10-13 21:17:33 -07:00
|
|
|
|
}
|
2017-10-09 14:33:02 -07:00
|
|
|
|
}
|
2017-10-09 09:12:21 -07:00
|
|
|
|
|
2018-01-18 05:55:32 -08:00
|
|
|
|
app.on('will-finish-launching', () => {
|
|
|
|
|
// Protocol handler for osx
|
|
|
|
|
app.on('open-url', (event, url) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
setDeeplinkingUrl(url);
|
2018-01-19 07:38:42 -08:00
|
|
|
|
if (app.isReady()) {
|
|
|
|
|
function openDeepLink() {
|
|
|
|
|
try {
|
|
|
|
|
mainWindow.webContents.send('protocol-deeplink', deeplinkingUrl);
|
|
|
|
|
mainWindow.show();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
setTimeout(openDeepLink, 1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
openDeepLink();
|
2018-01-18 05:55:32 -08:00
|
|
|
|
}
|
|
|
|
|
});
|
2017-10-09 09:12:21 -07:00
|
|
|
|
});
|
|
|
|
|
|
2015-10-23 09:44:10 -07:00
|
|
|
|
// This method will be called when Electron has finished
|
|
|
|
|
// initialization and is ready to create browser windows.
|
2016-09-25 07:14:01 -07:00
|
|
|
|
app.on('ready', () => {
|
2017-03-18 08:07:29 -07:00
|
|
|
|
if (global.willAppQuit) {
|
2016-12-22 06:26:18 -08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2018-01-17 07:14:33 -08:00
|
|
|
|
|
|
|
|
|
const appStateJson = path.join(app.getPath('userData'), 'app-state.json');
|
|
|
|
|
appState = new AppStateManager(appStateJson);
|
|
|
|
|
if (wasUpdated(appState.lastAppVersion)) {
|
|
|
|
|
clearAppCache();
|
|
|
|
|
}
|
|
|
|
|
appState.lastAppVersion = app.getVersion();
|
|
|
|
|
|
2017-03-06 06:29:56 -08:00
|
|
|
|
if (global.isDev) {
|
|
|
|
|
installExtension.default(installExtension.REACT_DEVELOPER_TOOLS).
|
|
|
|
|
then((name) => console.log(`Added Extension: ${name}`)).
|
|
|
|
|
catch((err) => console.log('An error occurred: ', err));
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 09:12:21 -07:00
|
|
|
|
// Protocol handler for win32
|
|
|
|
|
if (process.platform === 'win32') {
|
2017-10-20 11:23:51 -07:00
|
|
|
|
// Keep only command line / deep linked argument. Make sure it's not squirrel command
|
|
|
|
|
const tmpArgs = process.argv.slice(1);
|
|
|
|
|
if (
|
|
|
|
|
Array.isArray(tmpArgs) && tmpArgs.length > 0 &&
|
|
|
|
|
tmpArgs[0].match(/^--squirrel-/) === null
|
|
|
|
|
) {
|
2017-10-25 05:05:17 -07:00
|
|
|
|
setDeeplinkingUrl(tmpArgs[0]);
|
2017-10-09 14:33:02 -07:00
|
|
|
|
}
|
2017-10-09 09:12:21 -07:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 08:07:29 -07:00
|
|
|
|
mainWindow = createMainWindow(config, {
|
|
|
|
|
hideOnStartup,
|
2017-10-09 09:12:21 -07:00
|
|
|
|
linuxAppIcon: path.join(assetsDir, 'appicon.png'),
|
2018-02-21 11:20:33 -08:00
|
|
|
|
deeplinkingUrl,
|
2017-03-18 08:07:29 -07:00
|
|
|
|
});
|
2017-10-09 14:33:02 -07:00
|
|
|
|
|
2017-03-18 08:07:29 -07:00
|
|
|
|
mainWindow.on('closed', () => {
|
|
|
|
|
// 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.
|
|
|
|
|
mainWindow = null;
|
|
|
|
|
});
|
2017-10-16 08:54:56 -07:00
|
|
|
|
criticalErrorHandler.setMainWindow(mainWindow);
|
|
|
|
|
mainWindow.on('unresponsive', criticalErrorHandler.windowUnresponsiveHandler.bind(criticalErrorHandler));
|
2017-03-18 08:07:29 -07:00
|
|
|
|
mainWindow.webContents.on('crashed', () => {
|
2017-10-16 08:54:56 -07:00
|
|
|
|
throw new Error('webContents \'crashed\' event has been emitted');
|
2017-03-18 08:07:29 -07:00
|
|
|
|
});
|
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
ipcMain.on('notified', () => {
|
2016-07-25 04:54:46 -07:00
|
|
|
|
if (process.platform === 'win32' || process.platform === 'linux') {
|
|
|
|
|
if (config.notifications.flashWindow === 2) {
|
|
|
|
|
mainWindow.flashFrame(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-09 06:01:47 -08:00
|
|
|
|
|
|
|
|
|
if (process.platform === 'darwin' && config.notifications.bounceIcon) {
|
|
|
|
|
app.dock.bounce(config.notifications.bounceIconType);
|
|
|
|
|
}
|
2016-07-25 04:54:46 -07:00
|
|
|
|
});
|
2016-08-12 11:49:43 -07:00
|
|
|
|
|
2016-09-25 07:14:01 -07:00
|
|
|
|
ipcMain.on('update-title', (event, arg) => {
|
2016-08-12 11:49:43 -07:00
|
|
|
|
mainWindow.setTitle(arg.title);
|
|
|
|
|
});
|
|
|
|
|
|
2016-04-11 05:51:24 -07:00
|
|
|
|
if (shouldShowTrayIcon()) {
|
2016-04-06 08:49:20 -07:00
|
|
|
|
// set up tray icon
|
2016-04-07 07:15:12 -07:00
|
|
|
|
trayIcon = new Tray(trayImages.normal);
|
2016-06-12 05:40:59 -07:00
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
|
trayIcon.setPressedImage(trayImages.clicked.normal);
|
2016-09-25 07:14:01 -07:00
|
|
|
|
systemPreferences.subscribeNotification('AppleInterfaceThemeChangedNotification', () => {
|
2016-06-12 05:40:59 -07:00
|
|
|
|
switchMenuIconImages(trayImages, systemPreferences.isDarkMode());
|
|
|
|
|
trayIcon.setImage(trayImages.normal);
|
|
|
|
|
});
|
|
|
|
|
}
|
2016-06-12 05:33:00 -07:00
|
|
|
|
|
2015-10-30 06:30:18 -07:00
|
|
|
|
trayIcon.setToolTip(app.getName());
|
2016-09-25 07:14:01 -07:00
|
|
|
|
trayIcon.on('click', () => {
|
2016-08-26 07:56:50 -07:00
|
|
|
|
if (!mainWindow.isVisible() || mainWindow.isMinimized()) {
|
2016-08-16 14:12:41 -07:00
|
|
|
|
if (mainWindow.isMinimized()) {
|
|
|
|
|
mainWindow.restore();
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} else {
|
2016-08-16 14:12:41 -07:00
|
|
|
|
mainWindow.show();
|
|
|
|
|
}
|
2016-07-05 09:37:18 -07:00
|
|
|
|
mainWindow.focus();
|
|
|
|
|
if (process.platform === 'darwin') {
|
2016-06-30 13:17:31 -07:00
|
|
|
|
app.dock.show();
|
|
|
|
|
}
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} else {
|
2016-07-05 09:37:18 -07:00
|
|
|
|
mainWindow.focus();
|
2016-06-30 13:17:31 -07:00
|
|
|
|
}
|
2015-11-06 06:39:44 -08:00
|
|
|
|
});
|
2016-06-30 13:17:31 -07:00
|
|
|
|
|
2016-05-23 07:46:24 -07:00
|
|
|
|
trayIcon.on('right-click', () => {
|
|
|
|
|
trayIcon.popUpContextMenu();
|
|
|
|
|
});
|
2016-09-25 07:14:01 -07:00
|
|
|
|
trayIcon.on('balloon-click', () => {
|
2016-07-03 05:58:48 -07:00
|
|
|
|
if (process.platform === 'win32' || process.platform === 'darwin') {
|
2016-09-25 07:14:01 -07:00
|
|
|
|
if (mainWindow.isMinimized()) {
|
|
|
|
|
mainWindow.restore();
|
|
|
|
|
} else {
|
|
|
|
|
mainWindow.show();
|
|
|
|
|
}
|
2016-06-27 00:06:20 -07:00
|
|
|
|
}
|
2016-07-03 05:58:48 -07:00
|
|
|
|
|
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
|
app.dock.show();
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-03 02:15:24 -08:00
|
|
|
|
mainWindow.focus();
|
|
|
|
|
});
|
2016-02-11 07:44:16 -08:00
|
|
|
|
|
|
|
|
|
// Set overlay icon from dataURL
|
2016-02-25 05:21:28 -08:00
|
|
|
|
// Set trayicon to show "dot"
|
2016-09-25 07:14:01 -07:00
|
|
|
|
ipcMain.on('update-unread', (event, arg) => {
|
2016-04-06 08:49:20 -07:00
|
|
|
|
if (process.platform === 'win32') {
|
2016-06-12 05:06:49 -07:00
|
|
|
|
const overlay = arg.overlayDataURL ? nativeImage.createFromDataURL(arg.overlayDataURL) : null;
|
2017-03-18 08:07:29 -07:00
|
|
|
|
if (mainWindow) {
|
|
|
|
|
mainWindow.setOverlayIcon(overlay, arg.description);
|
|
|
|
|
}
|
2016-04-06 08:49:20 -07:00
|
|
|
|
}
|
2016-02-25 05:21:28 -08:00
|
|
|
|
|
2017-10-20 06:08:47 -07:00
|
|
|
|
if (trayIcon && !trayIcon.isDestroyed()) {
|
2017-03-18 08:07:29 -07:00
|
|
|
|
if (arg.mentionCount > 0) {
|
|
|
|
|
trayIcon.setImage(trayImages.mention);
|
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
|
trayIcon.setPressedImage(trayImages.clicked.mention);
|
|
|
|
|
}
|
|
|
|
|
trayIcon.setToolTip(arg.mentionCount + ' unread mentions');
|
|
|
|
|
} else if (arg.unreadCount > 0) {
|
|
|
|
|
trayIcon.setImage(trayImages.unread);
|
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
|
trayIcon.setPressedImage(trayImages.clicked.unread);
|
|
|
|
|
}
|
|
|
|
|
trayIcon.setToolTip(arg.unreadCount + ' unread channels');
|
|
|
|
|
} else {
|
|
|
|
|
trayIcon.setImage(trayImages.normal);
|
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
|
trayIcon.setPressedImage(trayImages.clicked.normal);
|
|
|
|
|
}
|
|
|
|
|
trayIcon.setToolTip(app.getName());
|
2016-06-12 05:40:59 -07:00
|
|
|
|
}
|
2016-02-25 05:21:28 -08:00
|
|
|
|
}
|
2016-02-11 07:44:16 -08:00
|
|
|
|
});
|
2015-10-30 06:30:18 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-04 11:34:00 -07:00
|
|
|
|
if (process.platform === 'darwin') {
|
2016-09-25 07:14:01 -07:00
|
|
|
|
session.defaultSession.on('will-download', (event, item) => {
|
2016-10-04 11:34:00 -07:00
|
|
|
|
var filename = item.getFilename();
|
|
|
|
|
var savePath = dialog.showSaveDialog({
|
|
|
|
|
title: filename,
|
2018-02-21 11:20:33 -08:00
|
|
|
|
defaultPath: os.homedir() + '/Downloads/' + filename,
|
2016-10-04 11:34:00 -07:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (savePath) {
|
|
|
|
|
item.setSavePath(savePath);
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} else {
|
2016-10-04 11:34:00 -07:00
|
|
|
|
item.cancel();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 00:13:22 -07:00
|
|
|
|
// Set application menu
|
2016-09-25 07:14:01 -07:00
|
|
|
|
ipcMain.on('update-menu', (event, configData) => {
|
2017-03-06 05:00:21 -08:00
|
|
|
|
var aMenu = appMenu.createMenu(mainWindow, configData, global.isDev);
|
2016-09-25 07:14:01 -07:00
|
|
|
|
Menu.setApplicationMenu(aMenu);
|
|
|
|
|
|
2016-07-03 13:41:15 -07:00
|
|
|
|
// set up context menu for tray icon
|
|
|
|
|
if (shouldShowTrayIcon()) {
|
2017-03-06 05:00:21 -08:00
|
|
|
|
const tMenu = trayMenu.createMenu(mainWindow, configData, global.isDev);
|
2016-09-25 07:14:01 -07:00
|
|
|
|
trayIcon.setContextMenu(tMenu);
|
2016-09-29 02:34:01 -07:00
|
|
|
|
if (process.platform === 'darwin' || process.platform === 'linux') {
|
2016-07-03 13:41:15 -07:00
|
|
|
|
// store the information, if the tray was initialized, for checking in the settings, if the application
|
|
|
|
|
// was restarted after setting "Show icon on menu bar"
|
2016-09-25 07:14:01 -07:00
|
|
|
|
if (trayIcon) {
|
2016-07-03 13:41:15 -07:00
|
|
|
|
mainWindow.trayWasVisible = true;
|
2016-09-25 07:14:01 -07:00
|
|
|
|
} else {
|
2016-07-03 13:41:15 -07:00
|
|
|
|
mainWindow.trayWasVisible = false;
|
2016-09-25 07:14:01 -07:00
|
|
|
|
}
|
2016-07-03 13:41:15 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-05-21 00:13:22 -07:00
|
|
|
|
});
|
2016-06-12 05:06:49 -07:00
|
|
|
|
ipcMain.emit('update-menu', true, config);
|
2016-05-21 00:13:22 -07:00
|
|
|
|
|
2017-04-26 08:42:48 -07:00
|
|
|
|
ipcMain.on('update-dict', () => {
|
2017-04-20 05:32:34 -07:00
|
|
|
|
if (config.useSpellChecker) {
|
|
|
|
|
spellChecker = new SpellChecker(
|
2017-04-26 08:42:48 -07:00
|
|
|
|
config.spellCheckerLocale,
|
2017-04-20 05:32:34 -07:00
|
|
|
|
path.resolve(app.getAppPath(), 'node_modules/simple-spellchecker/dict'),
|
|
|
|
|
(err) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error(err);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
ipcMain.on('checkspell', (event, word) => {
|
|
|
|
|
let res = null;
|
|
|
|
|
if (config.useSpellChecker && spellChecker.isReady() && word !== null) {
|
|
|
|
|
res = spellChecker.spellCheck(word);
|
|
|
|
|
}
|
|
|
|
|
event.returnValue = res;
|
|
|
|
|
});
|
|
|
|
|
ipcMain.on('get-spelling-suggestions', (event, word) => {
|
|
|
|
|
if (config.useSpellChecker && spellChecker.isReady() && word !== null) {
|
|
|
|
|
event.returnValue = spellChecker.getSuggestions(word, 10);
|
|
|
|
|
} else {
|
|
|
|
|
event.returnValue = [];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
ipcMain.on('get-spellchecker-locale', (event) => {
|
|
|
|
|
event.returnValue = config.spellCheckerLocale;
|
|
|
|
|
});
|
2017-05-02 07:00:40 -07:00
|
|
|
|
ipcMain.on('reply-on-spellchecker-is-ready', (event) => {
|
2017-10-07 14:05:49 -07:00
|
|
|
|
if (!spellChecker) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-02 07:00:40 -07:00
|
|
|
|
if (spellChecker.isReady()) {
|
|
|
|
|
event.sender.send('spellchecker-is-ready');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
spellChecker.once('ready', () => {
|
|
|
|
|
event.sender.send('spellchecker-is-ready');
|
|
|
|
|
});
|
|
|
|
|
});
|
2017-04-26 08:42:48 -07:00
|
|
|
|
ipcMain.emit('update-dict');
|
2017-04-20 05:32:34 -07:00
|
|
|
|
|
2017-10-03 08:16:13 -07:00
|
|
|
|
const permissionFile = path.join(app.getPath('userData'), 'permission.json');
|
2017-12-04 06:52:49 -08:00
|
|
|
|
const trustedURLs = settings.mergeDefaultTeams(config.teams).map((team) => team.url);
|
|
|
|
|
permissionManager = new PermissionManager(permissionFile, trustedURLs);
|
|
|
|
|
session.defaultSession.setPermissionRequestHandler(permissionRequestHandler(mainWindow, permissionManager));
|
2017-10-03 08:16:13 -07:00
|
|
|
|
|
2015-10-23 09:44:10 -07:00
|
|
|
|
// Open the DevTools.
|
|
|
|
|
// mainWindow.openDevTools();
|
|
|
|
|
});
|