Merge branch 'master' into electron-113

# Conflicts:
#	js/main.js
#	package.json
This commit is contained in:
Vishwas Shashidhar 2017-09-01 12:53:10 +05:30
commit 526c7cc1c9
50 changed files with 981 additions and 631 deletions

View File

@ -57,5 +57,11 @@ In order to achieve those goals Symphony is participating and working in close c
- code coverage reports are placed in dir: converage
- tests are located in dir: tests
## Logging
- Local logging is enabled for dev environments using the module [electron-log](https://www.npmjs.com/package/electron-log)
- On macOS, the logs are stored under `~/Library/Logs/<app name>/log.log`
- On Windows, the logs are stored under `%USERPROFILE%\AppData\Roaming\<app name>\log.log`
- Remote logging is enabled for local and production cases and are sent to the backend server via the remote objects
## Misc notes
If desiring to run against server without proper cert use cmd line option: --ignore-certificate-errors

View File

@ -16,7 +16,7 @@ let throttleActivity;
function activityDetection() {
// Get system idle status and idle time from PaulCBetts package
if (systemIdleTime.getIdleTime() < maxIdleTime) {
return {isUserIdle: false, systemIdleTime: systemIdleTime.getIdleTime()};
return { isUserIdle: false, systemIdleTime: systemIdleTime.getIdleTime() };
}
// If idle for more than 4 mins, monitor system idle status every second
@ -65,7 +65,7 @@ function monitorUserActivity() {
function sendActivity() {
let systemActivity = activityDetection();
if (systemActivity && !systemActivity.isUserIdle && systemActivity.systemIdleTime) {
send({systemIdleTime: systemActivity.systemIdleTime});
send({ systemIdleTime: systemActivity.systemIdleTime });
}
}
@ -84,6 +84,11 @@ function send(data) {
}
}
/**
* Set the activity's window
* @param period
* @param win
*/
function setActivityWindow(period, win) {
maxIdleTime = period;
activityWindow = win;
@ -95,6 +100,5 @@ module.exports = {
send: send,
setActivityWindow: setActivityWindow,
activityDetection: activityDetection,
monitorUserActivity: monitorUserActivity, // Exporting this for unit test
initiateActivityDetection: initiateActivityDetection
};
monitorUserActivity: monitorUserActivity, // Exporting this for unit tests
};

View File

@ -10,6 +10,10 @@ const maxCount = 1e8;
const log = require('./log.js');
const logLevels = require('./enums/logLevels.js');
/**
* Shows the badge count
* @param count
*/
function show(count) {
if (typeof count !== 'number') {
log.send(logLevels.WARN, 'badgeCount: invalid func arg, must be a number: ' + count);
@ -37,6 +41,11 @@ function show(count) {
}
}
/**
* Sets the data url
* @param dataUrl
* @param count
*/
function setDataUrl(dataUrl, count) {
const mainWindow = windowMgr.getMainWindow();
if (mainWindow && dataUrl && count) {
@ -50,4 +59,4 @@ function setDataUrl(dataUrl, count) {
module.exports = {
show: show,
setDataUrl: setDataUrl
}
};

View File

@ -12,23 +12,32 @@
// renderer process, this will have to do. See github issue posted here to
// electron: https://github.com/electron/electron/issues/9312
var { ipcRenderer } = require('electron');
const { ipcRenderer } = require('electron');
var nextId = 0;
var includes = [].includes;
let nextId = 0;
let includes = [].includes;
function getNextId() {
return ++nextId;
}
// |options.type| can not be empty and has to include 'window' or 'screen'.
/**
* Checks if the options and their types are valid
* @param options |options.type| can not be empty and has to include 'window' or 'screen'.
* @returns {boolean}
*/
function isValid(options) {
return ((options != null ? options.types : undefined) != null) && Array.isArray(options.types);
return ((options !== null ? options.types : undefined) !== null) && Array.isArray(options.types);
}
/**
* Gets the sources for capturing screens / windows
* @param options
* @param callback
* @returns {*}
*/
function getSources(options, callback) {
var captureScreen, captureWindow, id;
let captureScreen, captureWindow, id;
if (!isValid(options)) {
return callback(new Error('Invalid options'));
}
@ -36,33 +45,34 @@ function getSources(options, callback) {
captureScreen = includes.call(options.types, 'screen');
let updatedOptions = options;
if (updatedOptions.thumbnailSize == null) {
if (updatedOptions.thumbnailSize === null) {
updatedOptions.thumbnailSize = {
width: 150,
height: 150
}
};
}
id = getNextId();
ipcRenderer.send('ELECTRON_BROWSER_DESKTOP_CAPTURER_GET_SOURCES', captureWindow, captureScreen, updatedOptions.thumbnailSize, id);
return ipcRenderer.once('ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_' + id, function (event, sources) {
var source;
callback(null, (function () {
var i, len, results
return ipcRenderer.once('ELECTRON_RENDERER_DESKTOP_CAPTURER_RESULT_' + id, function(event, sources) {
let source;
callback(null, (function() {
let i, len, results;
results = [];
for (i = 0, len = sources.length; i < len; i++) {
source = sources[i]
source = sources[i];
results.push({
id: source.id,
name: source.name,
thumbnail: source.thumbnail
})
});
}
return results
return results;
}()));
});
}
module.exports = getSources;
module.exports = getSources;

View File

@ -11,14 +11,14 @@ const logLevels = require('../enums/logLevels.js');
* @param {String} url Url that failed
* @param {String} errorDesc Description of error
* @param {Number} errorCode Error code
* @param {callback} retryCallback Callback when user clicks reload
* @param {function} retryCallback Callback when user clicks reload
*/
function showLoadFailure(win, url, errorDesc, errorCode, retryCallback) {
let msg;
if (url) {
msg = 'Error loading URL:\n' + url;
} else {
msg = 'Error loading window'
msg = 'Error loading window';
}
if (errorDesc) {
msg += '\n\n' + errorDesc;
@ -29,7 +29,7 @@ function showLoadFailure(win, url, errorDesc, errorCode, retryCallback) {
electron.dialog.showMessageBox(win, {
type: 'error',
buttons: [ 'Reload', 'Ignore' ],
buttons: ['Reload', 'Ignore'],
defaultId: 0,
cancelId: 1,
noLink: true,
@ -38,7 +38,7 @@ function showLoadFailure(win, url, errorDesc, errorCode, retryCallback) {
}, response);
log.send(logLevels.WARNING, 'Load failure msg: ' + errorDesc +
' errorCode: ' + errorCode + ' for url:' + url);
' errorCode: ' + errorCode + ' for url:' + url);
// async handle of user input
function response(buttonId) {
@ -53,11 +53,11 @@ function showLoadFailure(win, url, errorDesc, errorCode, retryCallback) {
* Show message indicating network connectivity has been lost.
* @param {BrowserWindow} win Window to host dialog
* @param {String} url Url that failed
* @param {callback} retryCallback Callback when user clicks reload
* @param {function} retryCallback Callback when user clicks reload
*/
function showNetworkConnectivityError(win, url, retryCallback) {
var errorDesc = 'Network connectivity has been lost, check your internet connection.';
let errorDesc = 'Network connectivity has been lost, check your internet connection.';
showLoadFailure(win, url, errorDesc, 0, retryCallback);
}
module.exports = { showLoadFailure, showNetworkConnectivityError };
module.exports = { showLoadFailure, showNetworkConnectivityError };

View File

@ -19,12 +19,13 @@ local.ipcRenderer.on('downloadProgress', () => {
/**
* Open file in default app.
* @param id
*/
function openFile(id) {
let fileIndex = local.downloadItems.findIndex((item) => {
return item._id === id
return item._id === id;
});
if (fileIndex !== -1){
if (fileIndex !== -1) {
let openResponse = remote.shell.openExternal(`file:///${local.downloadItems[fileIndex].savedPath}`);
if (!openResponse) {
remote.dialog.showErrorBox("File not found", 'The file you are trying to open cannot be found in the specified path.');
@ -34,10 +35,11 @@ function openFile(id) {
/**
* Show downloaded file in explorer or finder.
* @param id
*/
function showInFinder(id) {
let showFileIndex = local.downloadItems.findIndex((item) => {
return item._id === id
return item._id === id;
});
if (showFileIndex !== -1) {
let showResponse = remote.shell.showItemInFolder(local.downloadItems[showFileIndex].savedPath);
@ -47,6 +49,10 @@ function showInFinder(id) {
}
}
/**
* Create the document object model
* @param arg
*/
function createDOM(arg) {
if (arg && arg._id) {
@ -149,6 +155,9 @@ function createDOM(arg) {
}
}
/**
* Initiate the download manager
*/
function initiate() {
let mainFooter = document.getElementById('footer');
let mainDownloadDiv = document.getElementById('download-manager-footer');
@ -159,7 +168,7 @@ function initiate() {
let ulFind = document.getElementById('download-main');
if (!ulFind){
if (!ulFind) {
let uList = document.createElement('ul');
uList.id = 'download-main';
mainDownloadDiv.appendChild(uList);
@ -167,7 +176,7 @@ function initiate() {
let closeSpanFind = document.getElementById('close-download-bar');
if (!closeSpanFind){
if (!closeSpanFind) {
let closeSpan = document.createElement('span');
closeSpan.id = 'close-download-bar';
closeSpan.classList.add('close-download-bar');

View File

@ -1,7 +1,11 @@
'use strict';
var keyMirror = require('keymirror');
let keyMirror = require('keymirror');
/**
* Set of APIs exposed to the remote object
* @type {Object}
*/
const cmds = keyMirror({
isOnline: null,
registerLogger: null,

View File

@ -1,7 +1,11 @@
'use strict';
var keyMirror = require('keymirror');
let keyMirror = require('keymirror');
/**
* The different log levels
* @type {Object}
*/
module.exports = keyMirror({
ERROR: null,
CONFLICT: null,

View File

@ -1,16 +1,26 @@
'use strict';
const getCmdLineArg = require('./utils/getCmdLineArg.js')
const getCmdLineArg = require('./utils/getCmdLineArg.js');
const { isDevEnv } = require('./utils/misc');
const logLevels = require('./enums/logLevels.js');
const MAX_LOG_QUEUE_LENGTH = 100;
let electronLog;
class Logger {
constructor() {
// browser window that has registered a logger
this.logWindow = null;
// holds log messages received before logger has been registered.
this.logQueue = [];
// Initializes the local logger
if (isDevEnv) {
initializeLocalLogger();
}
}
/**
@ -25,6 +35,10 @@ class Logger {
return;
}
if (isDevEnv) {
logLocally(level, details);
}
let logMsg = {
level: level,
details: details,
@ -45,18 +59,22 @@ class Logger {
}
}
/**
* Sets a window instance for the remote object
* @param win
*/
setLogWindow(win) {
this.logWindow = win;
if (this.logWindow) {
var logMsg = {};
let logMsg = {};
if (Array.isArray(this.logQueue)) {
logMsg.msgs = this.logQueue;
}
// configure desired log level and send pending log msgs
let logLevel = getCmdLineArg(process.argv, '--logLevel=');
let logLevel = getCmdLineArg(process.argv, '--logLevel=', false);
if (logLevel) {
let level = logLevel.split('=')[1];
if (level) {
@ -64,7 +82,7 @@ class Logger {
}
}
if (getCmdLineArg(process.argv, '--enableConsoleLogging')) {
if (getCmdLineArg(process.argv, '--enableConsoleLogging', false)) {
logMsg.showInConsole = true;
}
@ -77,11 +95,40 @@ class Logger {
}
}
var loggerInstance = new Logger();
let loggerInstance = new Logger();
/**
* Initializes the electron logger for local logging
*/
function initializeLocalLogger() {
// eslint-disable-next-line global-require
electronLog = require('electron-log');
electronLog.transports.file.level = 'debug';
electronLog.transports.file.format = '{h}:{i}:{s}:{ms} {text}';
electronLog.transports.file.maxSize = 10 * 1024 * 1024;
electronLog.transports.file.appName = 'Symphony';
}
/**
* Logs locally using the electron-logger
* @param level
* @param message
*/
function logLocally(level, message) {
switch (level) {
case logLevels.ERROR: electronLog.error(message); break;
case logLevels.CONFLICT: electronLog.error(message); break;
case logLevels.WARN: electronLog.warn(message); break;
case logLevels.ACTION: electronLog.warn(message); break;
case logLevels.INFO: electronLog.info(message); break;
case logLevels.DEBUG: electronLog.debug(message); break;
default: electronLog.debug(message);
}
}
// Logger class is only exposed for testing purposes.
module.exports = {
Logger: Logger,
send: loggerInstance.send.bind(loggerInstance),
setLogWindow: loggerInstance.setLogWindow.bind(loggerInstance)
}
};

View File

@ -1,12 +1,20 @@
'use strict';
// Third Party Dependencies
const electron = require('electron');
const app = electron.app;
const nodeURL = require('url');
const squirrelStartup = require('electron-squirrel-startup');
const AutoLaunch = require('auto-launch');
const urlParser = require('url');
const { getConfigField, updateUserConfigWin, updateUserConfigMac } = require('./config.js');
const childProcess = require('child_process');
const path = require('path');
const AppDirectory = require('appdirectory');
const dirs = new AppDirectory('Symphony');
// Local Dependencies
const { getConfigField } = require('./config.js');
const { isMac, isDevEnv } = require('./utils/misc.js');
const protocolHandler = require('./protocolHandler');
const getCmdLineArg = require('./utils/getCmdLineArg.js');
@ -71,10 +79,17 @@ if (isMac) {
*/
app.on('ready', setupThenOpenMainWindow);
/**
* Is triggered when all the windows are closed
* In which case we quit the app
*/
app.on('window-all-closed', function() {
app.quit();
});
/**
* Is triggered when the app is up & running
*/
app.on('activate', function() {
if (windowMgr.isMainWindow(null)) {
setupThenOpenMainWindow();
@ -88,13 +103,19 @@ app.on('activate', function() {
// and registry keys in windows
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)
/**
* 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) {
handleProtocolAction(url);
});
/**
* Sets up the app (to handle various things like config changes, protocol handling etc.)
* and opens the main window
*/
function setupThenOpenMainWindow() {
processProtocolAction(process.argv);
@ -120,8 +141,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];
// We wire this in via the post install script
// to get the config file path where the app is installed
// We wire this in via the post install script
// to get the config file path where the app is installed
let appGlobalConfigPath = process.argv[2];
setStartup(launchOnStartup)
.then(() => updateUserConfigMac(appGlobalConfigPath))
@ -137,6 +158,11 @@ function setupThenOpenMainWindow() {
electron.screen.on('display-removed', windowMgr.verifyDisplays);
}
/**
* Sets Symphony on startup
* @param lStartup
* @returns {Promise}
*/
function setStartup(lStartup) {
return symphonyAutoLauncher.isEnabled()
.then(function(isEnabled) {
@ -152,10 +178,51 @@ function setStartup(lStartup) {
});
}
/**
* Method to overwrite user config on mac installer
* @returns {Promise}
*/
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);
}
resolve();
});
});
}
/**
* Method to overwrite user config on windows installer
* @returns {Promise}
*/
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);
}
resolve();
});
});
}
/**
* Checks for the url argument, processes it
* and creates the main window
*/
function getUrlAndCreateMainWindow() {
// for dev env allow passing url argument
if (isDevEnv) {
let url = getCmdLineArg(process.argv, '--url=')
let url = getCmdLineArg(process.argv, '--url=', false);
if (url) {
windowMgr.createMainWindow(url.substr(6));
return;
@ -169,6 +236,10 @@ function getUrlAndCreateMainWindow() {
});
}
/**
* Creates a window
* @param urlFromConfig
*/
function createWin(urlFromConfig) {
let protocol = '';
// add https protocol if none found.
@ -176,7 +247,7 @@ function createWin(urlFromConfig) {
if (!parsedUrl.protocol) {
protocol = 'https';
}
var url = nodeURL.format({
let url = nodeURL.format({
protocol: protocol,
slahes: true,
pathname: parsedUrl.href
@ -198,7 +269,7 @@ function processProtocolAction(argv) {
return;
}
let protocolUri = getCmdLineArg(argv, 'symphony://');
let protocolUri = getCmdLineArg(argv, 'symphony://', false);
if (protocolUri) {
@ -213,6 +284,10 @@ function processProtocolAction(argv) {
}
}
/**
* Handles a protocol action based on the current state of the app
* @param uri
*/
function handleProtocolAction(uri) {
if (!isAppAlreadyOpen) {
// app is opened by the protocol url, cache the protocol url to be used later

View File

@ -9,7 +9,7 @@ const electron = require('electron');
const windowMgr = require('./windowMgr.js');
const log = require('./log.js');
const logLevels = require('./enums/logLevels');
const activityDetection = require('./activityDetection/activityDetection');
const activityDetection = require('./activityDetection');
const badgeCount = require('./badgeCount.js');
const protocolHandler = require('./protocolHandler');
const configureNotification = require('./notify/settings/configure-notification-position');
@ -30,7 +30,7 @@ function isValidWindow(event) {
if (!checkValidWindow) {
return true;
}
var result = false;
let result = false;
if (event && event.sender) {
// validate that event sender is from window we created
const browserWin = electron.BrowserWindow.fromWebContents(event.sender);
@ -107,7 +107,7 @@ electron.ipcMain.on(apiName, (event, arg) => {
// expose these methods primarily for testing...
module.exports = {
shouldCheckValidWindow: function (shouldCheck) {
shouldCheckValidWindow: function(shouldCheck) {
checkValidWindow = shouldCheck;
}
};
};

View File

@ -1,14 +1,17 @@
'use strict';
const log = require('./log.js');
const logLevels = require('./enums/logLevels.js')
const logLevels = require('./enums/logLevels.js');
// once a minute
setInterval(gatherMemory, 1000 * 60);
/**
* Gathers system memory and logs it to the remote system
*/
function gatherMemory() {
var memory = process.getProcessMemoryInfo();
var details =
let memory = process.getProcessMemoryInfo();
let details =
'workingSetSize: ' + memory.workingSetSize +
' peakWorkingSetSize: ' + memory.peakWorkingSetSize +
' privatesBytes: ' + memory.privatesBytes +

View File

@ -8,9 +8,9 @@ const log = require('../log.js');
const logLevels = require('../enums/logLevels.js');
const eventEmitter = require('../eventEmitter');
var minimizeOnClose = false;
var launchOnStartup = false;
var isAlwaysOnTop = false;
let minimizeOnClose = false;
let launchOnStartup = false;
let isAlwaysOnTop = false;
setCheckboxValues();
@ -31,10 +31,9 @@ if (isMac) {
});
}
const template = [
{
label: 'Edit',
submenu: [
const template = [{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
@ -44,228 +43,214 @@ const template = [
{ role: 'pasteandmatchstyle' },
{ role: 'delete' },
{ role: 'selectall' }
]
]
},
{
label: 'View',
submenu: [{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.reload();
}
}
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click (item, focusedWindow) {
if (focusedWindow) {
focusedWindow.reload();
}
}
},
{
label: 'Toggle Developer Tools',
accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
click (item, focusedWindow) {
if (focusedWindow) {
focusedWindow.webContents.toggleDevTools();
}
}
},
{
type: 'separator'
},
{
role: 'resetzoom'
},
{
role: 'zoomin'
},
{
role: 'zoomout'
},
{
type: 'separator'
},
{
role: 'togglefullscreen'
label: 'Toggle Developer Tools',
accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.webContents.toggleDevTools();
}
]
}
},
{
role: 'window',
submenu: [
{
role: 'minimize'
},
{
role: 'close'
}
]
type: 'separator'
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click () { electron.shell.openExternal('https://www.symphony.com') }
}
]
role: 'resetzoom'
},
{
role: 'zoomin'
},
{
role: 'zoomout'
},
{
type: 'separator'
},
{
role: 'togglefullscreen'
}
]
},
{
role: 'window',
submenu: [{
role: 'minimize'
},
{
role: 'close'
}
]
},
{
role: 'help',
submenu: [{
label: 'Learn More',
click() { electron.shell.openExternal('https://www.symphony.com'); }
}]
}
];
function getTemplate(app) {
if (isMac && template[0].label !== app.getName()) {
template.unshift({
label: app.getName(),
submenu: [
{
role: 'about'
},
{
type: 'separator'
},
{
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
role: 'hide'
},
{
role: 'hideothers'
},
{
role: 'unhide'
},
{
type: 'separator'
},
{
role: 'quit'
}
submenu: [{
role: 'about'
},
{
type: 'separator'
},
{
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
role: 'hide'
},
{
role: 'hideothers'
},
{
role: 'unhide'
},
{
type: 'separator'
},
{
role: 'quit'
}
]
});
// Edit menu.
template[1].submenu.push(
{
type: 'separator'
// Edit menu.
template[1].submenu.push({
type: 'separator'
}, {
label: 'Speech',
submenu: [{
role: 'startspeaking'
},
{
label: 'Speech',
submenu: [
{
role: 'startspeaking'
},
{
role: 'stopspeaking'
}
]
role: 'stopspeaking'
}
)
// Window menu.
template[3].submenu = [
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Zoom',
role: 'zoom'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
]
]
});
// Window menu.
template[3].submenu = [{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Zoom',
role: 'zoom'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
];
}
var index = 2;
if (isMac && template[0].label !== app.getName()){
let index = 2;
if (isMac && template[0].label !== app.getName()) {
index = 3;
}
// Window menu -> launchOnStartup.
template[index].submenu.push(
{
label: 'Auto Launch On Startup',
type: 'checkbox',
checked: launchOnStartup,
click: function (item) {
if (item.checked){
symphonyAutoLauncher.enable()
.catch(function (err) {
let title = 'Error setting AutoLaunch configuration';
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
});
} else {
symphonyAutoLauncher.disable()
.catch(function (err) {
let title = 'Error setting AutoLaunch configuration';
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
});
}
launchOnStartup = item.checked;
updateConfigField('launchOnStartup', launchOnStartup);
template[index].submenu.push({
label: 'Auto Launch On Startup',
type: 'checkbox',
checked: launchOnStartup,
click: function(item) {
if (item.checked) {
symphonyAutoLauncher.enable()
.catch(function(err) {
let title = 'Error setting AutoLaunch configuration';
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
});
} else {
symphonyAutoLauncher.disable()
.catch(function(err) {
let title = 'Error setting AutoLaunch configuration';
log.send(logLevels.ERROR, 'MenuTemplate: ' + title + ': auto launch error ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
});
}
launchOnStartup = item.checked;
updateConfigField('launchOnStartup', launchOnStartup);
}
)
});
// Window menu -> alwaysOnTop.
template[index].submenu.push(
{
label: 'Always on top',
type: 'checkbox',
checked: isAlwaysOnTop,
click: (item) => {
isAlwaysOnTop = item.checked;
eventEmitter.emit('isAlwaysOnTop', isAlwaysOnTop);
updateConfigField('alwaysOnTop', isAlwaysOnTop);
}
template[index].submenu.push({
label: 'Always on top',
type: 'checkbox',
checked: isAlwaysOnTop,
click: (item) => {
isAlwaysOnTop = item.checked;
eventEmitter.emit('isAlwaysOnTop', isAlwaysOnTop);
updateConfigField('alwaysOnTop', isAlwaysOnTop);
}
)
});
// Window menu -> minimizeOnClose.
// Window menu -> minimizeOnClose.
// ToDo: Add behavior on Close.
template[index].submenu.push(
{
label: 'Minimize on Close',
type: 'checkbox',
checked: minimizeOnClose,
click: function (item) {
minimizeOnClose = item.checked;
updateConfigField('minimizeOnClose', minimizeOnClose);
}
template[index].submenu.push({
label: 'Minimize on Close',
type: 'checkbox',
checked: minimizeOnClose,
click: function(item) {
minimizeOnClose = item.checked;
updateConfigField('minimizeOnClose', minimizeOnClose);
}
)
});
if (!isMac){
template[index].submenu.push(
{
label: 'Quit Symphony',
click: function () {
app.quit();
}
if (!isMac) {
template[index].submenu.push({
label: 'Quit Symphony',
click: function() {
app.quit();
}
)
});
}
return template;
}
function setCheckboxValues(){
/**
* Sets the checkbox values for different menu items
* based on configuration
*/
function setCheckboxValues() {
getConfigField('minimizeOnClose').then(function(mClose) {
minimizeOnClose = mClose;
}).catch(function (err){
}).catch(function(err) {
let title = 'Error loading configuration';
log.send(logLevels.ERROR, 'MenuTemplate: error getting config field minimizeOnClose, error: ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
@ -273,7 +258,7 @@ function setCheckboxValues(){
getConfigField('launchOnStartup').then(function(lStartup) {
launchOnStartup = lStartup;
}).catch(function (err){
}).catch(function(err) {
let title = 'Error loading configuration';
log.send(logLevels.ERROR, 'MenuTemplate: error getting config field launchOnStartup, error: ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
@ -282,7 +267,7 @@ function setCheckboxValues(){
getConfigField('alwaysOnTop').then(function(mAlwaysOnTop) {
isAlwaysOnTop = mAlwaysOnTop;
eventEmitter.emit('isAlwaysOnTop', isAlwaysOnTop);
}).catch(function (err){
}).catch(function(err) {
let title = 'Error loading configuration';
log.send(logLevels.ERROR, 'MenuTemplate: error getting config field alwaysOnTop, error: ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
@ -290,7 +275,7 @@ function setCheckboxValues(){
getConfigField('notificationSettings').then(function(notfObject) {
eventEmitter.emit('notificationSettings', notfObject);
}).catch(function (err){
}).catch(function(err) {
let title = 'Error loading configuration';
log.send(logLevels.ERROR, 'MenuTemplate: error getting config field notificationSettings, error: ' + err);
electron.dialog.showErrorBox(title, title + ': ' + err);
@ -298,11 +283,11 @@ function setCheckboxValues(){
}
function getMinimizeOnClose(){
function getMinimizeOnClose() {
return minimizeOnClose;
}
module.exports = {
getTemplate : getTemplate,
getMinimizeOnClose : getMinimizeOnClose
getTemplate: getTemplate,
getMinimizeOnClose: getMinimizeOnClose
};

View File

@ -3,13 +3,21 @@
const log = require('../log.js');
const logLevels = require('../enums/logLevels.js');
// One animation at a time
/**
* Manages one animation at a time
* @param options
* @constructor
*/
const AnimationQueue = function(options) {
this.options = options;
this.queue = [];
this.running = false;
}
};
/**
* Pushes each animation to a queue
* @param object
*/
AnimationQueue.prototype.push = function(object) {
if (this.running) {
this.queue.push(object);
@ -17,8 +25,12 @@ AnimationQueue.prototype.push = function(object) {
this.running = true;
setTimeout(this.animate.bind(this, object), 0);
}
}
};
/**
* Animates an animation that is part of the queue
* @param object
*/
AnimationQueue.prototype.animate = function(object) {
object.func.apply(null, object.args)
.then(function() {
@ -37,10 +49,13 @@ AnimationQueue.prototype.animate = function(object) {
' with stack trace:' + err.stack);
/* eslint-enable no-console */
})
}
};
/**
* Clears the queue
*/
AnimationQueue.prototype.clear = function() {
this.queue = [];
}
};
module.exports = AnimationQueue;

View File

@ -1,4 +1,4 @@
'use strict'
'use strict';
//
// BrowserWindow preload script use to create notifications window for
@ -9,6 +9,10 @@
const electron = require('electron');
const ipc = electron.ipcRenderer;
/**
* Sets style for a notification
* @param config
*/
function setStyle(config) {
// Style it
let notiDoc = window.document;
@ -20,14 +24,14 @@ function setStyle(config) {
let close = notiDoc.getElementById('close');
// Default style
setStyleOnDomElement(config.defaultStyleContainer, container)
setStyleOnDomElement(config.defaultStyleContainer, container);
let style = {
height: config.height,
width: config.width,
borderRadius: config.borderRadius + 'px'
}
setStyleOnDomElement(style, container)
};
setStyleOnDomElement(style, container);
setStyleOnDomElement(config.defaultStyleHeader, header);
@ -40,6 +44,11 @@ function setStyle(config) {
setStyleOnDomElement(config.defaultStyleClose, close);
}
/**
* Sets contents for a notification
* @param event
* @param notificationObj
*/
function setContents(event, notificationObj) {
// sound
if (notificationObj.sound) {
@ -49,7 +58,7 @@ function setContents(event, notificationObj) {
// Won't check remote files e.g. http://
if (notificationObj.sound.match(/^file:/) !== null
|| notificationObj.sound.match(/^\//) !== null) {
let audio = new window.Audio(notificationObj.sound)
let audio = new window.Audio(notificationObj.sound);
audio.play()
}
} catch (e) {
@ -102,15 +111,20 @@ function setContents(event, notificationObj) {
// note: use onclick because we only want one handler, for case
// when content gets overwritten by notf with same tag
closeButton.onclick = function(clickEvent) {
clickEvent.stopPropagation()
clickEvent.stopPropagation();
ipc.send('electron-notify-close', winId, notificationObj)
}
};
container.onclick = function() {
ipc.send('electron-notify-click', winId, notificationObj);
}
}
/**
* Sets style on a notification for a DOM element
* @param styleObj
* @param domElement
*/
function setStyleOnDomElement(styleObj, domElement) {
try {
let styleAttr = Object.keys(styleObj);
@ -124,22 +138,30 @@ function setStyleOnDomElement(styleObj, domElement) {
}
}
/**
* Loads the config
* @param event
* @param conf
*/
function loadConfig(event, conf) {
setStyle(conf || {})
}
/**
* Resets the notification window
*/
function reset() {
let notiDoc = window.document
let container = notiDoc.getElementById('container')
let closeButton = notiDoc.getElementById('close')
let notiDoc = window.document;
let container = notiDoc.getElementById('container');
let closeButton = notiDoc.getElementById('close');
// Remove event listener
let newContainer = container.cloneNode(true)
container.parentNode.replaceChild(newContainer, container)
let newCloseButton = closeButton.cloneNode(true)
let newContainer = container.cloneNode(true);
container.parentNode.replaceChild(newContainer, container);
let newCloseButton = closeButton.cloneNode(true);
closeButton.parentNode.replaceChild(newCloseButton, closeButton)
}
ipc.on('electron-notify-set-contents', setContents)
ipc.on('electron-notify-load-config', loadConfig)
ipc.on('electron-notify-reset', reset)
ipc.on('electron-notify-set-contents', setContents);
ipc.on('electron-notify-load-config', loadConfig);
ipc.on('electron-notify-reset', reset);

View File

@ -9,8 +9,8 @@
<p id="message"></p>
<div id="close">
<svg fill="#000000" height="16" viewBox="0 0 24 24" width="16" xmlns="http://www.w3.org/2000/svg">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
<path d="M0 0h24v24H0z" fill="none"></path>
</svg>
</div>
</div>

View File

@ -1,4 +1,4 @@
'use strict'
'use strict';
//
// code here adapted from https://www.npmjs.com/package/electron-notify
// made following changes:
@ -138,13 +138,7 @@ let config = {
nodeIntegration: isNodeEnv
}
}
}
// function setConfig(customConfig) {
// Object.assign(customConfig, config);
//
// calcDimensions();
// }
};
if (app.isReady()) {
setup();
@ -152,7 +146,10 @@ if (app.isReady()) {
app.on('ready', setup);
}
// Method to update notification config
/**
* Method to update notification config
* @param customConfig
*/
function updateConfig(customConfig) {
// Fetching user preferred notification position from config
if (customConfig.position) {
@ -167,6 +164,9 @@ function updateConfig(customConfig) {
}
}
/**
* Method to setup the notification configuration
*/
function setup() {
setupConfig();
@ -177,6 +177,10 @@ function setup() {
electron.screen.on('display-metrics-changed', setupConfig);
}
/**
* Method to get the notification template path
* @returns {string|*}
*/
function getTemplatePath() {
let templatePath = path.join(__dirname, 'electron-notify.html');
try {
@ -188,12 +192,15 @@ function getTemplatePath() {
return config.templatePath;
}
/**
* Calculates the dimensions of the screen
*/
function calcDimensions() {
const vertSpaceBetweenNotf = 8;
// Calc totalHeight & totalWidth
config.totalHeight = config.height + vertSpaceBetweenNotf;
config.totalWidth = config.width
config.totalWidth = config.width;
let firstPosX, firstPosY;
switch (config.startCorner) {
@ -220,13 +227,16 @@ function calcDimensions() {
config.firstPos = {
x: firstPosX,
y: firstPosY
}
};
// Set nextInsertPos
nextInsertPos.x = config.firstPos.x
nextInsertPos.x = config.firstPos.x;
nextInsertPos.y = config.firstPos.y
}
/**
* Setup the notification config
*/
function setupConfig() {
closeAll();
@ -273,6 +283,11 @@ function setupConfig() {
config.maxVisibleNotifications = config.maxVisibleNotifications > 5 ? 5 : config.maxVisibleNotifications;
}
/**
* Notifies the user
* @param notification
* @returns {*}
*/
function notify(notification) {
// Is it an object and only one argument?
if (arguments.length === 1 && typeof notification === 'object') {
@ -283,17 +298,25 @@ function notify(notification) {
animationQueue.push({
func: showNotification,
args: [ notf ]
})
});
return notf.id
}
log.send(logLevels.ERROR, 'electron-notify: ERROR notify() only accepts a single object with notification parameters.');
return null;
}
/**
* Increment the notification
*/
function incrementId() {
latestID++;
}
/**
* Shows the notification to the user
* @param notificationObj
* @returns {Promise}
*/
function showNotification(notificationObj) {
return new Promise(function(resolve) {
@ -349,7 +372,7 @@ function showNotification(notificationObj) {
});
delete notificationWindow.electronNotifyOnCloseFunc;
}
setNotificationContents(notificationWindow, notificationObj)
setNotificationContents(notificationWindow, notificationObj);
resolve();
return;
}
@ -361,8 +384,8 @@ function showNotification(notificationObj) {
// Get inactiveWindow or create new:
getWindow().then(function(notificationWindow) {
// Move window to position
calcInsertPos()
setWindowPosition(notificationWindow, nextInsertPos.x, nextInsertPos.y)
calcInsertPos();
setWindowPosition(notificationWindow, nextInsertPos.x, nextInsertPos.y);
let updatedNotfWindow = setNotificationContents(notificationWindow, notificationObj);
@ -378,6 +401,12 @@ function showNotification(notificationObj) {
})
}
/**
* Sets the HTML notification contents along with other options
* @param notfWindow
* @param notfObj
* @returns {*}
*/
function setNotificationContents(notfWindow, notfObj) {
// Display time per notification basis.
@ -387,7 +416,7 @@ function setNotificationContents(notfWindow, notfObj) {
clearTimeout(notfWindow.displayTimer);
}
var updatedNotificationWindow = notfWindow;
const updatedNotificationWindow = notfWindow;
updatedNotificationWindow.notfyObj = notfObj;
@ -437,7 +466,13 @@ function setNotificationContents(notfWindow, notfObj) {
return updatedNotificationWindow;
}
// Close notification function
/**
* Closes the notification
* @param notificationWindow
* @param notificationObj
* @param getTimeoutId
* @returns {Function}
*/
function buildCloseNotification(notificationWindow, notificationObj, getTimeoutId) {
return function(event) {
if (closedNotifications[notificationObj.id]) {
@ -459,7 +494,7 @@ function buildCloseNotification(notificationWindow, notificationObj, getTimeoutI
}
// reset content
notificationWindow.webContents.send('electron-notify-reset')
notificationWindow.webContents.send('electron-notify-reset');
if (getTimeoutId && typeof getTimeoutId === 'function') {
let timeoutId = getTimeoutId();
clearTimeout(timeoutId);
@ -480,8 +515,13 @@ function buildCloseNotification(notificationWindow, notificationObj, getTimeoutI
}
}
// Always add to animationQueue to prevent erros (e.g. notification
// got closed while it was moving will produce an error)
/**
* Adds an active notification the close notification queue
* Always add to animationQueue to prevent erros (e.g. notification
* got closed while it was moving will produce an error)
* @param closeFunc
* @returns {Function}
*/
function buildCloseNotificationSafely(closeFunc) {
return function(reason) {
animationQueue.push({
@ -509,10 +549,10 @@ ipc.on('electron-notify-click', function (event, winId, notificationObj) {
}
});
/*
* Checks for queued notifications and add them
* to AnimationQueue if possible
*/
/**
* Checks for queued notifications and add them
* to AnimationQueue if possible
*/
function checkForQueuedNotifications() {
if (notificationQueue.length > 0 &&
activeNotifications.length < config.maxVisibleNotifications) {
@ -524,25 +564,25 @@ function checkForQueuedNotifications() {
}
}
/*
* Moves the notifications one position down,
* starting with notification at startPos
*
* @param {int} startPos
*/
/**
* Moves the notifications one position down,
* starting with notification at startPos
* @param startPos
* @returns {Promise}
*/
function moveOneDown(startPos) {
return new Promise(function(resolve) {
if (startPos >= activeNotifications || startPos === -1) {
resolve()
resolve();
return
}
// Build array with index of affected notifications
let notificationPosArray = []
let notificationPosArray = [];
for (let i = startPos; i < activeNotifications.length; i++) {
notificationPosArray.push(i)
}
// Start to animate all notifications at once or in parallel
let asyncFunc = asyncMap // Best performance
let asyncFunc = asyncMap; // Best performance
if (config.animateInParallel === false) {
asyncFunc = asyncMapSeries // Sluggish
}
@ -552,6 +592,11 @@ function moveOneDown(startPos) {
})
}
/**
* Moves the notification animation
* @param i
* @param done
*/
function moveNotificationAnimation(i, done) {
// Get notification to move
let notificationWindow = activeNotifications[i];
@ -571,32 +616,38 @@ function moveNotificationAnimation(i, done) {
}
// Get startPos, calc step size and start animationInterval
let startY = notificationWindow.getPosition()[1]
let step = (newY - startY) / config.animationSteps
let curStep = 1
let startY = notificationWindow.getPosition()[1];
let step = (newY - startY) / config.animationSteps;
let curStep = 1;
let animationInterval = setInterval(function() {
// Abort condition
if (curStep === config.animationSteps) {
setWindowPosition(notificationWindow, config.firstPos.x, newY);
clearInterval(animationInterval)
clearInterval(animationInterval);
done(null, 'done');
return;
}
// Move one step down
setWindowPosition(notificationWindow, config.firstPos.x, startY + curStep * step)
setWindowPosition(notificationWindow, config.firstPos.x, startY + curStep * step);
curStep++
}, config.animationStepMs)
}
/**
* Sets the window's position
* @param browserWin
* @param posX
* @param posY
*/
function setWindowPosition(browserWin, posX, posY) {
if (!browserWin.isDestroyed()) {
browserWin.setPosition(parseInt(posX, 10), parseInt(posY, 10))
}
}
/*
* Find next possible insert position (on top)
*/
/**
* Find next possible insert position (on top)
*/
function calcInsertPos() {
if (activeNotifications.length < config.maxVisibleNotifications) {
switch(config.startCorner) {
@ -614,35 +665,38 @@ function calcInsertPos() {
}
}
/*
* Get a window to display a notification. Use inactiveWindows or
* create a new window
* @return {Window}
*/
/**
* Get a window to display a notification. Use inactiveWindows or
* create a new window
* @returns {Promise}
*/
function getWindow() {
return new Promise(function(resolve) {
let notificationWindow
let notificationWindow;
// Are there still inactiveWindows?
if (inactiveWindows.length > 0) {
notificationWindow = inactiveWindows.pop()
notificationWindow = inactiveWindows.pop();
resolve(notificationWindow)
} else {
// Or create a new window
let windowProperties = config.defaultWindow
windowProperties.width = config.width
windowProperties.height = config.height
notificationWindow = new BrowserWindow(windowProperties)
notificationWindow.setVisibleOnAllWorkspaces(true)
notificationWindow.loadURL(getTemplatePath())
let windowProperties = config.defaultWindow;
windowProperties.width = config.width;
windowProperties.height = config.height;
notificationWindow = new BrowserWindow(windowProperties);
notificationWindow.setVisibleOnAllWorkspaces(true);
notificationWindow.loadURL(getTemplatePath());
notificationWindow.webContents.on('did-finish-load', function() {
// Done
notificationWindow.webContents.send('electron-notify-load-config', config)
notificationWindow.webContents.send('electron-notify-load-config', config);
resolve(notificationWindow)
})
}
})
}
/**
* Closes all the notifications and windows
*/
function closeAll() {
// Clear out animation Queue and close windows
animationQueue.clear();
@ -668,10 +722,13 @@ function closeAll() {
}
/**
/* once a minute, remove inactive windows to free up memory used.
* Once a minute, remove inactive windows to free up memory used.
*/
setInterval(cleanUpInactiveWindow, 60000);
/**
* Cleans up inactive windows
*/
function cleanUpInactiveWindow() {
inactiveWindows.forEach(function(window) {
window.close();
@ -679,6 +736,6 @@ function cleanUpInactiveWindow() {
inactiveWindows = [];
}
module.exports.notify = notify
module.exports.updateConfig = updateConfig
module.exports.reset = setupConfig
module.exports.notify = notify;
module.exports.updateConfig = updateConfig;
module.exports.reset = setupConfig;

View File

@ -51,6 +51,10 @@ class Notify {
this._data = options.data || null;
/**
* Handles on show event
* @param arg
*/
function onShow(arg) {
if (arg.id === this._id) {
log.send(logLevels.INFO, 'showing notification, id=' + this._id);
@ -61,6 +65,10 @@ class Notify {
}
}
/**
* Handles on click event
* @param arg
*/
function onClick(arg) {
if (arg.id === this._id) {
log.send(logLevels.INFO, 'clicking notification, id=' + this._id);
@ -70,6 +78,10 @@ class Notify {
}
}
/**
* Handles on close event
* @param arg
*/
function onClose(arg) {
if (arg.id === this._id || arg.event === 'close-all') {
log.send(logLevels.INFO, 'closing notification, id=' + this._id);
@ -80,6 +92,10 @@ class Notify {
}
}
/**
* Handles on error event
* @param arg
*/
function onError(arg) {
if (arg.id === this._id) {
// don't raise error event if handler doesn't exist, node
@ -95,7 +111,7 @@ class Notify {
}
/**
* close notification
* Closes notification
*/
close() {
if (typeof this._closeNotification === 'function') {
@ -105,7 +121,7 @@ class Notify {
}
/**
* always allow showing notifications.
* Always allow showing notifications.
* @return {string} 'granted'
*/
static get permission() {
@ -113,14 +129,14 @@ class Notify {
}
/**
* returns data object passed in via constructor options
* Returns data object passed in via constructor options
*/
get data() {
return this._data;
}
/**
* add event listeners for 'click', 'close', 'show', 'error' events
* Adds event listeners for 'click', 'close', 'show', 'error' events
*
* @param {String} event event to listen for
* @param {func} cb callback invoked when event occurs
@ -132,7 +148,7 @@ class Notify {
}
/**
* remove event listeners for 'click', 'close', 'show', 'error' events
* Removes event listeners for 'click', 'close', 'show', 'error' events
*
* @param {String} event event to stop listening for.
* @param {func} cb callback associated with original addEventListener
@ -144,7 +160,7 @@ class Notify {
}
/**
* removes all event listeners
* Removes all event listeners
*/
removeAllEvents() {
this.destroy();
@ -168,10 +184,10 @@ class Notify {
*/
function Queue(emitter) {
/**
* Cache emitter on.
* @api private
*/
var cache = emitter.on;
* Cache emitter on.
* @api private
*/
const cache = emitter.on;
let modifiedEmitter = emitter;
/**
* Emit event and store it if no
@ -180,7 +196,7 @@ function Queue(emitter) {
*
* .queue('message', 'hi');
*
* @param {String} event
* @param {String} topic
*/
modifiedEmitter.queue = function(topic) {
this._queue = this._queue || {};
@ -191,18 +207,18 @@ function Queue(emitter) {
(this._queue[topic] = this._queue[topic] || [])
.push([].slice.call(arguments, 1));
}
}
};
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @return {Event}
*/
modifiedEmitter.on = modifiedEmitter.addEventListener = function(topic, fn) {
this._queue = this._queue || {};
var topics = this._queue[topic];
const topics = this._queue[topic];
cache.apply(this, arguments);
if (!this._callbacks) {
@ -211,7 +227,9 @@ function Queue(emitter) {
this._callbacks[topic] = true;
if (topics) {
for(var i = 0, l = topics.length; i < l; i++) {
let i = 0;
const l = topics.length;
for(; i < l; i++) {
fn.apply(this, topics[i]);
}
delete this._queue[topic];

View File

@ -9,7 +9,9 @@ let selectedDisplay;
renderSettings();
// Method that renders the data from user config
/**
* Method that renders the data from user config
*/
function renderSettings() {
document.addEventListener('DOMContentLoaded', function () {
@ -33,6 +35,9 @@ function renderSettings() {
}
/**
* Updates the configuration and closes the alert
*/
function updateAndClose() {
ipc.send('update-config', {position: selectedPosition, display: selectedDisplay});
ipc.send('close-alert');

View File

@ -15,7 +15,7 @@
<label class="label">Monitor</label>
<div id="screens" class="main">
<label>Notification shown on Monitor: </label>
<select class="selector" id="screen-selector">
<select class="selector" id="screen-selector" title="position">
</select>
</div>
<label class="label">Position</label>

View File

@ -41,6 +41,9 @@ app.on('ready', () => {
electron.screen.on('display-removed', updateScreens);
});
/**
* Update all the screens
*/
function updateScreens() {
screens = electron.screen.getAllDisplays();
@ -50,6 +53,10 @@ function updateScreens() {
}
}
/**
* Gets the template path
* @returns {string}
*/
function getTemplatePath() {
let templatePath = path.join(__dirname, 'configure-notification-position.html');
try {
@ -60,6 +67,10 @@ function getTemplatePath() {
return 'file://' + templatePath;
}
/**
* Opens the configuration window for a specific window
* @param windowName
*/
function openConfigurationWindow(windowName) {
let allWindows = BrowserWindow.getAllWindows();
allWindows = allWindows.find((window) => { return window.winName === windowName });
@ -94,6 +105,9 @@ function openConfigurationWindow(windowName) {
});
}
/**
* Destroys a window
*/
function destroyWindow() {
configurationWindow = null;
}

View File

@ -19,7 +19,7 @@ const apiCmds = apiEnums.cmds;
const apiName = apiEnums.apiName;
const getMediaSources = require('../desktopCapturer/getSources');
require('../downloadManager/downloadManager');
require('../downloadManager');
// bug in electron preventing us from using spellchecker in pop outs
// https://github.com/electron/electron/issues/4025
@ -28,7 +28,7 @@ require('../downloadManager/downloadManager');
document.addEventListener('DOMContentLoaded', () => {
try {
/* eslint-disable global-require */
const SpellCheckerHelper = require('../spellChecker/spellChecker').SpellCheckHelper;
const SpellCheckerHelper = require('../spellChecker').SpellCheckHelper;
/* eslint-enable global-require */
// Method to initialize spell checker
const spellChecker = new SpellCheckerHelper();
@ -72,11 +72,11 @@ function createAPI() {
// A tags are allowed if they include href='_blank', this cause 'new-window'
// event to be received which is handled properly in windowMgr.js
window.addEventListener('beforeunload', function(event) {
var newUrl = document.activeElement && document.activeElement.href;
let newUrl = document.activeElement && document.activeElement.href;
if (newUrl) {
var currHostName = window.location.hostname;
var parsedNewUrl = nodeURL.parse(newUrl);
var parsedNewUrlHostName = parsedNewUrl && parsedNewUrl.hostname;
let currHostName = window.location.hostname;
let parsedNewUrl = nodeURL.parse(newUrl);
let parsedNewUrlHostName = parsedNewUrl && parsedNewUrl.hostname;
if (currHostName !== parsedNewUrlHostName) {
/* eslint-disable no-param-reassign */
event.returnValue = 'false';
@ -95,14 +95,14 @@ function createAPI() {
window.ssf = {
getVersionInfo: function() {
return new Promise(function(resolve) {
var appName = remote.app.getName();
var appVer = remote.app.getVersion();
let appName = remote.app.getName();
let appVer = remote.app.getVersion();
const verInfo = {
containerIdentifier: appName,
containerVer: appVer,
apiVer: '1.0.0'
}
};
resolve(verInfo);
});
},
@ -126,9 +126,9 @@ function createAPI() {
/**
* provides api to allow user to capture portion of screen, see api
* details in screenSnipper/ScreenSnippet.js
* details in screenSnipper/index.js
*/
ScreenSnippet: remote.require('./screenSnippet/ScreenSnippet.js').ScreenSnippet,
ScreenSnippet: remote.require('./screenSnippet/index.js').ScreenSnippet,
/**
* Brings window forward and gives focus.
@ -191,7 +191,7 @@ function createAPI() {
* this registration func is invoked then the protocolHandler callback
* will be immediately called.
*/
registerProtocolHandler: function (protocolHandler) {
registerProtocolHandler: function(protocolHandler) {
if (typeof protocolHandler === 'function') {
local.processProtocolAction = protocolHandler;
@ -347,4 +347,4 @@ function createAPI() {
window.addEventListener('online', updateOnlineStatus, false);
updateOnlineStatus();
}
}

View File

@ -43,6 +43,10 @@ function setProtocolUrl(uri) {
protocolUrl = uri;
}
/**
* gets the protocol url set against an instance
* @returns {*}
*/
function getProtocolUrl() {
return protocolUrl;
}

View File

@ -47,21 +47,21 @@ class ScreenSnippet {
// utilize Mac OSX built-in screencapture tool which has been
// available since OSX ver 10.2.
captureUtil = '/usr/sbin/screencapture';
captureUtilArgs = [ '-i', '-s', '-t', 'jpg', outputFileName ];
captureUtilArgs = ['-i', '-s', '-t', 'jpg', outputFileName];
} else {
// use custom built windows screen capture tool
if (isDevEnv) {
// for dev env pick up tool from node nodules
captureUtil =
path.join(__dirname,
'../../node_modules/screen-snippet/bin/Release/ScreenSnippet.exe');
'../../node_modules/screen-snippet/bin/Release/ScreenSnippet.exe');
} else {
// for production gets installed next to exec.
let execPath = path.dirname(app.getPath('exe'));
captureUtil = path.join(execPath, 'ScreenSnippet.exe');
}
captureUtilArgs = [ outputFileName ];
captureUtilArgs = [outputFileName];
}
log.send(logLevels.INFO, 'ScreenSnippet: starting screen capture util: ' + captureUtil + ' with args=' + captureUtilArgs);
@ -84,9 +84,15 @@ class ScreenSnippet {
}
}
// this function was moved outside of class since class is exposed to web
// client via preload API, we do NOT want web client to be able to call this
// method - then they could read any file on the disk!
/**
* this function was moved outside of class since class is exposed to web
* client via preload API, we do NOT want web client to be able to call this
* method - then they could read any file on the disk!
* @param outputFileName
* @param resolve
* @param reject
* @param childProcessErr
*/
function readResult(outputFileName, resolve, reject, childProcessErr) {
fs.readFile(outputFileName, (readErr, data) => {
if (readErr) {
@ -120,8 +126,7 @@ function readResult(outputFileName, resolve, reject, childProcessErr) {
});
} catch (error) {
reject(createError(error));
}
finally {
} finally {
// remove tmp file (async)
fs.unlink(outputFileName, function(removeErr) {
// note: node complains if calling async
@ -136,14 +141,24 @@ function readResult(outputFileName, resolve, reject, childProcessErr) {
}
/* eslint-disable class-methods-use-this */
/**
* Create an error object with the ERROR level
* @param msg
* @returns {Error}
*/
function createError(msg) {
var err = new Error(msg);
let err = new Error(msg);
err.type = 'ERROR';
return err;
}
/**
* Create an error object with the WARN level
* @param msg
* @returns {Error}
*/
function createWarn(msg) {
var err = new Error(msg);
let err = new Error(msg);
err.type = 'WARN';
return err;
}
@ -153,4 +168,4 @@ module.exports = {
ScreenSnippet: ScreenSnippet,
// note: readResult only exposed for testing purposes
readResult: readResult
}
};

View File

@ -5,6 +5,9 @@ const { SpellCheckHandler, ContextMenuListener, ContextMenuBuilder } = require('
class SpellCheckHelper {
/**
* A constructor to create an instance of the spell checker
*/
constructor() {
this.spellCheckHandler = new SpellCheckHandler();
}

View File

@ -7,7 +7,7 @@ const logLevels = require('../enums/logLevels.js');
* Search given argv for argName using exact match or starts with.
* @param {Array} argv Array of strings
* @param {String} argName Arg name to search for.
* @param {bool} exactMatch If true then look for exact match otherwise
* @param {Boolean} exactMatch If true then look for exact match otherwise
* try finding arg that starts with argName.
* @return {String} If found, returns the arg, otherwise null.
*/
@ -26,4 +26,5 @@ function getCmdLineArg(argv, argName, exactMatch) {
return null;
}
module.exports = getCmdLineArg
module.exports = getCmdLineArg;

View File

@ -7,12 +7,11 @@
* @return {String} guid value in string
*/
function getGuid() {
const guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
function(c) {
var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
function (c) {
let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
return guid;
}
module.exports = getGuid;

View File

@ -5,17 +5,17 @@ const { isMac } = require('./misc.js');
const log = require('../log.js');
const logLevels = require('../enums/logLevels.js');
var Registry = require('winreg');
var symphonyRegistryHKCU = new Registry({
let Registry = require('winreg');
let symphonyRegistryHKCU = new Registry({
hive: Registry.HKCU,
key: symphonyRegistry
});
var symphonyRegistryHKLM = new Registry({
let symphonyRegistryHKLM = new Registry({
key: symphonyRegistry
});
var symphonyRegistryHKLM6432 = new Registry({
let symphonyRegistryHKLM6432 = new Registry({
key: symphonyRegistry.replace('\\Software','\\Software\\WOW6432Node')
});
@ -24,24 +24,24 @@ var symphonyRegistryHKLM6432 = new Registry({
* that are intended to be used as global (or default) value for all users
* running this app.
*/
var getRegistry = function (name) {
var promise = new Promise(function(resolve, reject) {
let getRegistry = function (name) {
return new Promise(function (resolve, reject) {
if (isMac) {
reject('registry is not supported for mac osx.');
return;
}
//Try to get registry on HKEY_CURRENT_USER
symphonyRegistryHKCU.get( name, function( err1, reg1 ) {
if (!err1 && reg1 !==null && reg1.value) {
symphonyRegistryHKCU.get(name, function (err1, reg1) {
if (!err1 && reg1 !== null && reg1.value) {
log.send(logLevels.WARN, 'getRegistry: Cannot find ' + name + ' Registry. Using HKCU');
resolve(reg1.value);
return;
}
//Try to get registry on HKEY_LOCAL_MACHINE
symphonyRegistryHKLM.get( name, function( err2, reg2 ) {
if ( !err2 && reg2!==null && reg2.value) {
symphonyRegistryHKLM.get(name, function (err2, reg2) {
if (!err2 && reg2 !== null && reg2.value) {
log.send(logLevels.WARN, 'getRegistry: Cannot find ' + name + ' Registry. Using HKLM');
resolve(reg2.value);
return;
@ -49,18 +49,16 @@ var getRegistry = function (name) {
// Try to get registry on HKEY_LOCAL_MACHINE in case 32bit app installed on 64bit system.
// winreg does not merge keys as normally windows does.
symphonyRegistryHKLM6432.get( name, function( err3, reg3 ) {
if ( !err3 && reg3!==null && reg3.value) {
symphonyRegistryHKLM6432.get(name, function (err3, reg3) {
if (!err3 && reg3 !== null && reg3.value) {
resolve(reg3.value);
} else{
} else {
reject('Cannot find PodUrl Registry. Using default url.');
}
});
});
});
});
};
return promise;
}
module.exports = getRegistry
module.exports = getRegistry;

View File

@ -1,4 +1,4 @@
'use strict'
'use strict';
const electron = require('electron');
@ -6,8 +6,8 @@ const electron = require('electron');
/**
* Returns true if given rectangle is contained within the workArea of at
* least one of the screens.
* @param {x: Number, y: Number, width: Number, height: Number} rect
* @return {Boolean} true if condition in desc is met.
* @param {Object} rect - ex:- {x: Number, y: Number, width: Number, height: Number}
* @return {Boolean} true if condition in desc is met.
*/
function isInDisplayBounds(rect) {
if (!rect) {

View File

@ -42,18 +42,36 @@ const preloadMainScript = path.join(__dirname, 'preload/_preloadMain.js');
const MIN_WIDTH = 300;
const MIN_HEIGHT = 600;
/**
* Adds a window key
* @param key
* @param browserWin
*/
function addWindowKey(key, browserWin) {
windows[key] = browserWin;
}
/**
* Removes a window key
* @param key
*/
function removeWindowKey(key) {
delete windows[key];
}
/**
* Gets the parsed url
* @param url
* @returns {Url}
*/
function getParsedUrl(url) {
return nodeURL.parse(url);
}
/**
* Creates the main window
* @param initialUrl
*/
function createMainWindow(initialUrl) {
getConfigField('mainWinPos').then(
function (bounds) {
@ -66,6 +84,11 @@ function createMainWindow(initialUrl) {
)
}
/**
* Creates the main window with bounds
* @param initialUrl
* @param initialBounds
*/
function doCreateMainWindow(initialUrl, initialBounds) {
let url = initialUrl;
let key = getGuid();
@ -179,7 +202,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
function destroyAllWindows() {
let keys = Object.keys(windows);
for (var i = 0, len = keys.length; i < len; i++) {
for (let i = 0, len = keys.length; i < len; i++) {
let winKey = keys[i];
removeWindowKey(winKey);
}
@ -247,7 +270,7 @@ function doCreateMainWindow(initialUrl, initialBounds) {
let height = newWinOptions.height || MIN_HEIGHT;
// try getting x and y position from query parameters
var query = newWinParsedUrl && querystring.parse(newWinParsedUrl.query);
let query = newWinParsedUrl && querystring.parse(newWinParsedUrl.query);
if (query && query.x && query.y) {
let newX = Number.parseInt(query.x, 10);
let newY = Number.parseInt(query.y, 10);
@ -318,10 +341,16 @@ function doCreateMainWindow(initialUrl, initialBounds) {
}
/**
* Handles the event before-quit emitted by electron
*/
app.on('before-quit', function () {
willQuitApp = true;
});
/**
* Saves the main window bounds
*/
function saveMainWinBounds() {
let newBounds = getWindowSizeAndPosition(mainWindow);
@ -330,10 +359,19 @@ function saveMainWinBounds() {
}
}
/**
* Gets the main window
* @returns {*}
*/
function getMainWindow() {
return mainWindow;
}
/**
* Gets a window's size and position
* @param window
* @returns {*}
*/
function getWindowSizeAndPosition(window) {
if (window) {
let newPos = window.getPosition();
@ -353,14 +391,28 @@ function getWindowSizeAndPosition(window) {
return null;
}
/**
* Shows the main window
*/
function showMainWindow() {
mainWindow.show();
}
/**
* Tells if a window is the main window
* @param win
* @returns {boolean}
*/
function isMainWindow(win) {
return mainWindow === win;
}
/**
* Checks if the window and a key has a window
* @param win
* @param winKey
* @returns {*}
*/
function hasWindow(win, winKey) {
if (win instanceof BrowserWindow) {
let browserWin = windows[winKey];
@ -370,6 +422,10 @@ function hasWindow(win, winKey) {
return false;
}
/**
* Sets if a user is online
* @param status
*/
function setIsOnline(status) {
isOnline = status;
}
@ -417,6 +473,10 @@ function sendChildWinBoundsChange(window) {
}
}
/**
* Opens an external url in the system's default browser
* @param urlToOpen
*/
function openUrlInDefaultBrower(urlToOpen) {
if (urlToOpen) {
electron.shell.openExternal(urlToOpen);
@ -514,11 +574,8 @@ function checkExternalDisplay(appBounds) {
return false;
}
if (rightMost > bounds.x + bounds.width || bottomMost > bounds.y + bounds.height) {
return false;
}
return !(rightMost > bounds.x + bounds.width || bottomMost > bounds.y + bounds.height);
return true;
});
}

View File

@ -1,112 +1,112 @@
{
"name": "Symphony",
"productName": "Symphony",
"version": "1.0.1",
"description": "Symphony desktop app (Foundation ODP)",
"author": "Symphony",
"main": "js/main.js",
"scripts": {
"dev": "npm run prebuild && cross-env ELECTRON_DEV=true electron .",
"demo-win": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file:///demo/index.html",
"demo-mac": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file://$(pwd)/demo/index.html",
"unpacked-mac": "npm run prebuild && npm run test && build --mac --dir",
"packed-mac": "npm run unpacked-mac && packagesbuild -v installer/mac/symphony-mac-packager.pkgproj",
"unpacked-win": "npm run prebuild && npm run test && build --win --x64 --dir",
"unpacked-win-x86": "npm run prebuild && npm run test && build --win --ia32",
"prebuild": "npm run rebuild && npm run browserify-preload",
"browserify-preload": "browserify -o js/preload/_preloadMain.js -x electron --insert-global-vars=__filename,__dirname js/preload/preloadMain.js --exclude electron-spellchecker",
"rebuild": "electron-rebuild -f",
"test": "npm run lint && jest --verbose --testPathPattern test && npm run rebuild",
"spectron-test": "jest --config tests/spectron/jest_spectron.json --runInBand && npm run rebuild",
"lint": "eslint --ext .js js/",
"rename-exe": "cd dist/win-unpacked && ren Symphony.exe Symphony-Electron.exe"
},
"jest": {
"collectCoverage": true,
"transformIgnorePatterns": [
]
},
"build": {
"asarUnpack": [
"node_modules/@paulcbetts/cld/build/Release/cld.node"
],
"files": [
"!coverage/*",
"!installer/*",
"!tests/*",
"!node_modules/@paulcbetts/cld/deps/cld${/*}",
"!node_modules/@paulcbetts/cld/build/deps${/*}",
"!node_modules/@paulcbetts/spellchecker/vendor${/*}"
],
"extraFiles": "config/Symphony.config",
"appId": "symphony-electron-desktop",
"mac": {
"target": "dmg",
"category": "public.app-category.business"
},
"dmg": {
"contents": [{
"x": 140,
"y": 184
},
{
"x": 412,
"y": 184,
"type": "link",
"path": "/Applications"
}
]
},
"win": {
"target": "squirrel"
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/SymphonyOSS/SymphonyElectron.git"
},
"keywords": [
"Symphony",
"start"
"name": "Symphony",
"productName": "Symphony",
"version": "1.0.1",
"description": "Symphony desktop app (Foundation ODP)",
"author": "Symphony",
"main": "js/main.js",
"scripts": {
"dev": "npm run prebuild && cross-env ELECTRON_DEV=true electron .",
"demo-win": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file:///demo/index.html",
"demo-mac": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file://$(pwd)/demo/index.html",
"unpacked-mac": "npm run prebuild && npm run test && build --mac --dir",
"packed-mac": "npm run unpacked-mac && packagesbuild -v installer/mac/symphony-mac-packager.pkgproj",
"unpacked-win": "npm run prebuild && npm run test && build --win --x64 --dir",
"unpacked-win-x86": "npm run prebuild && npm run test && build --win --ia32",
"prebuild": "npm run rebuild && npm run browserify-preload",
"browserify-preload": "browserify -o js/preload/_preloadMain.js -x electron --insert-global-vars=__filename,__dirname js/preload/preloadMain.js --exclude electron-spellchecker",
"rebuild": "electron-rebuild -f",
"test": "npm run lint && jest --verbose --testPathPattern test && npm run rebuild",
"spectron-test": "jest --config tests/spectron/jest_spectron.json --runInBand && npm run rebuild",
"lint": "eslint --ext .js js/",
"rename-exe": "cd dist/win-unpacked && ren Symphony.exe Symphony-Electron.exe"
},
"jest": {
"collectCoverage": true,
"transformIgnorePatterns": []
},
"build": {
"asarUnpack": [
"node_modules/@paulcbetts/cld/build/Release/cld.node"
],
"license": "Apache-2.0",
"bugs": {
"url": "https://support.symphony.com"
"files": [
"!coverage/*",
"!installer/*",
"!tests/*",
"!node_modules/@paulcbetts/cld/deps/cld${/*}",
"!node_modules/@paulcbetts/cld/build/deps${/*}",
"!node_modules/@paulcbetts/spellchecker/vendor${/*}"
],
"extraFiles": "config/Symphony.config",
"appId": "symphony-electron-desktop",
"mac": {
"target": "dmg",
"category": "public.app-category.business"
},
"devDependencies": {
"browserify": "^14.1.0",
"cross-env": "^3.2.4",
"electron": "1.7.5",
"electron-builder": "^13.9.0",
"electron-builder-squirrel-windows": "^12.3.0",
"electron-packager": "^8.5.2",
"electron-rebuild": "^1.5.7",
"eslint": "^3.16.1",
"eslint-config-airbnb": "^14.1.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.0",
"jest": "^19.0.2",
"ncp": "^2.0.0",
"robotjs": "^0.4.7",
"spectron": "^3.7.2"
"dmg": {
"contents": [
{
"x": 140,
"y": 184
},
{
"x": 412,
"y": 184,
"type": "link",
"path": "/Applications"
}
]
},
"dependencies": {
"@paulcbetts/system-idle-time": "^1.0.4",
"appdirectory": "^0.1.0",
"async.map": "^0.5.2",
"async.mapseries": "^0.5.2",
"auto-launch": "^5.0.1",
"electron-dl": "^1.9.0",
"electron-spellchecker": "^1.2.0",
"electron-squirrel-startup": "^1.0.0",
"filesize": "^3.5.10",
"keymirror": "0.1.1",
"lodash.pick": "^4.4.0",
"winreg": "^1.2.3"
},
"optionalDependencies": {
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet.git#v1.0.1"
"win": {
"target": "squirrel"
}
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/SymphonyOSS/SymphonyElectron.git"
},
"keywords": [
"Symphony",
"start"
],
"license": "Apache-2.0",
"bugs": {
"url": "https://support.symphony.com"
},
"devDependencies": {
"browserify": "^14.1.0",
"cross-env": "^3.2.4",
"electron": "1.7.5",
"electron-builder": "^13.9.0",
"electron-builder-squirrel-windows": "^12.3.0",
"electron-packager": "^8.5.2",
"electron-rebuild": "^1.5.7",
"eslint": "^3.16.1",
"eslint-config-airbnb": "^14.1.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.0",
"jest": "^19.0.2",
"ncp": "^2.0.0",
"robotjs": "^0.4.7",
"spectron": "^3.7.2"
},
"dependencies": {
"@paulcbetts/system-idle-time": "^1.0.4",
"appdirectory": "^0.1.0",
"async.map": "^0.5.2",
"async.mapseries": "^0.5.2",
"auto-launch": "^5.0.1",
"electron-dl": "^1.9.0",
"electron-log": "^2.2.7",
"electron-spellchecker": "^1.2.0",
"electron-squirrel-startup": "^1.0.0",
"filesize": "^3.5.10",
"keymirror": "0.1.1",
"lodash.pick": "^4.4.0",
"winreg": "^1.2.3"
},
"optionalDependencies": {
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet.git#v1.0.1"
}
}

View File

@ -1,21 +1,21 @@
const downloadManager = require('../js/downloadManager/downloadManager');
const downloadManager = require('../js/downloadManager');
const electron = require('./__mocks__/electron');
describe('download manager', function () {
describe('Download Manager to create DOM once download is initiated', function () {
beforeEach(function () {
describe('download manager', function() {
describe('Download Manager to create DOM once download is initiated', function() {
beforeEach(function() {
global.document.body.innerHTML =
'<div id="download-main">' +
'</div>';
});
it('should inject download bar element into DOM once download is initiated', function () {
it('should inject download bar element into DOM once download is initiated', function() {
electron.ipcRenderer.send('downloadCompleted', { _id: '12345', fileName: 'test', total: 100 });
expect(document.getElementsByClassName('text-cutoff')[0].innerHTML).toBe('test');
expect(document.getElementById('per').innerHTML).toBe('100 Downloaded');
});
it('should inject multiple download items during multiple downloads', function () {
it('should inject multiple download items during multiple downloads', function() {
electron.ipcRenderer.send('downloadCompleted', { _id: '12345', fileName: 'test', total: 100 });
electron.ipcRenderer.send('downloadCompleted', { _id: '67890', fileName: 'test1', total: 200 });
@ -31,23 +31,23 @@ describe('download manager', function () {
});
describe('Download Manager to initiate footer', function () {
beforeEach(function () {
describe('Download Manager to initiate footer', function() {
beforeEach(function() {
global.document.body.innerHTML =
'<div id="footer" class="hidden">' +
'<div id="download-manager-footer">' +
'<div id="download-main">' +
'</div>' +
'</div>' +
'<div id="download-manager-footer">' +
'<div id="download-main">' +
'</div>' +
'</div>' +
'</div>';
});
it('should inject dom element once download is completed', function () {
it('should inject dom element once download is completed', function() {
electron.ipcRenderer.send('downloadProgress');
expect(document.getElementById('footer').classList).not.toContain('hidden');
});
it('should remove the download bar and clear up the download items', function () {
it('should remove the download bar and clear up the download items', function() {
electron.ipcRenderer.send('downloadProgress');
expect(document.getElementById('footer').classList).not.toContain('hidden');
@ -59,19 +59,19 @@ describe('download manager', function () {
});
describe('Download Manager to initiate footer', function () {
describe('Download Manager to initiate footer', function() {
beforeEach(function () {
beforeEach(function() {
global.document.body.innerHTML =
'<div id="footer" class="hidden">' +
'<div id="download-manager-footer">' +
'<div id="download-main">' +
'</div>' +
'</div>' +
'<div id="download-manager-footer">' +
'<div id="download-main">' +
'</div>' +
'</div>' +
'</div>';
});
it('should inject ul element if not found', function () {
it('should inject ul element if not found', function() {
electron.ipcRenderer.send('downloadProgress');

View File

@ -1,10 +1,9 @@
const { ScreenSnippet, readResult } = require('../js/screenSnippet/ScreenSnippet.js');
const { ScreenSnippet, readResult } = require('../js/screenSnippet');
const path = require('path');
const fs = require('fs');
const os = require('os');
const { isMac } = require('../js/utils/misc.js')
const { isMac } = require('../js/utils/misc.js');
const snippetBase64 = require('./fixtures/snippet/snippet-base64.js');
@ -27,7 +26,7 @@ function mockedExecFile(util, args, doneCallback) {
}
function copyTestFile(destFile, done) {
const testfile = path.join(__dirname ,
const testfile = path.join(__dirname,
'fixtures/snippet/ScreenSnippet.jpeg');
let reader = fs.createReadStream(testfile);
@ -43,7 +42,7 @@ function copyTestFile(destFile, done) {
function createTestFile(done) {
let tmpDir = os.tmpdir();
const testFileName = path.join(tmpDir,
'ScreenSnippet-' + Date.now() + '.jpeg');
'ScreenSnippet-' + Date.now() + '.jpeg');
copyTestFile(testFileName, function() {
done(testFileName)
@ -65,7 +64,7 @@ describe('Tests for ScreenSnippet', function() {
expect(rsp.type).toEqual('image/jpg;base64');
expect(rsp.data).toEqual(snippetBase64);
done();
};
}
});
}
@ -104,7 +103,7 @@ describe('Tests for ScreenSnippet', function() {
// skip test for windows - until feature is supported
if (isMac) {
it('should fail if read file fails', function(done) {
var origFsReadFile = fs.readFile;
const origFsReadFile = fs.readFile;
fs.readFile = jest.fn(mockedReadFile);
@ -132,4 +131,4 @@ describe('Tests for ScreenSnippet', function() {
}
});
}
});
});

View File

@ -29,7 +29,7 @@ const ipcMain = {
ipcEmitter.on(event, cb);
},
send: function (event, args) {
var senderEvent = {
const senderEvent = {
sender: {
send: function (event, arg) {
ipcEmitter.emit(event, arg);
@ -45,16 +45,16 @@ const ipcRenderer = {
let listeners = ipcEmitter.listeners(event);
if (listeners.length > 0) {
let listener = listeners[0];
var eventArg = {};
const eventArg = {};
listener(eventArg, args);
return eventArg.returnValue;
}
return null;
},
send: function(event, args) {
var senderEvent = {
const senderEvent = {
sender: {
send: function(event, arg) {
send: function (event, arg) {
ipcEmitter.emit(event, arg);
}
}

View File

@ -3,29 +3,29 @@ const childProcess = require('child_process');
let activityDetection;
describe('Tests for Activity Detection', function () {
describe('Tests for Activity Detection', function() {
var originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
const originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
beforeAll(function (done) {
childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function (err) {
activityDetection = require('../js/activityDetection/activityDetection.js');
beforeAll(function(done) {
childProcess.exec(`npm rebuild --target=${process.version} --build-from-source`, function(err) {
activityDetection = require('../js/activityDetection');
activityDetection.setActivityWindow(900000, electron.ipcRenderer);
done();
});
});
beforeEach(function () {
beforeEach(function() {
jest.clearAllMocks()
});
afterAll(function (done) {
afterAll(function(done) {
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
done();
});
it('should return null', function () {
it('should return null', function() {
activityDetection.setActivityWindow(0, electron.ipcRenderer);
const noData = activityDetection.activityDetection();
@ -33,17 +33,17 @@ describe('Tests for Activity Detection', function () {
});
it('should send activity event', function () {
it('should send activity event', function() {
const spy = jest.spyOn(activityDetection, 'send');
expect(spy).not.toBeCalled();
activityDetection.send({systemIdleTime: 120000});
expect(spy).toHaveBeenCalledWith({systemIdleTime: 120000});
activityDetection.send({ systemIdleTime: 120000 });
expect(spy).toHaveBeenCalledWith({ systemIdleTime: 120000 });
});
it('should monitor user activity', function () {
it('should monitor user activity', function() {
activityDetection.setActivityWindow(500000, electron.ipcRenderer);
const spy = jest.spyOn(activityDetection, 'monitorUserActivity');
@ -54,7 +54,7 @@ describe('Tests for Activity Detection', function () {
});
it('should not send activity event as data is undefined', function () {
it('should not send activity event as data is undefined', function() {
const spy = jest.spyOn(activityDetection, 'send');
expect(spy).not.toBeCalled();
@ -64,4 +64,4 @@ describe('Tests for Activity Detection', function () {
});
});
});

View File

@ -62,13 +62,13 @@ describe('read/write config tests', function() {
}
function createTempUserConfig(config) {
var tmpDir = os.tmpdir();
const tmpDir = os.tmpdir();
userConfigDir = fs.mkdtempSync(path.join(tmpDir, 'config-'));
return createTempConfigFile(path.join(userConfigDir, configFileName), config);
}
function createTempGlobalConfig(config) {
var tmpDir = os.tmpdir();
const tmpDir = os.tmpdir();
globalConfigDir = path.join(fs.mkdtempSync(path.join(tmpDir, 'config-')), 'config');
fs.mkdirSync(globalConfigDir);
return createTempConfigFile(path.join(globalConfigDir, configFileName), config);
@ -80,15 +80,15 @@ describe('read/write config tests', function() {
describe('getConfigField tests', function() {
it('should fail when field not present in either user or global config', function() {
var userConfig = {
const userConfig = {
url: 'something'
}
};
createTempUserConfig(userConfig);
var globalConfig = {
const globalConfig = {
url: 'something-else'
}
};
createTempGlobalConfig(globalConfig);
@ -98,9 +98,9 @@ describe('read/write config tests', function() {
});
it('should succeed when field only present in user config', function() {
var userConfig = {
const userConfig = {
url: 'something'
}
};
createTempUserConfig(userConfig);
@ -110,9 +110,9 @@ describe('read/write config tests', function() {
});
it('should succeed when field only present in global config', function() {
var globalConfig = {
const globalConfig = {
url: 'something-else'
}
};
createTempGlobalConfig(globalConfig);
@ -122,15 +122,15 @@ describe('read/write config tests', function() {
});
it('should succeed and return user config field when value is in both', function() {
var userConfig = {
const userConfig = {
url: 'something'
}
};
createTempUserConfig(userConfig);
var globalConfig = {
const globalConfig = {
url: 'something-else'
}
};
createTempGlobalConfig(globalConfig);
@ -140,7 +140,7 @@ describe('read/write config tests', function() {
});
it('should fail when global config path is invalid', function() {
var globalConfig = {
const globalConfig = {
url: 'something-else'
};
createTempGlobalConfig(globalConfig);
@ -155,7 +155,7 @@ describe('read/write config tests', function() {
});
it('should fail when user config path is invalid', function() {
var userConfig = {
const userConfig = {
url: 'something'
};
createTempUserConfig(userConfig);
@ -170,12 +170,12 @@ describe('read/write config tests', function() {
});
it('should read cached user config value rather than reading file from disk again', function(done) {
var userConfig = {
const userConfig = {
url: 'qa4.symphony.com'
};
createTempUserConfig(userConfig);
var userConfig2 = {
const userConfig2 = {
url: 'qa5.symphony.com'
};
@ -193,12 +193,12 @@ describe('read/write config tests', function() {
});
it('should read cache global config value rather than reading file from disk again', function(done) {
var globalConfig = {
const globalConfig = {
url: 'qa8.symphony.com'
};
createTempGlobalConfig(globalConfig);
var globalConfig2 = {
const globalConfig2 = {
url: 'qa9.symphony.com'
};
@ -220,7 +220,7 @@ describe('read/write config tests', function() {
describe('updateConfigField tests', function() {
it('should succeed and overwrite existing field', function() {
var userConfig = {
const userConfig = {
url: 'something'
};
@ -235,7 +235,7 @@ describe('read/write config tests', function() {
});
it('should succeed and add new field', function() {
var userConfig = {
const userConfig = {
url: 'something'
};
@ -252,7 +252,7 @@ describe('read/write config tests', function() {
it('should fail to update if invalid field name', function() {
var userConfig = {
const userConfig = {
url: 'something'
};
@ -277,7 +277,7 @@ describe('read/write config tests', function() {
it('should throw error if fieldName is not defined', function() {
var userConfig = {
const userConfig = {
url: 'something'
};
@ -291,7 +291,7 @@ describe('read/write config tests', function() {
it('should throw error if config is not defined', function() {
var userConfig = {
const userConfig = {
url: 'something'
};

View File

@ -1,5 +1,5 @@
// base64 conversion of file ScreenSnippet.jpeg
const base64ScreenSnippet =
"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";
module.exports = base64ScreenSnippet
module.exports = base64ScreenSnippet;

View File

@ -21,7 +21,6 @@ describe('Tests for Bring to front', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
}

View File

@ -20,7 +20,6 @@ describe('Tests for clipboard', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
}

View File

@ -22,7 +22,6 @@ describe('Tests for Close', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
} else {

View File

@ -19,7 +19,6 @@ describe('Tests for Full screen', () => {
return app.startApplication().then((startedApp) => {
app = startedApp;
getConfigPath().then((config) => {
console.log(config);
configPath = config;
done();
}).catch((err) => {
@ -54,7 +53,6 @@ describe('Tests for Full screen', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
} else {
@ -99,7 +97,6 @@ describe('Tests for Full screen', () => {
app.browserWindow.focus();
return app.browserWindow.setAlwaysOnTop(true).then(() => {
return app.browserWindow.isAlwaysOnTop().then((isOnTop) => {
console.log(isOnTop);
expect(isOnTop).toBeTruthy();
});
});

View File

@ -19,7 +19,6 @@ describe('Tests for Minimize on Close', () => {
return app.startApplication().then((startedApp) => {
app = startedApp;
getConfigPath().then((config) => {
console.log(config);
configPath = config;
done();
}).catch((err) => {
@ -54,7 +53,6 @@ describe('Tests for Minimize on Close', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
} else {
@ -99,7 +97,6 @@ describe('Tests for Minimize on Close', () => {
app.browserWindow.focus();
return app.browserWindow.setAlwaysOnTop(true).then(() => {
return app.browserWindow.isAlwaysOnTop().then((isOnTop) => {
console.log(isOnTop);
expect(isOnTop).toBeTruthy();
});
});

View File

@ -23,7 +23,6 @@ describe('Tests for Notification position', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
}

View File

@ -24,7 +24,6 @@ class App {
return this.app.start().then((app) => {
return app;
}).catch((err) => {
console.log(err);
});
}

View File

@ -26,7 +26,6 @@ describe('Tests for spellChecker', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
}

View File

@ -53,7 +53,6 @@ describe('Tests for Zoom in and Zoom out', () => {
app.stop().then(() => {
done();
}).catch((err) => {
console.log(err);
done();
});
} else {
@ -111,7 +110,7 @@ describe('Tests for Zoom in and Zoom out', () => {
robot.keyToggle('0', 'up');
robot.keyToggle('command', 'up');
for (var i = 0; i < 4; i++) {
for (let i = 0; i < 4; i++) {
robot.keyToggle('+', 'down', ['command']);
}
robot.keyToggle('+', 'up');
@ -134,7 +133,7 @@ describe('Tests for Zoom in and Zoom out', () => {
robot.keyToggle('0', 'up');
robot.keyToggle('control', 'up');
for (var i = 0; i < 4; i++) {
for (let i = 0; i < 4; i++) {
robot.keyToggle('+', 'down', ['control', 'shift']);
}
robot.keyToggle('+', 'up');
@ -159,7 +158,7 @@ describe('Tests for Zoom in and Zoom out', () => {
robot.keyToggle('0', 'up');
robot.keyToggle('command', 'up');
for (var i = 0; i < 4; i++) {
for (let i = 0; i < 4; i++) {
robot.keyToggle('-', 'down', ['command']);
}
robot.keyToggle('-', 'up');
@ -183,7 +182,7 @@ describe('Tests for Zoom in and Zoom out', () => {
robot.keyToggle('0', 'up');
robot.keyToggle('control', 'up');
for (var i = 0; i < 4; i++) {
for (let i = 0; i < 4; i++) {
robot.keyToggle('-', 'down', ['control']);
}
robot.keyToggle('-', 'up');

View File

@ -2,27 +2,27 @@ const getCmdLineArg = require('../../js/utils/getCmdLineArg.js');
describe('getCmdLineArg tests', function() {
it('should return no exact match', function() {
var result = getCmdLineArg([ 'hello.exe', '--arg1', '--arg2'], '--arg', true);
const result = getCmdLineArg(['hello.exe', '--arg1', '--arg2'], '--arg', true);
expect(result).toBe(null);
});
it('should return exact match only', function() {
var result = getCmdLineArg([ 'hello.exe', '--arg1', '--arg2'], '--arg2', true);
const result = getCmdLineArg(['hello.exe', '--arg1', '--arg2'], '--arg2', true);
expect(result).toBe('--arg2');
});
it('should return starts with match', function() {
var result = getCmdLineArg([ 'hello.exe', '--hello=test', '--arg2'], '--hello=');
const result = getCmdLineArg(['hello.exe', '--hello=test', '--arg2'], '--hello=', false);
expect(result).toBe('--hello=test');
});
it('should return no match for starts with', function() {
var result = getCmdLineArg([ 'hello.exe', '--hello=test', '--arg2'], '--help=');
const result = getCmdLineArg(['hello.exe', '--hello=test', '--arg2'], '--help=', false);
expect(result).toBe(null);
});
it('should return no match invalid argv given', function() {
var result = getCmdLineArg('invalid argv', '--help=');
const result = getCmdLineArg('invalid argv', '--help=', false);
expect(result).toBe(null);
});
});

View File

@ -2,9 +2,9 @@ const getGuid = require('../../js/utils/getGuid.js');
describe('guid tests', function() {
it('should have valid length', function() {
var guid = getGuid();
const guid = getGuid();
expect(guid.length).toBe(36);
var parts = guid.split('-');
const parts = guid.split('-');
expect(parts.length).toBe(5);
expect(parts[0].length).toBe(8);
expect(parts[1].length).toBe(4);
@ -14,9 +14,9 @@ describe('guid tests', function() {
});
it('should only contains hex chars', function() {
for(var i = 0; i < 100; i++) {
var guid = getGuid();
var parts = guid.split('-');
for(let i = 0; i < 100; i++) {
const guid = getGuid();
const parts = guid.split('-');
parts.forEach(function(part) {
expect(/^([A-Fa-f0-9]{2})+$/.test(part)).toBe(true);
});

View File

@ -33,12 +33,12 @@ describe('isInDisplayBounds should', function() {
}
}]);
var rect = {
const rect = {
x: 1,
y: 1,
width: 90,
height: 90
}
};
expect(isInDisplayBounds(rect)).toBe(true);
});
@ -53,12 +53,12 @@ describe('isInDisplayBounds should', function() {
}
}]);
var rect = {
const rect = {
x: 0,
y: 0,
width: 100,
height: 100
}
};
expect(isInDisplayBounds(rect)).toBe(true);
});
@ -73,12 +73,12 @@ describe('isInDisplayBounds should', function() {
}
}]);
var rect = {
const rect = {
x: 0,
y: 0,
width: 100,
height: 100
}
};
expect(isInDisplayBounds(rect)).toBe(true);
});
@ -100,15 +100,15 @@ describe('isInDisplayBounds should', function() {
x: 100,
y: 0
}
}
};
createMockDisplay([ display1, display2 ]);
var rect = {
const rect = {
x: 110,
y: 0,
width: 50,
height: 50
}
};
expect(isInDisplayBounds(rect)).toBe(true);
});
@ -123,12 +123,12 @@ describe('isInDisplayBounds should', function() {
}
}]);
var rect = {
const rect = {
x: 0,
y: 0,
width: 100,
height: 101
}
};
expect(isInDisplayBounds(rect)).toBe(false);
});
@ -149,15 +149,15 @@ describe('isInDisplayBounds should', function() {
x: 100,
y: 0
}
}
};
createMockDisplay([ display1, display2 ]);
var rect = {
const rect = {
x: 50,
y: 50,
width: 75,
height: 25
}
};
expect(isInDisplayBounds(rect)).toBe(false);
});

View File

@ -1,7 +1,7 @@
const throttle = require('../../js/utils/throttle.js');
describe('throttle tests', function() {
var now, origNow;
let now, origNow;
beforeEach(function() {
origNow = Date.now;
// mock date func