From ef57e28dab86c4ff4ec3ff5910a2bd3303eda6c7 Mon Sep 17 00:00:00 2001 From: William Petit Date: Mon, 24 Jul 2017 14:58:05 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9marrage=20des=20applications=20en=20mode?= =?UTF-8?q?=20daemon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les applications sont désormais lancées en mode "détachées". Une limite "dure" de 2 secondes est appliquées pour l'animation de lancement sur les tuiles. Fixes #5 --- src/components/launcher/launcher-view.js | 10 +++- src/store/actions/launcher.js | 11 ++++- src/util/system.js | 63 +++++++++++++++++++++--- 3 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/components/launcher/launcher-view.js b/src/components/launcher/launcher-view.js index 2530f9d..85b277b 100644 --- a/src/components/launcher/launcher-view.js +++ b/src/components/launcher/launcher-view.js @@ -104,10 +104,16 @@ var LauncherView = React.createClass({ var el = evt.currentTarget; el.classList.add('pulse'); - + let startAnim = Date.now(); + let endAnim = startAnim + 2000; this.props.dispatch(actions.launcher.runApp(item.exec)) .then(function() { - el.classList.remove('pulse'); + let now = Date.now(); + if(endAnim > now) { + setTimeout(() => el.classList.remove('pulse'), endAnim - now) + } else { + el.classList.remove('pulse') + } }) .catch(function() { el.classList.remove('pulse'); diff --git a/src/store/actions/launcher.js b/src/store/actions/launcher.js index 36e17ba..4a0437b 100644 --- a/src/store/actions/launcher.js +++ b/src/store/actions/launcher.js @@ -1,6 +1,7 @@ var Util = require('../../util'); var logger = Util.Logger; -var remote = require('electron').Remote; +var LoggerStream = Util.LoggerStream; +var remote = require('electron').remote; var RUN_APP = exports.RUN_APP = 'RUN_APP'; var RUN_APP_SUCCESS = exports.RUN_APP_SUCCESS = 'RUN_APP_SUCCESS'; @@ -14,7 +15,13 @@ exports.runApp = function(execPath) { dispatch({ type: RUN_APP, execPath: execPath }); - return Util.System.runApp(execPath, { clearFreeDesktopFlags: true }) + var opts = { + clearFreeDesktopFlags: true, + stdout: process.stdout, + stderr: process.stderr + } + + return Util.System.runApp(execPath, opts) .then(function() { dispatch({ type: RUN_APP_SUCCESS, execPath: execPath }); // Hypothetical fix diff --git a/src/util/system.js b/src/util/system.js index ef41c27..d14a36a 100644 --- a/src/util/system.js +++ b/src/util/system.js @@ -98,15 +98,64 @@ exports.runApp = function(execPath, opts) { opts = opts || {}; - if(opts.clearFreeDesktopFlags) { - execPath = exports.clearFreeDesktopFlags(execPath); - } - return new Promise(function(resolve, reject) { - cp.exec(execPath, function(err) { - if(err) return reject(err); - return resolve(); + try { + + if(opts.clearFreeDesktopFlags) { + execPath = exports.clearFreeDesktopFlags(execPath); + } + + var isDev = process.env.NODE_ENV === 'development'; + + var child = cp.spawn(execPath, { + detached: true, + shell: true, + stdio: [ + 'ignore', + isDev ? process.stdout : 'ignore', + isDev ? process.stderr : 'ignore' + ] + }); + + // Detach the child process + child.unref(); + + } catch(err) { + return reject(err); + } + + // Execute the rest after all I/O operations in this tick + let immediateId = setImmediate(() => { + + // We do not want to be notified of child events after launch + child.removeAllListeners(); + + try { + // Check if the child process is still alive, should throw otherwise + child.kill(0); + } catch(err) { + return reject(err); + } + + return resolve(child); + }); + + // If the child process exit with an exit code != 0, reject the promise + child.once('close', code => { + if(code === 0) return; + clearImmediate(immediateId); + child.removeAllListeners(); + return reject(`Program exited with a exit code "${code}"`); + }); + + // If an error occurs during the process launch, reject the promise + child.once('error', err => { + clearImmediate(immediateId); + child.removeAllListeners(); + return reject(err); + }); + }); };