From dd860e82ba0edce02caa1553a24de9639a40bd23 Mon Sep 17 00:00:00 2001 From: Jean Ouina Date: Thu, 6 Aug 2020 23:34:25 +0200 Subject: [PATCH] Sync with stable@0.0.307, I guess ? --- src/common/paths.ts | 112 ++++++------- src/index.ts | 208 ++++++++++++----------- src/singleInstance.ts | 106 ------------ src/splashScreen.ts | 381 +++++++++++++++++++++--------------------- 4 files changed, 361 insertions(+), 446 deletions(-) delete mode 100644 src/singleInstance.ts diff --git a/src/common/paths.ts b/src/common/paths.ts index 4ee383e..4b428c6 100644 --- a/src/common/paths.ts +++ b/src/common/paths.ts @@ -1,56 +1,56 @@ -import * as fs from "fs" -import * as path from "path" -import rimraf from "rimraf" -import { app } from "electron" - -// Determines environment-specific paths based on info provided -import originalFs from 'fs'; - -let userDataPath = null; -let resourcesPath = null; - -function determineAppUserDataRoot() { - return app.getPath('appData') -} - -function determineUserData(userDataRoot, buildInfo) { - return path.join(userDataRoot, 'Lightcord'); -} - -// cleans old version data in the background -export function cleanOldVersions(buildInfo) { - const entries = fs.readdirSync(userDataPath) || []; - entries.forEach(entry => { - const fullPath = path.join(userDataPath, entry); - if (fs.statSync(fullPath).isDirectory() && entry.indexOf(buildInfo.version) === -1) { - if (entry.match('^[0-9]+.[0-9]+.[0-9]+') != null) { - console.log('Removing old directory ', entry); - rimraf(fullPath, originalFs, error => { - if (error) { - console.warn('...failed with error: ', error); - } - }); - } - } - }); -} - -export function init(buildInfo) { - resourcesPath = path.join(require.main.filename, '..', '..', '..'); - - const userDataRoot = determineAppUserDataRoot(); - - userDataPath = determineUserData(userDataRoot, buildInfo); - - const { app } = require('electron'); - app.setPath('userData', userDataPath); - console.log(userDataPath, buildInfo.version) -} - -export function getUserData() { - return userDataPath; -} - -export function getResources() { - return resourcesPath; -} +import * as fs from "fs" +import * as path from "path" +import rimraf from "rimraf" +import { app } from "electron" + +// Determines environment-specific paths based on info provided +import originalFs from 'fs'; + +let userDataPath = null; +let resourcesPath = null; + +function determineAppUserDataRoot() { + return app.getPath('appData') +} + +function determineUserData(userDataRoot, buildInfo) { + return path.join(userDataRoot, 'Lightcord'); +} + +// cleans old version data in the background +export function cleanOldVersions(buildInfo) { + const entries = fs.readdirSync(userDataPath) || []; + entries.forEach(entry => { + const fullPath = path.join(userDataPath, entry); + if (fs.lstatSync(fullPath).isDirectory() && entry.indexOf(buildInfo.version) === -1) { + if (entry.match('^[0-9]+.[0-9]+.[0-9]+') != null) { + console.log('Removing old directory ', entry); + rimraf(fullPath, originalFs, error => { + if (error) { + console.warn('...failed with error: ', error); + } + }); + } + } + }); +} + +export function init(buildInfo) { + resourcesPath = path.join(require.main.filename, '..', '..', '..'); + + const userDataRoot = determineAppUserDataRoot(); + + userDataPath = determineUserData(userDataRoot, buildInfo); + + const { app } = require('electron'); + app.setPath('userData', userDataPath); + console.log(userDataPath, buildInfo.version) +} + +export function getUserData() { + return userDataPath; +} + +export function getResources() { + return resourcesPath; +} diff --git a/src/index.ts b/src/index.ts index dd2b0aa..8bb8f4e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,119 +1,141 @@ /** settings */ -import appSettings from "./appSettings" -let settings = appSettings.getSettings() +import appSettings from "./appSettings"; +let settings = appSettings.getSettings(); /** Glasstron */ -if(settings.get("GLASSTRON", true)){ - const glasstron = require("glasstron") - glasstron.init() +if (settings.get("GLASSTRON", true)) { + const glasstron = require("glasstron"); + glasstron.init(); } /** Modules */ -import * as electron from "electron" +import * as electron from "electron"; import requireNativeDiscordModule from "./requireNative"; -import autoStart from "./autoStart" -import * as buildInfo from "./buildInfo" -import * as Constants from "./Constants" -import * as GPUSettings from "./GPUSettings" -import * as moduleUpdater from "./common/moduleUpdater" -import * as paths from "./common/paths" -import { create } from "./singleInstance"; -import * as splashScreen from "./splashScreen" -import { join } from "path" -import { homedir } from "os" +import autoStart from "./autoStart"; +import * as buildInfo from "./buildInfo"; +import * as Constants from "./Constants"; +import * as GPUSettings from "./GPUSettings"; +import * as moduleUpdater from "./common/moduleUpdater"; +import * as paths from "./common/paths"; +import * as splashScreen from "./splashScreen"; +import { join } from "path"; +import { homedir } from "os"; -if (process.platform === 'linux') { - // Some people are reporting audio problems on Linux that are fixed by setting - // an environment variable PULSE_LATENCY_MSEC=30 -- the "real" fix is to see - // what conditions require this and set this then (also to set it directly in - // our webrtc setup code rather than here) but this should fix the bug for now. - if (process.env.PULSE_LATENCY_MSEC === undefined) { - process.env.PULSE_LATENCY_MSEC = "30"; - } +if (process.platform === "linux") { + // Some people are reporting audio problems on Linux that are fixed by setting + // an environment variable PULSE_LATENCY_MSEC=30 -- the "real" fix is to see + // what conditions require this and set this then (also to set it directly in + // our webrtc setup code rather than here) but this should fix the bug for now. + if (process.env.PULSE_LATENCY_MSEC === undefined) { + process.env.PULSE_LATENCY_MSEC = "30"; + } } -paths.init(buildInfo) -electron.app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required'); +paths.init(buildInfo); +electron.app.commandLine.appendSwitch( + "autoplay-policy", + "no-user-gesture-required" +); electron.app.commandLine.appendSwitch("no-force-async-hooks-checks"); function setupHardwareAcceleration() { - const settings = appSettings.getSettings(); - //@ts-ignore - const electronMajor = parseInt(process.versions.electron.split('.')[0]); - const allowed = process.env.DISCORD_ENABLE_HARDWARE_ACCELERATION || buildInfo.releaseChannel === 'development' || !(electronMajor === 7 && process.platform === 'darwin'); - // TODO: this is a copy of gpuSettings.getEnableHardwareAcceleration - if (!allowed || !settings.get('enableHardwareAcceleration', true)) { - electron.app.disableHardwareAcceleration(); - } + const settings = appSettings.getSettings(); + // TODO: this is a copy of gpuSettings.getEnableHardwareAcceleration + if (!settings.get("enableHardwareAcceleration", true)) { + electron.app.disableHardwareAcceleration(); + } } -global["releaseChannel"] = "stable" +electron.app.allowRendererProcessReuse = false; + +global["releaseChannel"] = "stable"; setupHardwareAcceleration(); function hasArgvFlag(flag) { - return (process.argv || []).slice(1).includes(flag); + return (process.argv || []).slice(1).includes(flag); } //Transform main thread into async -(async function Main(){ - await electron.app.whenReady() - - if(process.argv.includes("--should-create-shortcut")){ - console.log(`Creating shortcuts.`) - if(process.platform === "win32"){ - electron.shell.writeShortcutLink(join(homedir(), "Desktop", "Lightcord.lnk"), "create", { - "appUserModelId": Constants.APP_ID, - description: Constants.packageJSON.description, - target: process.execPath - }) - electron.shell.writeShortcutLink(join(electron.app.getPath("appData"), "Microsoft", "Windows", "Start Menu", "Programs", "Lightcord.lnk"), "create", { - "appUserModelId": Constants.APP_ID, - description: Constants.packageJSON.description, - target: process.execPath - }) - } - } +(async function Main() { + await electron.app.whenReady(); - console.log(`Initializing Lightcord.`) - console.log(`Version: ${buildInfo.version} + if (process.argv.includes("--should-create-shortcut")) { + console.log(`Creating shortcuts.`); + if (process.platform === "win32") { + electron.shell.writeShortcutLink( + join(homedir(), "Desktop", "Lightcord.lnk"), + "create", + { + appUserModelId: Constants.APP_ID, + description: Constants.packageJSON.description, + target: process.execPath, + } + ); + electron.shell.writeShortcutLink( + join( + electron.app.getPath("appData"), + "Microsoft", + "Windows", + "Start Menu", + "Programs", + "Lightcord.lnk" + ), + "create", + { + appUserModelId: Constants.APP_ID, + description: Constants.packageJSON.description, + target: process.execPath, + } + ); + } + } + + console.log(`Initializing Lightcord.`); + console.log(`Version: ${buildInfo.version} releaseChannel: ${buildInfo.releaseChannel} -commit: ${buildInfo.commit}`) +commit: ${buildInfo.commit}`); - if(!electron.app.commandLine.hasSwitch('enable-transparent-visuals'))electron.app.commandLine.appendSwitch('enable-transparent-visuals'); - electron.app.setAppUserModelId(Constants.APP_ID); - - let coreModule - create(() => { - const startMinimized = hasArgvFlag('--start-minimized'); - - coreModule = requireNativeDiscordModule('discord_desktop_core'); - coreModule.startup({ - paths, - splashScreen, - moduleUpdater, - autoStart, - buildInfo, - appSettings, - Constants, - GPUSettings - }); - - coreModule.setMainWindowVisible(!startMinimized) - }, (args) => { - if(args && args.length > 0){ - if(args.length > 0 && args[0] === '--squirrel-uninstall') { - electron.app.quit(); - return; - } + if (!electron.app.commandLine.hasSwitch("enable-transparent-visuals"))electron.app.commandLine.appendSwitch("enable-transparent-visuals"); + electron.app.setAppUserModelId(Constants.APP_ID); - if(args && args.length === 1 && args[0] === "--overlay-host"){ // this is a patch for Lightcord that focus itself - //console.warn("OVERLAY HOST DÉTECTÉ. EVENNEMENT IGNORÉ MAIS POURRAIT CAUSER UN PROBLÈME.") - return - } - } - if (coreModule) { - coreModule.handleSingleInstance(args); - } - }) -})() \ No newline at end of file + + let coreModule; + + const isFirstInstance = electron.app.requestSingleInstanceLock(); + const allowMultipleInstances = hasArgvFlag("--multi-instance"); + if (!isFirstInstance && !allowMultipleInstances) { + electron.app.quit(); + return + } + + if (!allowMultipleInstances) { + electron.app.on("second-instance", (_event, args, _workingDirectory) => { + if(args && args[0] === "--overlay-host"){ + // this is a patch for Lightcord that focus itself when the user is playing a game. + //console.warn("OVERLAY HOST DÉTECTÉ. EVENNEMENT IGNORÉ MAIS POURRAIT CAUSER UN PROBLÈME.") + return; + } + + if (coreModule) { + coreModule.handleSingleInstance(args); + } + }); + } + + const startMinimized = hasArgvFlag("--start-minimized"); + + coreModule = requireNativeDiscordModule("discord_desktop_core"); + coreModule.startup({ + paths, + splashScreen, + moduleUpdater, + autoStart, + buildInfo, + appSettings, + Constants, + GPUSettings, + }); + + coreModule.setMainWindowVisible(!startMinimized); +})(); diff --git a/src/singleInstance.ts b/src/singleInstance.ts deleted file mode 100644 index 7908b11..0000000 --- a/src/singleInstance.ts +++ /dev/null @@ -1,106 +0,0 @@ -import * as electron from "electron" -import * as net from "net" -import * as path from "path" -import * as fs from "fs" -import * as os from "os" -import * as buildinfo from "./buildInfo" - -function deleteSocketFile(socketPath) { - if (process.platform === 'win32') { - return; - } - - if (fs.existsSync(socketPath)) { - try { - fs.unlinkSync(socketPath); - } catch (error) { - // Ignore ENOENT errors in case the file was deleted between the exists - // check and the call to unlink sync. This occurred occasionally on CI - // which is why this check is here. - if (error.code !== 'ENOENT') { - throw error; - } - } - } -} - -/** - * Creates server to listen for additional atom application launches. - * - * You can run the command multiple times, but after the first launch - * the other launches will just pass their information to this server and then - * close immediately. - */ -function listenForArgumentsFromNewProcess(socketPath, callback) { - deleteSocketFile(socketPath); - - const server = net.createServer(connection => { - connection.on('data', data => { - const args = JSON.parse(data.toString()); - callback(args); - }); - }); - server.listen(socketPath); - server.on('error', error => console.error('Application server failed', error)); - return server; -} - -function tryStart(socketPath, callback, otherAppFound) { - // FIXME: Sometimes when socketPath doesn't exist, net.connect would strangely - // take a few seconds to trigger 'error' event, it could be a bug of node - // or atom-shell, before it's fixed we check the existence of socketPath to - // speedup startup. - if (process.platform !== 'win32' && !fs.existsSync(socketPath)) { - callback(); - return; - } - - const client = net.connect({ path: socketPath }, () => { - client.write(JSON.stringify(process.argv.slice(1)), () => { - client.end(); - otherAppFound(); - }); - }); - client.on('error', callback); -} - -function makeSocketPath() { - let name = electron.app.name ? electron.app.name : electron.app.getName(); - if (buildinfo.releaseChannel !== 'stable') { - name += buildinfo.releaseChannel; - } - - if (process.platform === 'win32') { - return '\\\\.\\pipe\\' + name + '-sock'; - } else { - return path.join(os.tmpdir(), name + '.sock'); - } -} - -export function create(startCallback, newProcessCallback) { - const socketPath = makeSocketPath(); - - tryStart(socketPath, () => { - const server = listenForArgumentsFromNewProcess(socketPath, newProcessCallback); - - electron.app.on('will-quit', () => { - server.close(); - deleteSocketFile(socketPath); - }); - - //@ts-ignore - electron.app.on('will-exit', () => { - server.close(); - deleteSocketFile(socketPath); - }); - - startCallback(); - }, () => { - console.log('Another instance exists. Quitting.'); - electron.app.exit(0); - }); -} - -export function pipeCommandLineArgs(noOtherAppFoundCallback, otherAppFound) { - tryStart(makeSocketPath(), noOtherAppFoundCallback, otherAppFound); -} \ No newline at end of file diff --git a/src/splashScreen.ts b/src/splashScreen.ts index 669c803..1474d46 100644 --- a/src/splashScreen.ts +++ b/src/splashScreen.ts @@ -1,192 +1,191 @@ -import * as electron from "electron" -import {EventEmitter} from "events" -import * as fs from "fs" -import * as path from "path" -import * as url from "url" -import * as moduleUpdater from "./common/moduleUpdater" -import * as paths from "./common/paths" -import * as ipcMain from "./ipcMain" - -// citron note: atom seems to add about 50px height to the frame on mac but not windows -// TODO: see if we can eliminate fudge by using useContentSize BrowserWindow option -const LOADING_WINDOW_WIDTH = 300; -const LOADING_WINDOW_HEIGHT = process.platform == 'darwin' ? 300 : 350; - -// TODO: addModulesListener events should use Module's constants -const UPDATE_CHECK_FINISHED = 'update-check-finished'; -const LAUNCHING = 'launching'; - -export const APP_SHOULD_LAUNCH = 'APP_SHOULD_LAUNCH'; -export const APP_SHOULD_SHOW = 'APP_SHOULD_SHOW'; - -export const events = new EventEmitter(); - -function webContentsSend(win, event, ...args) { - if(event === "SPLASH_UPDATE_STATE")lastStatus = args[0].status - if (win != null && win.webContents != null) { - win.webContents.send(`DISCORD_${event}`, ...args); - } -} - -let splashWindow:electron.BrowserWindow; -let modulesListeners; -let splashState; -let launchedMainWindow; -let quoteCachePath; -let lastStatus - -export function setSplashState(state:any){ - splashState = state - if (splashWindow != null && !splashWindow.isDestroyed() && !splashWindow.webContents.isDestroyed()) { - webContentsSend(splashWindow, 'SPLASH_UPDATE_STATE', Object.assign({ status: lastStatus }, splashState)); - } -} - -export function launchMainWindow(){ - launchMainWindowInternal(); - updateSplashState(LAUNCHING); -} - -export function initSplash(startMinimized = false) { - modulesListeners = {}; - splashState = {}; - launchedMainWindow = false; -/* - addModulesListener(UPDATE_CHECK_FINISHED, ({ succeeded, updateCount, manualRequired }) => { - launchMainWindow(); - updateSplashState(LAUNCHING); - });*/ - - launchSplashWindow(startMinimized); - - quoteCachePath = path.join(paths.getUserData(), 'quotes.json'); - ipcMain.default.on('UPDATED_QUOTES', (_event, quotes) => cacheLatestQuotes(quotes)); -} - -function destroySplash() { - if (splashWindow) { - splashWindow.setSkipTaskbar(true); - // defer the window hiding for a short moment so it gets covered by the main window - const _nukeWindow = () => { - splashWindow.hide(); - splashWindow.close(); - splashWindow = null; - }; - setTimeout(_nukeWindow, 100); - } -} - -function addModulesListener(event, listener) { - modulesListeners[event] = listener; - moduleUpdater.events.addListener(event, listener); -} - -function removeModulesListeners() { - for (const event of Object.keys(modulesListeners)) { - moduleUpdater.events.removeListener(event, modulesListeners[event]); - } -} -export function updateSplashState(event) { - if (splashWindow != null && !splashWindow.isDestroyed() && !splashWindow.webContents.isDestroyed()) { - webContentsSend(splashWindow, 'SPLASH_UPDATE_STATE', Object.assign({ status: event }, splashState)); - } -} - -function launchSplashWindow(startMinimized = false) { - const windowConfig = { - width: LOADING_WINDOW_WIDTH, - height: LOADING_WINDOW_HEIGHT, - transparent: false, - frame: false, - resizable: false, - center: true, - show: false, - webPreferences: { - nodeIntegration: true, - - }, - icon: path.join(__dirname, "..", "discord.png") - }; - - splashWindow = new electron.BrowserWindow(windowConfig); - - splashWindow.webContents.session.protocol.interceptFileProtocol('http', (request, callback) => { - callback(path.join(__dirname, '..', "splash", request.url.replace('http://localhost/', ''))); - }); - - // prevent users from dropping links to navigate in splash window - splashWindow.webContents.on('will-navigate', e => e.preventDefault()); - - splashWindow.webContents.on('new-window', (e, windowURL) => { - e.preventDefault(); - electron.shell.openExternal(windowURL); - // exit, but delay half a second because openExternal is about to fire - // some events to things that are freed by app.quit. - setTimeout(electron.app.quit, 500); - }); - - if (process.platform !== 'darwin') { - // citron note: this causes a crash on quit while the window is open on osx - splashWindow.on('closed', () => { - splashWindow = null; - if (!launchedMainWindow) { - // user has closed this window before we launched the app, so let's quit - electron.app.quit(); - } - }); - } - - ipcMain.default.on('SPLASH_SCREEN_READY', () => { - const cachedQuote = chooseCachedQuote(); - if (cachedQuote) { - webContentsSend(splashWindow, 'SPLASH_SCREEN_QUOTE', cachedQuote); - } - - if (splashWindow && !startMinimized) { - splashWindow.show(); - } - - moduleUpdater.installPendingUpdates(); - - events.emit("SPLASH_SCREEN_READY") - }); - ipcMain.default.on('LAUNCH_ANYWAY', () => { - launchMainWindowInternal() - }); - - splashWindow.loadURL("http://localhost/index.html"); -} - -function launchMainWindowInternal() { - removeModulesListeners(); - if (!launchedMainWindow && splashWindow != null) { - launchedMainWindow = true; - events.emit(APP_SHOULD_LAUNCH); - } -} - -function scheduleUpdateCheck() {} - -export function focusWindow() { - if (splashWindow != null) { - splashWindow.focus(); - } -} - -export function pageReady() { - destroySplash(); - process.nextTick(() => events.emit(APP_SHOULD_SHOW)); -} - -function cacheLatestQuotes(quotes) { - fs.writeFile(quoteCachePath, JSON.stringify(quotes), e => { - if (e) { - console.warn('Failed updating quote cache with error: ', e); - } - }); -} - -function chooseCachedQuote() { - let cachedQuote = "Launching..."; - return cachedQuote; +import * as electron from "electron" +import {EventEmitter} from "events" +import * as fs from "fs" +import * as path from "path" +import * as moduleUpdater from "./common/moduleUpdater" +import * as paths from "./common/paths" +import * as ipcMain from "./ipcMain" + +// citron note: atom seems to add about 50px height to the frame on mac but not windows +// TODO: see if we can eliminate fudge by using useContentSize BrowserWindow option +const LOADING_WINDOW_WIDTH = 300; +const LOADING_WINDOW_HEIGHT = process.platform === 'darwin' ? 300 : 350; + +// TODO: addModulesListener events should use Module's constants +const UPDATE_CHECK_FINISHED = 'update-check-finished'; +const LAUNCHING = 'launching'; + +export const APP_SHOULD_LAUNCH = 'APP_SHOULD_LAUNCH'; +export const APP_SHOULD_SHOW = 'APP_SHOULD_SHOW'; + +export const events = new EventEmitter(); + +function webContentsSend(win, event, ...args) { + if(event === "SPLASH_UPDATE_STATE")lastStatus = args[0].status + if (win != null && win.webContents != null) { + win.webContents.send(`DISCORD_${event}`, ...args); + } +} + +let splashWindow:electron.BrowserWindow; +let modulesListeners; +let splashState; +let launchedMainWindow; +let quoteCachePath; +let lastStatus + +export function setSplashState(state:any){ + splashState = state + if (splashWindow != null && !splashWindow.isDestroyed() && !splashWindow.webContents.isDestroyed()) { + webContentsSend(splashWindow, 'SPLASH_UPDATE_STATE', Object.assign({ status: lastStatus }, splashState)); + } +} + +export function launchMainWindow(){ + launchMainWindowInternal(); + updateSplashState(LAUNCHING); +} + +export function initSplash(startMinimized = false) { + modulesListeners = {}; + splashState = {}; + launchedMainWindow = false; +/* + addModulesListener(UPDATE_CHECK_FINISHED, ({ succeeded, updateCount, manualRequired }) => { + launchMainWindow(); + updateSplashState(LAUNCHING); + });*/ + + launchSplashWindow(startMinimized); + + quoteCachePath = path.join(paths.getUserData(), 'quotes.json'); + ipcMain.default.on('UPDATED_QUOTES', (_event, quotes) => cacheLatestQuotes(quotes)); +} + +function destroySplash() { + if (splashWindow) { + splashWindow.setSkipTaskbar(true); + // defer the window hiding for a short moment so it gets covered by the main window + const _nukeWindow = () => { + splashWindow.hide(); + splashWindow.close(); + splashWindow = null; + }; + setTimeout(_nukeWindow, 100); + } +} + +function addModulesListener(event, listener) { + modulesListeners[event] = listener; + moduleUpdater.events.addListener(event, listener); +} + +function removeModulesListeners() { + for (const event of Object.keys(modulesListeners)) { + moduleUpdater.events.removeListener(event, modulesListeners[event]); + } +} +export function updateSplashState(event) { + if (splashWindow != null && !splashWindow.isDestroyed() && !splashWindow.webContents.isDestroyed()) { + webContentsSend(splashWindow, 'SPLASH_UPDATE_STATE', Object.assign({ status: event }, splashState)); + } +} + +function launchSplashWindow(startMinimized = false) { + const windowConfig = { + width: LOADING_WINDOW_WIDTH, + height: LOADING_WINDOW_HEIGHT, + transparent: false, + frame: false, + resizable: false, + center: true, + show: false, + webPreferences: { + nodeIntegration: true, + enableRemoteModule: true + }, + icon: path.join(__dirname, "..", "discord.png") + }; + + splashWindow = new electron.BrowserWindow(windowConfig); + + splashWindow.webContents.session.protocol.interceptFileProtocol('http', (request, callback) => { + callback(path.join(__dirname, '..', "splash", request.url.replace('http://localhost/', ''))); + }); + + // prevent users from dropping links to navigate in splash window + splashWindow.webContents.on('will-navigate', e => e.preventDefault()); + + splashWindow.webContents.on('new-window', (e, windowURL) => { + e.preventDefault(); + electron.shell.openExternal(windowURL); + // exit, but delay half a second because openExternal is about to fire + // some events to things that are freed by app.quit. + setTimeout(electron.app.quit, 500); + }); + + if (process.platform !== 'darwin') { + // citron note: this causes a crash on quit while the window is open on osx + splashWindow.on('closed', () => { + splashWindow = null; + if (!launchedMainWindow) { + // user has closed this window before we launched the app, so let's quit + electron.app.quit(); + } + }); + } + + ipcMain.default.on('SPLASH_SCREEN_READY', () => { + const cachedQuote = chooseCachedQuote(); + if (cachedQuote) { + webContentsSend(splashWindow, 'SPLASH_SCREEN_QUOTE', cachedQuote); + } + + if (splashWindow && !startMinimized) { + splashWindow.show(); + } + + moduleUpdater.installPendingUpdates(); + + events.emit("SPLASH_SCREEN_READY") + }); + ipcMain.default.on('LAUNCH_ANYWAY', () => { + launchMainWindowInternal() + }); + + splashWindow.loadURL("http://localhost/index.html"); +} + +function launchMainWindowInternal() { + removeModulesListeners(); + if (!launchedMainWindow && splashWindow != null) { + launchedMainWindow = true; + events.emit(APP_SHOULD_LAUNCH); + } +} + +function scheduleUpdateCheck() {} + +export function focusWindow() { + if (splashWindow != null) { + splashWindow.focus(); + } +} + +export function pageReady() { + destroySplash(); + process.nextTick(() => events.emit(APP_SHOULD_SHOW)); +} + +function cacheLatestQuotes(quotes) { + fs.writeFile(quoteCachePath, JSON.stringify(quotes), e => { + if (e) { + console.warn('Failed updating quote cache with error: ', e); + } + }); +} + +function chooseCachedQuote() { + let cachedQuote = "Launching..."; + return cachedQuote; } \ No newline at end of file