2017-11-22 21:10:34 +00:00
|
|
|
// @flow
|
2019-05-10 16:30:20 +00:00
|
|
|
import { checkIfRestartNeeded } from './main/squirrel-startup';
|
2020-04-27 20:42:57 +00:00
|
|
|
import { appConfig } from '../config';
|
2020-05-28 17:09:51 +00:00
|
|
|
import path from 'path';
|
2017-11-22 21:10:34 +00:00
|
|
|
import * as electron from 'electron';
|
2017-05-03 17:48:23 +00:00
|
|
|
import * as errorHandling from './main/error-handling';
|
|
|
|
import * as updates from './main/updates';
|
2017-05-24 16:25:22 +00:00
|
|
|
import * as windowUtils from './main/window-utils';
|
2017-11-17 12:10:37 +00:00
|
|
|
import * as models from './models/index';
|
|
|
|
import * as database from './common/database';
|
2020-04-26 20:33:39 +00:00
|
|
|
import { changelogUrl, getAppVersion, isDevelopment, isMac } from './common/constants';
|
2018-06-25 17:42:50 +00:00
|
|
|
import type { ToastNotification } from './ui/components/toast';
|
|
|
|
import type { Stats } from './models/stats';
|
2020-04-26 20:33:39 +00:00
|
|
|
import { trackNonInteractiveEventQueueable } from './common/analytics';
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2017-05-03 17:48:23 +00:00
|
|
|
// Handle potential auto-update
|
2019-05-10 16:30:20 +00:00
|
|
|
if (checkIfRestartNeeded()) {
|
2017-05-03 17:48:23 +00:00
|
|
|
process.exit(0);
|
|
|
|
}
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2018-06-25 17:42:50 +00:00
|
|
|
const { app, ipcMain, session } = electron;
|
2017-11-22 21:10:34 +00:00
|
|
|
const commandLineArgs = process.argv.slice(1);
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2020-05-28 17:09:51 +00:00
|
|
|
// Explicitly set userData folder from config because it's sketchy to
|
|
|
|
// rely on electron-builder to use productName, which could be changed
|
|
|
|
// by accident.
|
|
|
|
if (!isDevelopment()) {
|
|
|
|
const defaultPath = app.getPath('userData');
|
|
|
|
const newPath = path.join(defaultPath, '../', appConfig().userDataFolder);
|
|
|
|
app.setPath('userData', newPath);
|
|
|
|
}
|
|
|
|
|
2017-11-22 21:10:34 +00:00
|
|
|
// So if (window) checks don't throw
|
|
|
|
global.window = global.window || undefined;
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2017-11-22 21:10:34 +00:00
|
|
|
// When the app is first launched
|
|
|
|
app.on('ready', async () => {
|
|
|
|
// Init some important things first
|
|
|
|
await database.init(models.types());
|
|
|
|
await errorHandling.init();
|
2020-05-14 22:54:07 +00:00
|
|
|
|
2017-11-22 21:10:34 +00:00
|
|
|
await windowUtils.init();
|
|
|
|
|
|
|
|
// Init the app
|
|
|
|
await _trackStats();
|
|
|
|
await _launchApp();
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2017-11-22 21:10:34 +00:00
|
|
|
// Init the rest
|
|
|
|
await updates.init();
|
|
|
|
});
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2017-05-03 17:48:23 +00:00
|
|
|
// Set as default protocol
|
|
|
|
app.setAsDefaultProtocolClient(`insomnia${isDevelopment() ? 'dev' : ''}`);
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2018-06-25 17:42:50 +00:00
|
|
|
function _addUrlToOpen(e, url) {
|
2017-11-22 21:10:34 +00:00
|
|
|
e.preventDefault();
|
|
|
|
commandLineArgs.push(url);
|
|
|
|
}
|
|
|
|
|
|
|
|
app.on('open-url', _addUrlToOpen);
|
2016-12-01 18:48:49 +00:00
|
|
|
|
|
|
|
// Enable this for CSS grid layout :)
|
|
|
|
app.commandLine.appendSwitch('enable-experimental-web-platform-features');
|
|
|
|
|
|
|
|
// Quit when all windows are closed (except on Mac).
|
|
|
|
app.on('window-all-closed', () => {
|
2017-05-03 17:48:23 +00:00
|
|
|
if (!isMac()) {
|
2016-12-01 18:48:49 +00:00
|
|
|
app.quit();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Mac-only, when the user clicks the doc icon
|
|
|
|
app.on('activate', (e, hasVisibleWindows) => {
|
|
|
|
// Create a new window when clicking the doc icon if there isn't one open
|
|
|
|
if (!hasVisibleWindows) {
|
|
|
|
try {
|
2017-05-24 16:25:22 +00:00
|
|
|
windowUtils.createWindow();
|
2016-12-01 18:48:49 +00:00
|
|
|
} catch (e) {
|
|
|
|
// This might happen if 'ready' hasn't fired yet. So we're just going
|
|
|
|
// to silence these errors.
|
2017-11-18 22:47:54 +00:00
|
|
|
console.log('[main] App not ready to "activate" yet');
|
2016-12-01 18:48:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-06-25 17:42:50 +00:00
|
|
|
function _launchApp() {
|
2017-11-22 21:10:34 +00:00
|
|
|
app.removeListener('open-url', _addUrlToOpen);
|
2017-05-24 16:25:22 +00:00
|
|
|
const window = windowUtils.createWindow();
|
2016-12-01 18:48:49 +00:00
|
|
|
|
2017-05-03 17:48:23 +00:00
|
|
|
// Handle URLs sent via command line args
|
2017-11-22 21:10:34 +00:00
|
|
|
ipcMain.once('window-ready', () => {
|
|
|
|
commandLineArgs.length && window.send('run-command', commandLineArgs[0]);
|
2016-12-01 18:48:49 +00:00
|
|
|
});
|
|
|
|
|
2017-05-03 17:48:23 +00:00
|
|
|
// Called when second instance launched with args (Windows)
|
2019-04-18 00:50:03 +00:00
|
|
|
const gotTheLock = app.requestSingleInstanceLock();
|
|
|
|
|
|
|
|
if (!gotTheLock) {
|
|
|
|
console.error('[app] Failed to get instance lock');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
|
|
|
// Someone tried to run a second instance, we should focus our window.
|
|
|
|
if (window) {
|
|
|
|
if (window.isMinimized()) window.restore();
|
|
|
|
window.focus();
|
|
|
|
}
|
2016-12-01 18:48:49 +00:00
|
|
|
});
|
2016-12-01 20:22:43 +00:00
|
|
|
|
2017-05-03 17:48:23 +00:00
|
|
|
// Handle URLs when app already open
|
|
|
|
app.addListener('open-url', (e, url) => {
|
|
|
|
window.send('run-command', url);
|
|
|
|
// Apparently a timeout is needed because Chrome steals back focus immediately
|
|
|
|
// after opening the URL.
|
|
|
|
setTimeout(() => {
|
|
|
|
window.focus();
|
|
|
|
}, 100);
|
2016-12-01 18:48:49 +00:00
|
|
|
});
|
2017-08-01 22:03:12 +00:00
|
|
|
|
|
|
|
// Don't send origin header from Insomnia app because we're not technically using CORS
|
2017-11-20 16:07:36 +00:00
|
|
|
session.defaultSession.webRequest.onBeforeSendHeaders((details, fn) => {
|
2020-04-09 17:32:19 +00:00
|
|
|
delete details.requestHeaders.Origin;
|
2020-05-28 17:09:51 +00:00
|
|
|
fn({
|
|
|
|
cancel: false,
|
|
|
|
requestHeaders: details.requestHeaders,
|
|
|
|
});
|
2017-08-01 22:03:12 +00:00
|
|
|
});
|
2017-11-22 21:10:34 +00:00
|
|
|
}
|
|
|
|
|
2018-06-25 17:42:50 +00:00
|
|
|
async function _trackStats() {
|
2017-11-22 21:10:34 +00:00
|
|
|
// Handle the stats
|
|
|
|
const oldStats = await models.stats.get();
|
|
|
|
const stats: Stats = await models.stats.update({
|
|
|
|
currentLaunch: Date.now(),
|
|
|
|
lastLaunch: oldStats.currentLaunch,
|
|
|
|
currentVersion: getAppVersion(),
|
|
|
|
lastVersion: oldStats.currentVersion,
|
2018-12-12 17:36:11 +00:00
|
|
|
launches: oldStats.launches + 1,
|
2017-11-22 21:10:34 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// Update Stats Object
|
|
|
|
const firstLaunch = stats.launches === 1;
|
2018-10-17 16:42:33 +00:00
|
|
|
const justUpdated = !firstLaunch && stats.currentVersion !== stats.lastVersion;
|
2017-11-22 21:10:34 +00:00
|
|
|
|
2020-04-26 20:33:39 +00:00
|
|
|
if (firstLaunch) {
|
|
|
|
trackNonInteractiveEventQueueable('General', 'First Launch', stats.currentVersion);
|
|
|
|
} else if (justUpdated) {
|
|
|
|
trackNonInteractiveEventQueueable('General', 'Updated', stats.currentVersion);
|
|
|
|
} else {
|
|
|
|
trackNonInteractiveEventQueueable('General', 'Launched', stats.currentVersion);
|
|
|
|
}
|
|
|
|
|
2017-11-22 21:10:34 +00:00
|
|
|
ipcMain.once('window-ready', () => {
|
2018-06-25 17:42:50 +00:00
|
|
|
const { currentVersion } = stats;
|
2017-11-22 21:10:34 +00:00
|
|
|
if (!justUpdated || !currentVersion) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-06-25 17:42:50 +00:00
|
|
|
const { BrowserWindow } = electron;
|
2017-11-22 21:10:34 +00:00
|
|
|
const notification: ToastNotification = {
|
|
|
|
key: `updated-${currentVersion}`,
|
2020-04-26 20:33:39 +00:00
|
|
|
url: changelogUrl(),
|
2020-05-14 22:54:07 +00:00
|
|
|
cta: "See What's New",
|
2020-04-27 20:42:57 +00:00
|
|
|
email: appConfig().gravatarEmail,
|
2017-11-22 21:10:34 +00:00
|
|
|
message: `Updated to ${currentVersion}`,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Wait a bit before showing the user because the app just launched.
|
|
|
|
setTimeout(() => {
|
|
|
|
for (const window of BrowserWindow.getAllWindows()) {
|
|
|
|
window.send('show-notification', notification);
|
|
|
|
}
|
|
|
|
}, 5000);
|
|
|
|
});
|
|
|
|
}
|