electron-113: implemented changes as per the use cases defined in the ticket

This commit is contained in:
Vishwas Shashidhar
2017-08-18 17:59:03 +05:30
parent 0d859de70f
commit d4807279f6
4 changed files with 289 additions and 181 deletions

View File

@@ -9,6 +9,12 @@ const isMac = require('./utils/misc.js').isMac;
const getRegistry = require('./utils/getRegistry.js');
const configFileName = 'Symphony.config';
// For modifying user config while installation
const pick = require('lodash.pick');
const childProcess = require('child_process');
const AppDirectory = require('appdirectory');
const dirs = new AppDirectory('Symphony');
// cached config when first reading files. initially undefined and will be
// updated when read from disk.
let userConfig;
@@ -29,13 +35,13 @@ let globalConfig;
*/
function getConfigField(fieldName) {
return getUserConfigField(fieldName)
.then(function(value) {
// got value from user config
return value;
}, function () {
// failed to get value from user config, so try global config
return getGlobalConfigField(fieldName);
});
.then(function(value) {
// got value from user config
return value;
}, function() {
// failed to get value from user config, so try global config
return getGlobalConfigField(fieldName);
});
}
function getUserConfigField(fieldName) {
@@ -124,12 +130,12 @@ function readGlobalConfig() {
reject('can not parse config file data: ' + data + ', error: ' + err);
}
getRegistry('PodUrl')
.then(function(url) {
globalConfig.url = url;
resolve(globalConfig);
}).catch(function () {
resolve(globalConfig);
});
.then(function(url) {
globalConfig.url = url;
resolve(globalConfig);
}).catch(function() {
resolve(globalConfig);
});
}
});
});
@@ -143,17 +149,17 @@ function readGlobalConfig() {
*/
function updateConfigField(fieldName, newValue) {
return readUserConfig()
.then(function(config) {
return saveUserConfig(fieldName, newValue, config);
},
function() {
// in case config doesn't exist, can't read or is corrupted.
// add configVersion - just in case in future we need to provide
// upgrade capabilities.
return saveUserConfig(fieldName, newValue, {
configVersion: '1.0.0'
});
});
.then(function(config) {
return saveUserConfig(fieldName, newValue, config);
},
function() {
// in case config doesn't exist, can't read or is corrupted.
// add configVersion - just in case in future we need to provide
// upgrade capabilities.
return saveUserConfig(fieldName, newValue, {
configVersion: '1.0.0'
});
});
}
function saveUserConfig(fieldName, newValue, oldConfig) {
@@ -182,6 +188,136 @@ function saveUserConfig(fieldName, newValue, oldConfig) {
});
}
/**
* Method to update multiple user config field
* @param {Object} newGlobalConfig - The latest config changes from installer
* @param {Object} oldUserConfig - The old user config data
* @returns {Promise}
*/
function updateUserConfig(newGlobalConfig, oldUserConfig) {
return new Promise((resolve, reject) => {
// Picking some values from global config to overwrite user config
const configDataToUpdate = pick(newGlobalConfig, ['url', 'minimizeOnClose', 'launchOnStartup', 'alwaysOnTop']);
const updatedUserConfigData = Object.assign(oldUserConfig, configDataToUpdate);
const jsonNewConfig = JSON.stringify(updatedUserConfigData, null, ' ');
// get user config path
let userConfigFile;
if (isMac) {
userConfigFile = path.join(dirs.userConfig(), configFileName);
} else {
userConfigFile = path.join(app.getPath('userData'), configFileName);
}
fs.writeFile(userConfigFile, jsonNewConfig, 'utf8', (err) => {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
/**
* Method to overwrite user config on windows installer
* @param {String} perUserInstall - Is a flag to determine whether we are installing for per user
* @returns {Promise}
*/
function updateUserConfigWin(perUserInstall) {
return new Promise((resolve, reject) => {
const userConfigFile = path.join(app.getPath('userData'), configFileName);
if (!perUserInstall) {
reject();
return;
}
// if user config file does't exists just copy global config file
if (!fs.existsSync(userConfigFile)) {
const globalConfigFileName = path.join('config', configFileName);
const execPath = path.dirname(app.getPath('exe'));
const globalConfigPath = path.join(execPath, '', globalConfigFileName);
const userConfigPath = app.getPath('userData');
childProcess.exec(`echo D|xcopy /y /e /s /c "${globalConfigPath}" "${userConfigPath}"`, { timeout: 60000 }, (err) => {
if (err) {
reject(err);
return;
}
resolve();
});
}
readGlobalConfig().then((globalConfigData) => {
fs.readFile(userConfigFile, 'utf8', (err, userData) => {
if (err) {
reject('cannot open user config file: ' + userConfigFile + ', error: ' + err);
return;
}
let userConfigData;
try {
// data is the contents of the text file we just read
userConfigData = JSON.parse(userData);
} catch (e) {
reject('can not parse config file data: ' + userData + ', error: ' + err);
}
updateUserConfig(globalConfigData, userConfigData).then((error) => {
if (error) {
reject(error);
return;
}
resolve();
});
});
});
});
}
/**
* Method to overwrite user config on mac installer
* @param {String} globalConfigPath - The global config path from installer
* @returns {Promise}
*/
function updateUserConfigMac(globalConfigPath) {
return new Promise((resolve, reject) => {
const userConfigFile = path.join(dirs.userConfig(), configFileName);
// if user config file does't exists just copy global config file
if (!fs.existsSync(userConfigFile)) {
let userConfigPath = dirs.userConfig() + '/';
let userName = process.env.USER;
childProcess.exec(`rsync -r "${globalConfigPath}" "${userConfigPath}" && chown -R "${userName}" "${userConfigPath}"`, { timeout: 60000 }, (err) => {
if (err) {
reject(err);
}
resolve();
});
}
return readGlobalConfig().then((globalConfigData) => {
fs.readFile(userConfigFile, 'utf8', (err, userData) => {
if (err) {
reject('cannot open user config file: ' + userConfigFile + ', error: ' + err);
}
let userConfigData;
try {
// data is the contents of the text file we just read
userConfigData = JSON.parse(userData);
} catch (e) {
reject('can not parse config file data: ' + userData + ', error: ' + err);
}
updateUserConfig(globalConfigData, userConfigData).then((error) => {
if (error) {
reject(error);
return;
}
resolve();
});
});
});
});
}
function clearCachedConfigs() {
userConfig = null;
globalConfig = null;
@@ -191,8 +327,10 @@ module.exports = {
getConfigField,
updateConfigField,
configFileName,
updateUserConfigWin,
updateUserConfigMac,
// items below here are only exported for testing, do NOT use!
saveUserConfig,
clearCachedConfigs
};
};

View File

@@ -6,14 +6,10 @@ const nodeURL = require('url');
const squirrelStartup = require('electron-squirrel-startup');
const AutoLaunch = require('auto-launch');
const urlParser = require('url');
const { getConfigField } = require('./config.js');
const { getConfigField, updateUserConfigWin, updateUserConfigMac } = require('./config.js');
const { isMac, isDevEnv } = require('./utils/misc.js');
const protocolHandler = require('./protocolHandler');
const getCmdLineArg = require('./utils/getCmdLineArg.js');
const childProcess = require('child_process');
const path = require('path');
const AppDirectory = require('appdirectory');
const dirs = new AppDirectory('Symphony');
require('electron-dl')();
@@ -75,11 +71,11 @@ if (isMac) {
*/
app.on('ready', setupThenOpenMainWindow);
app.on('window-all-closed', function () {
app.on('window-all-closed', function() {
app.quit();
});
app.on('activate', function () {
app.on('activate', function() {
if (windowMgr.isMainWindow(null)) {
setupThenOpenMainWindow();
} else {
@@ -95,7 +91,7 @@ app.setAsDefaultProtocolClient('symphony');
// This event is emitted only on macOS
// at this moment, support for windows
// is in pipeline (https://github.com/electron/electron/pull/8052)
app.on('open-url', function (event, url) {
app.on('open-url', function(event, url) {
handleProtocolAction(url);
});
@@ -108,10 +104,11 @@ function setupThenOpenMainWindow() {
// allows installer to launch app and set auto startup mode then
// immediately quit.
let hasInstallFlag = getCmdLineArg(process.argv, '--install', true);
let perUserInstall = getCmdLineArg(process.argv, '--peruser', true);
if (!isMac && hasInstallFlag) {
getConfigField('launchOnStartup')
.then(setStartup)
.then(updateUserConfigWin)
.then(updateUserConfigWin(perUserInstall))
.then(app.quit)
.catch(app.quit);
return;
@@ -123,8 +120,8 @@ function setupThenOpenMainWindow() {
// as the app is launched as a root user we don't get
// access to the config file
let launchOnStartup = process.argv[3];
updateUserConfigMac()
.then(setStartup(launchOnStartup))
setStartup(launchOnStartup)
.then(updateUserConfigMac(process.argv[2]))
.then(app.quit)
.catch(app.quit);
return;
@@ -137,50 +134,19 @@ function setupThenOpenMainWindow() {
electron.screen.on('display-removed', windowMgr.verifyDisplays);
}
function setStartup(lStartup){
function setStartup(lStartup) {
return symphonyAutoLauncher.isEnabled()
.then(function(isEnabled){
if (!isEnabled && lStartup) {
return symphonyAutoLauncher.enable();
}
if (isEnabled && !lStartup) {
return symphonyAutoLauncher.disable();
}
return true;
});
}
// Method to overwrite user config on mac installer
function updateUserConfigMac() {
return new Promise((resolve, reject) => {
let userConfigPath = dirs.userConfig() + '/';
let globalConfigPath = process.argv[2];
let userName = process.env.USER;
childProcess.exec(`rsync -r "${globalConfigPath}" "${userConfigPath}" && chown -R "${userName}" "${userConfigPath}"`, {timeout: 60000}, (err) => {
if (err) {
reject(err);
.then(function(isEnabled) {
if (!isEnabled && lStartup) {
return symphonyAutoLauncher.enable();
}
resolve();
});
});
}
// Method to overwrite user config on windows installer
function updateUserConfigWin() {
return new Promise((resolve, reject) => {
let userConfigPath = app.getPath('userData');
let globalConfigPath = path.join(__dirname, '..', '..', '..', 'config/Symphony.config');
childProcess.exec(`echo D|xcopy /y /e /s /c "${globalConfigPath}" "${userConfigPath}"`, {timeout: 60000}, (err) => {
if (err) {
reject(err);
if (isEnabled && !lStartup) {
return symphonyAutoLauncher.disable();
}
resolve();
return true;
});
});
}
function getUrlAndCreateMainWindow() {
@@ -194,7 +160,7 @@ function getUrlAndCreateMainWindow() {
}
getConfigField('url')
.then(createWin).catch(function (err) {
.then(createWin).catch(function(err) {
let title = 'Error loading configuration';
electron.dialog.showErrorBox(title, title + ': ' + err);
});
@@ -252,4 +218,4 @@ function handleProtocolAction(uri) {
// app is already open, so, just trigger the protocol action method
protocolHandler.processProtocolAction(uri);
}
}
}