From e3eefcd385e09c53a32b9a6ab45dad133c5af7d6 Mon Sep 17 00:00:00 2001 From: Gregor Herdmann Date: Wed, 4 Apr 2018 01:33:31 +0200 Subject: [PATCH] refactor: Cleanup --- Gruntfile.js | 96 ++++++++--------- electron/js/certutils.js | 6 +- electron/js/config.js | 1 - electron/js/environment.js | 45 ++++---- electron/js/lib/download.js | 2 - electron/js/lib/eventType.js | 74 +++++++++++++ electron/js/lib/googleAuth.js | 23 ++-- electron/js/lib/openGraph.js | 28 ++--- electron/js/lib/pointInRect.js | 6 +- electron/js/lib/settings.js | 4 +- electron/js/menu/context.js | 26 ++--- electron/js/menu/developer.js | 1 - electron/js/menu/system.js | 60 +++++------ electron/js/menu/tray.js | 18 ++-- electron/js/preload-about.js | 14 +-- electron/js/preload.js | 11 +- electron/js/squirrel.js | 78 +++++++------- electron/js/util.js | 70 +----------- electron/js/window-manager.js | 16 ++- electron/locale/locale.js | 100 +++++++++--------- electron/main.js | 42 ++++---- electron/renderer/src/components/Webviews.js | 25 ++--- .../src/components/context/EditAccountMenu.js | 9 +- electron/renderer/src/index.js | 8 +- electron/renderer/src/lib/eventType.js | 31 ++++++ .../renderer/src/reducers/accountReducer.js | 4 +- electron/renderer/static/webview-preload.js | 58 +++++----- 27 files changed, 436 insertions(+), 420 deletions(-) create mode 100644 electron/js/lib/eventType.js create mode 100644 electron/renderer/src/lib/eventType.js diff --git a/Gruntfile.js b/Gruntfile.js index 683ff77a4e4..23bf64ebf53 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -17,9 +17,9 @@ * */ -const electron_packager = require('electron-packager'); +const electronPackager = require('electron-packager'); const {createWindowsInstaller} = require('electron-winstaller'); -const electron_builder = require('electron-builder'); +const electronBuilder = require('electron-builder'); const ELECTRON_PACKAGE_JSON = 'electron/package.json'; const PACKAGE_JSON = 'package.json'; @@ -28,7 +28,7 @@ const INFO_JSON = 'info.json'; const LINUX_DESKTOP = { "Version": "1.1", "Name": "Wire", - "GenericName": "Secure messenger", + "GenericName": "The most secure collaboration platform", "Categories": "Network;InstantMessaging;Chat;VideoConference", "Keywords": "chat;encrypt;e2e;messenger;videocall", "StartupWMClass": "Wire" @@ -36,12 +36,11 @@ const LINUX_DESKTOP = { module.exports = function(grunt) { require('load-grunt-tasks')(grunt, {pattern: ['grunt-*']}); - const path = require('path'); grunt.initConfig({ pkg: grunt.file.readJSON(PACKAGE_JSON), info: grunt.file.readJSON(INFO_JSON), - build_number: `${process.env.BUILD_NUMBER || '0'}`, + buildNumber: `${process.env.BUILD_NUMBER || '0'}`, clean: { wrap: 'wrap', @@ -82,7 +81,7 @@ module.exports = function(grunt) { asar: true, appCopyright: '<%= info.copyright %>', appVersion: '<%= info.version %>', - buildVersion: '<%= build_number %>', + buildVersion: '<%= buildNumber %>', ignore: 'electron/renderer/src', protocols: [{name: '', schemes: ['wire']}], }, @@ -204,7 +203,7 @@ module.exports = function(grunt) { internal: { title: '<%= info.nameInternal %>', description: '<%= info.description %>', - version: '<%= info.version %>.<%= build_number %>', + version: '<%= info.version %>.<%= buildNumber %>', appDirectory: 'wrap/build/<%= info.nameInternal %>-win32-ia32', outputDirectory: 'wrap/internal/<%= info.nameInternal %>-win32-ia32', authors: '<%= info.nameInternal %>', @@ -218,7 +217,7 @@ module.exports = function(grunt) { prod: { title: '<%= info.name %>', description: '<%= info.description %>', - version: '<%= info.version %>.<%= build_number %>', + version: '<%= info.version %>.<%= buildNumber %>', appDirectory: 'wrap/build/<%= info.name %>-win32-ia32', outputDirectory: 'wrap/prod/<%= info.name %>-win32-ia32', authors: '<%= info.name %>', @@ -264,50 +263,48 @@ module.exports = function(grunt) { grunt.config.set('info', info); grunt.file.write(INFO_JSON, `${JSON.stringify(info, null, 2)}\n`); - const electron_pkg = grunt.file.readJSON(ELECTRON_PACKAGE_JSON); - electron_pkg.version = `${info.version}`; - grunt.file.write(ELECTRON_PACKAGE_JSON, `${JSON.stringify(electron_pkg, null, 2)}\n`); + const electronPkg = grunt.file.readJSON(ELECTRON_PACKAGE_JSON); + electronPkg.version = `${info.version}`; + grunt.file.write(ELECTRON_PACKAGE_JSON, `${JSON.stringify(electronPkg, null, 2)}\n`); grunt.log.write(`Version number increased to ${info.version} `).ok(); }); grunt.registerTask('release-internal', () => { const info = grunt.config.get('info'); - const build_number = grunt.config.get('build_number'); - const commit_id = grunt.config('gitinfo.local.branch.current.shortSHA'); - const electron_pkg = grunt.file.readJSON(ELECTRON_PACKAGE_JSON); - electron_pkg.updateWinUrl = info.updateWinUrlInternal; - electron_pkg.environment = 'internal'; - electron_pkg.name = info.nameInternal.toLowerCase(); - electron_pkg.productName = info.nameInternal; - electron_pkg.version = build_number === '0' - ? `${info.version}.0-${commit_id}-internal` - : `${info.version}.${build_number}-internal`; - grunt.file.write(ELECTRON_PACKAGE_JSON, `${JSON.stringify(electron_pkg, null, 2)}\n`); - grunt.log.write(`Releases URL points to ${electron_pkg.updateWinUrl} `).ok(); + const buildNumber = grunt.config.get('buildNumber'); + const commitId = grunt.config('gitinfo.local.branch.current.shortSHA'); + const electronPkg = grunt.file.readJSON(ELECTRON_PACKAGE_JSON); + electronPkg.updateWinUrl = info.updateWinUrlInternal; + electronPkg.environment = 'internal'; + electronPkg.name = info.nameInternal.toLowerCase(); + electronPkg.productName = info.nameInternal; + electronPkg.version = buildNumber === '0' + ? `${info.version}.0-${commitId}-internal` + : `${info.version}.${buildNumber}-internal`; + grunt.file.write(ELECTRON_PACKAGE_JSON, `${JSON.stringify(electronPkg, null, 2)}\n`); + grunt.log.write(`Releases URL points to ${electronPkg.updateWinUrl} `).ok(); }); grunt.registerTask('release-prod', () => { const info = grunt.config.get('info'); - const build_number = grunt.config.get('build_number'); - const commit_id = grunt.config('gitinfo.local.branch.current.shortSHA'); - const electron_pkg = grunt.file.readJSON(ELECTRON_PACKAGE_JSON); - electron_pkg.updateWinUrl = info.updateWinUrlProd; - electron_pkg.environment = 'production'; - electron_pkg.name = info.name.toLowerCase(); - electron_pkg.productName = info.name; - if (build_number === '0') { - electron_pkg.version = `${info.version}.0-${commit_id}`; - } else { - electron_pkg.version = `${info.version}.${build_number}`; - } - grunt.file.write(ELECTRON_PACKAGE_JSON, `${JSON.stringify(electron_pkg, null, 2)}\n`); - grunt.log.write(`Releases URL points to ${electron_pkg.updateWinUrl} `).ok(); + const buildNumber = grunt.config.get('buildNumber'); + const commitId = grunt.config('gitinfo.local.branch.current.shortSHA'); + const electronPkg = grunt.file.readJSON(ELECTRON_PACKAGE_JSON); + electronPkg.updateWinUrl = info.updateWinUrlProd; + electronPkg.environment = 'production'; + electronPkg.name = info.name.toLohostnameShouldBePinnedwerCase(); + electronPkg.productName = info.name; + electronPkg.version = buildNumber === '0' + ? `${info.version}.0-${commitId}` + : `${info.version}.${buildNumber}`; + grunt.file.write(ELECTRON_PACKAGE_JSON, `${JSON.stringify(electronPkg, null, 2)}\n`); + grunt.log.write(`Releases URL points to ${electronPkg.updateWinUrl} `).ok(); }); grunt.registerMultiTask('electron', 'Package Electron apps', function() { const done = this.async(); - electron_packager(this.options(), function(error) { + electronPackager(this.options(), error => { if (error) { return grunt.warn(error); } @@ -316,7 +313,6 @@ module.exports = function(grunt) { }); grunt.registerMultiTask('electronbuilder', 'Build Electron apps', function() { - const done = this.async(); const options = this.options(); const {targets} = options; delete options.targets; @@ -324,32 +320,32 @@ module.exports = function(grunt) { delete options.arch; if (arch === 'all') { - return electron_builder.build({ - targets: electron_builder.Platform.LINUX.createTarget( + return electronBuilder.build({ + targets: electronBuilder.Platform.LINUX.createTarget( targets, - electron_builder.Arch.ia32, - electron_builder.Arch.x64, + electronBuilder.Arch.ia32, + electronBuilder.Arch.x64, ), config: options, }); } - electron_builder.build({ - targets: electron_builder.Platform.LINUX.createTarget(targets, electron_builder.archFromString(arch)), + electronBuilder.build({ + targets: electronBuilder.Platform.LINUX.createTarget(targets, electronBuilder.archFromString(arch)), config: options, }); }); grunt.registerTask('update-keys', function() { const options = this.options(); - const config_string = grunt.file.read(options.config); + const configString = grunt.file.read(options.config); - if (config_string) { - const new_config_string = config_string + if (configString) { + const newConfigString = configString .replace(`RAYGUN_API_KEY: ''`, `RAYGUN_API_KEY: '${process.env.RAYGUN_API_KEY || ''}'`) .replace(`GOOGLE_CLIENT_ID: ''`, `GOOGLE_CLIENT_ID: '${process.env.GOOGLE_CLIENT_ID || ''}'`) .replace(`GOOGLE_CLIENT_SECRET: ''`, `GOOGLE_CLIENT_SECRET: '${process.env.GOOGLE_CLIENT_SECRET || ''}'`); - return grunt.file.write(options.config, new_config_string); + return grunt.file.write(options.config, newConfigString); } grunt.warn('Failed updating keys in config'); @@ -370,7 +366,7 @@ module.exports = function(grunt) { `${options.name} Helper EH.app/`, `${options.name} Helper NP.app/Contents/MacOS/${options.name} Helper NP`, `${options.name} Helper NP.app/`, - ].forEach((framework) => + ].forEach(framework => execSync(`codesign --deep -fs '${options.sign.app}' --entitlements '${options.child}' '${options.dir}/Contents/Frameworks/${framework}'`), ); diff --git a/electron/js/certutils.js b/electron/js/certutils.js index b2418bb1b86..3d801d00544 100644 --- a/electron/js/certutils.js +++ b/electron/js/certutils.js @@ -59,11 +59,9 @@ const pins = [ ]; module.exports = { - hostnameShouldBePinned (hostname) { - return pins.some(pin => pin.url.test(hostname.toLowerCase().trim())); - }, + hostnameShouldBePinned: hostname => pins.some(pin => pin.url.test(hostname.toLowerCase().trim())), - verifyPinning (hostname, certificate) { + verifyPinning: (hostname, certificate) => { const {data: certData = '', issuerCert: {data: issuerCertData = ''} = {}} = certificate; let issuerCertHex, publicKey, publicKeyBytes, publicKeyFingerprint; diff --git a/electron/js/config.js b/electron/js/config.js index bddbef37f4b..985e1ec66ef 100644 --- a/electron/js/config.js +++ b/electron/js/config.js @@ -17,7 +17,6 @@ * */ - const pkg = require('./../package.json'); const config = { diff --git a/electron/js/environment.js b/electron/js/environment.js index 009fcbf8559..ecbc8fb6b16 100644 --- a/electron/js/environment.js +++ b/electron/js/environment.js @@ -17,7 +17,6 @@ * */ - const pkg = require('./../package.json'); const settings = require('./lib/settings'); @@ -53,45 +52,48 @@ const URL_WEBAPP = { STAGING: 'https://wire-webapp-staging.zinfra.io', }; -const _app = { +const app = { ENV: pkg.environment, IS_DEVELOPMENT: pkg.environment !== 'production', IS_PRODUCTION: pkg.environment === 'production', UPDATE_URL_WIN: pkg.updateWinUrl, }; -const _getEnvironment = () => { +const getEnvironment = () => { return currentEnvironment = currentEnvironment || settings.restore('env', TYPE.INTERNAL); }; -const _is_prod_environment = () => { +const isProdEnvironment = () => { return [ TYPE.INTERNAL, TYPE.PRODUCTION, - ].includes(_getEnvironment()); + ].includes(getEnvironment()); }; -const _platform = { +const platform = { IS_LINUX: process.platform === 'linux', IS_MAC_OS: process.platform === 'darwin', IS_WINDOWS: process.platform === 'win32', }; -const _setEnvironment = (env) => { +const setEnvironment = (env) => { currentEnvironment = env || settings.restore('env', TYPE.INTERNAL); settings.save('env', currentEnvironment); }; -const _web = { - get_url_admin: () => _is_prod_environment() ? URL_ADMIN.PRODUCTION : URL_ADMIN.STAGING, - get_url_support: () => URL_SUPPORT, - get_url_webapp: (env) => { +const web = { + getAdminUrl: path => { + const baseUrl = isProdEnvironment() ? URL_ADMIN.PRODUCTION : URL_ADMIN.STAGING; + return `${baseUrl}${path ? path : ''}`; + }, + getSupportUrl: path => `${URL_SUPPORT}${path ? path : ''}`, + getWebappUrl: (env) => { if (env) { return env; } - if (_app.IS_DEVELOPMENT) { - switch (_getEnvironment()) { + if (app.IS_DEVELOPMENT) { + switch (getEnvironment()) { case TYPE.DEV: return URL_WEBAPP.DEV; case TYPE.EDGE: @@ -109,14 +111,17 @@ const _web = { return URL_WEBAPP.PRODUCTION; }, - get_url_website: () => _is_prod_environment() ? URL_WEBSITE.PRODUCTION : URL_WEBSITE.STAGING, + getWebsiteUrl: path => { + const baseUrl = isProdEnvironment() ? URL_WEBSITE.PRODUCTION : URL_WEBSITE.STAGING; + return `${baseUrl}${path ? path : ''}`; + }, }; module.exports = { - TYPE: TYPE, - app: _app, - getEnvironment: _getEnvironment, - platform: _platform, - setEnvironment: _setEnvironment, - web: _web, + TYPE, + app, + getEnvironment, + platform, + setEnvironment, + web, }; diff --git a/electron/js/lib/download.js b/electron/js/lib/download.js index 67d3d1512f3..ca224c480e2 100644 --- a/electron/js/lib/download.js +++ b/electron/js/lib/download.js @@ -17,10 +17,8 @@ * */ - const fs = require('fs'); const imageType = require('image-type'); - const {dialog} = require('electron'); module.exports = (fileName, bytes) => { diff --git a/electron/js/lib/eventType.js b/electron/js/lib/eventType.js new file mode 100644 index 00000000000..4bc2139f32e --- /dev/null +++ b/electron/js/lib/eventType.js @@ -0,0 +1,74 @@ +/* + * Wire + * Copyright (C) 2018 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +module.exports = { + ABOUT: { + LOADED: 'EVENT_TYPE.ABOUT.LOADED', + LOCALE_RENDER: 'EVENT_TYPE.ABOUT.LOCALE_RENDER', + LOCALE_VALUES: 'EVENT_TYPE.ABOUT.LOCALE_VALUES', + SHOW: 'EVENT_TYPE.ABOUT.SHOW', + }, + ACCOUNT: { + DELETE_DATA: 'EVENT_TYPE.ACCOUNT.DELETE_DATA', + UPDATE_INFO: 'EVENT_TYPE.ACCOUNT.UPDATE_INFO', + }, + ACTION: { + NOTIFICATION_CLICK: 'EVENT_TYPE.ACTION.NOTIFICATION_CLICK', + SAVE_PICTURE: 'EVENT_TYPE.ACTION.SAVE_PICTURE', + SIGN_OUT: 'EVENT_TYPE.ACTION.SIGN_OUT', + }, + CONVERSATION: { + ADD_PEOPLE: 'EVENT_TYPE.CONVERSATION.ADD_PEOPLE', + ARCHIVE: 'EVENT_TYPE.CONVERSATION.ARCHIVE', + CALL: 'EVENT_TYPE.CONVERSATION.CALL', + DELETE: 'EVENT_TYPE.CONVERSATION.DELETE', + PEOPLE: 'EVENT_TYPE.CONVERSATION.PEOPLE', + PING: 'EVENT_TYPE.CONVERSATION.PING', + SHOW: 'EVENT_TYPE.CONVERSATION.SHOW', + SHOW_NEXT: 'EVENT_TYPE.CONVERSATION.SHOW_NEXT', + SHOW_PREVIOUS: 'EVENT_TYPE.CONVERSATION.SHOW_PREVIOUS', + START: 'EVENT_TYPE.CONVERSATION.START', + TOGGLE_MUTE: 'EVENT_TYPE.CONVERSATION.TOGGLE_MUTE', + VIDEO_CALL: 'EVENT_TYPE.CONVERSATION.VIDEO_CALL', + }, + GOOGLE_OAUTH: { + ERROR: 'EVENT_TYPE.GOOGLE_OAUTH.ERROR', + REQUEST: 'EVENT_TYPE.GOOGLE_OAUTH.REQUEST', + SUCCESS: 'EVENT_TYPE.GOOGLE_OAUTH.SUCCESS', + }, + LIFECYCLE: { + SIGN_OUT: 'EVENT_TYPE.LIFECYCLE.SIGN_OUT', + SIGNED_IN: 'EVENT_TYPE.LIFECYCLE.SIGNED_IN', + SIGNED_OUT: 'EVENT_TYPE.LIFECYCLE.SIGNED_OUT', + UNREAD_COUNT: 'EVENT_TYPE.LIFECYCLE.UNREAD_COUNT', + }, + PREFERENCES: { + SHOW: 'EVENT_TYPE.PREFERENCES.SHOW', + }, + UI: { + BADGE_COUNT: 'EVENT_TYPE.UI.BADGE_COUNT', + SYSTEM_MENU: 'EVENT_TYPE.UI.SYSTEM_MENU', + WEBAPP_VERSION: 'EVENT_TYPE.UI.WEBAPP_VERSION', + }, + WRAPPER: { + RELAUNCH: 'EVENT_TYPE.WRAPPER.RELAUNCH', + UPDATE: 'EVENT_TYPE.WRAPPER.UPDATE', + UPDATE_AVAILABLE: 'EVENT_TYPE.WRAPPER.UPDATE_AVAILABLE', + }, +}; diff --git a/electron/js/lib/googleAuth.js b/electron/js/lib/googleAuth.js index 0d0aa72e12a..9baad9db9ce 100644 --- a/electron/js/lib/googleAuth.js +++ b/electron/js/lib/googleAuth.js @@ -17,7 +17,6 @@ * */ - const {BrowserWindow} = require('electron'); const qs = require('querystring'); @@ -25,7 +24,7 @@ const google = require('googleapis'); const request = require('request'); const OAuth2 = google.auth.OAuth2; -const _authorizeApp = (url) => { +const authorizeApp = url => { return new Promise((resolve, reject) => { const win = new BrowserWindow({ 'title': '', @@ -41,12 +40,13 @@ const _authorizeApp = (url) => { setImmediate(() => { const title = win.getTitle(); + const [, , returnValue] = title.split(/[ =]/); if (title.startsWith('Denied')) { - reject(new Error(title.split(/[ =]/)[2])); + reject(new Error(returnValue)); win.removeAllListeners('closed'); win.close(); } else if (title.startsWith('Success')) { - resolve(title.split(/[ =]/)[2]); + resolve(returnValue); win.removeAllListeners('closed'); win.close(); } @@ -55,9 +55,9 @@ const _authorizeApp = (url) => { }); }; -const _getAccessToken = (scopes, clientId, clientSecret) => { +const getAccessToken = (scopes, clientId, clientSecret) => { return new Promise((resolve, reject) => { - _getAuthorizationCode(scopes, clientId, clientSecret) + getAuthorizationCode(scopes, clientId, clientSecret) .then((code) => { const data = qs.stringify({ client_id: clientId, @@ -78,7 +78,7 @@ const _getAccessToken = (scopes, clientId, clientSecret) => { }); }; -const _getAuthenticationUrl = (scopes, clientId, clientSecret) => { +const getAuthenticationUrl = (scopes, clientId, clientSecret) => { const oauth2Client = new OAuth2( clientId, clientSecret, @@ -87,12 +87,11 @@ const _getAuthenticationUrl = (scopes, clientId, clientSecret) => { return oauth2Client.generateAuthUrl({scope: scopes}); }; -const _getAuthorizationCode = (scopes, clientId, clientSecret) => { - const url = _getAuthenticationUrl(scopes, clientId, clientSecret); - return _authorizeApp(url); +const getAuthorizationCode = (scopes, clientId, clientSecret) => { + const url = getAuthenticationUrl(scopes, clientId, clientSecret); + return authorizeApp(url); }; - module.exports = { - getAccessToken: _getAccessToken, + getAccessToken, }; diff --git a/electron/js/lib/openGraph.js b/electron/js/lib/openGraph.js index ecfafece1c2..6d85bb01813 100644 --- a/electron/js/lib/openGraph.js +++ b/electron/js/lib/openGraph.js @@ -18,21 +18,21 @@ */ -const og = require('open-graph'); +const openGraph = require('open-graph'); const request = require('request'); -const _arrayify = (obj = []) => Array.isArray(obj) ? obj : [obj]; +const arrayify = (value = []) => Array.isArray(value) ? value : [value]; -const _bufferToBase64 = (buffer, mimeType) => { +const bufferToBase64 = (buffer, mimeType) => { const bufferBase64encoded = Buffer.from(buffer).toString('base64'); return 'data:' + mimeType + ';base64,' + bufferBase64encoded; }; -const _fetchImageAsBase64 = (url) => { +const fetchImageAsBase64 = (url) => { return new Promise((resolve) => { request({encoding: null, url: encodeURI(url)}, (error, response, body) => { if (!error && response.statusCode === 200) { - resolve(_bufferToBase64(body, response.headers['content-type'])); + resolve(bufferToBase64(body, response.headers['content-type'])); } else { // we just skip images that failed to download resolve(); @@ -41,13 +41,13 @@ const _fetchImageAsBase64 = (url) => { }); }; -const _fetchOpenGraphData = (url) => { +const fetchOpenGraphData = (url) => { return new Promise((resolve, reject) => { - og(url, (error, meta) => error ? reject(error) : resolve(meta)); + openGraph(url, (error, meta) => error ? reject(error) : resolve(meta)); }); }; -const _updateMetaDataWithImage = (meta, image) => { +const updateMetaDataWithImage = (meta, image) => { if (image) { meta.image.data = image; } else { @@ -57,14 +57,14 @@ const _updateMetaDataWithImage = (meta, image) => { return meta; }; -const _getOpenGraphData = (url, callback) => { - return _fetchOpenGraphData(url) +const getOpenGraphData = (url, callback) => { + return fetchOpenGraphData(url) .then((meta) => { if (meta.image && meta.image.url) { - const [imageUrl] = _arrayify(meta.image.url); + const [imageUrl] = arrayify(meta.image.url); - return _fetchImageAsBase64(imageUrl) - .then((uri) => _updateMetaDataWithImage(meta, uri)) + return fetchImageAsBase64(imageUrl) + .then((uri) => updateMetaDataWithImage(meta, uri)) .catch(() => meta); } @@ -86,4 +86,4 @@ const _getOpenGraphData = (url, callback) => { }); }; -module.exports = _getOpenGraphData; +module.exports = getOpenGraphData; diff --git a/electron/js/lib/pointInRect.js b/electron/js/lib/pointInRect.js index 9881f8008b4..670ba4f7648 100644 --- a/electron/js/lib/pointInRect.js +++ b/electron/js/lib/pointInRect.js @@ -20,8 +20,8 @@ module.exports = (point, rectangle) => { const [x, y] = point; - const x_in_range = x >= rectangle.x && x <= rectangle.x + rectangle.width; - const y_in_range = y >= rectangle.y && y <= rectangle.y + rectangle.height; + const xInRange = x >= rectangle.x && x <= rectangle.x + rectangle.width; + const yInRange = y >= rectangle.y && y <= rectangle.y + rectangle.height; - return x_in_range && y_in_range; + return xInRange && yInRange; }; diff --git a/electron/js/lib/settings.js b/electron/js/lib/settings.js index 9a0b469a1e4..ece65e5b764 100644 --- a/electron/js/lib/settings.js +++ b/electron/js/lib/settings.js @@ -35,7 +35,7 @@ class ConfigurationPersistence { this.debug('Reading config file'); try { - global._ConfigurationPersistence = this._readFromFile(); + global._ConfigurationPersistence = this.readFromFile(); } catch (error) { this.debug('Unable to parse the init file. Details: %s', error); global._ConfigurationPersistence = {}; @@ -79,7 +79,7 @@ class ConfigurationPersistence { }); } - _readFromFile() { + readFromFile() { this.debug('Reading user configuration file...'); const dataInJSON = JSON.parse(fs.readFileSync(INIT_JSON, 'utf8')); this.debug('%o', dataInJSON); diff --git a/electron/js/menu/context.js b/electron/js/menu/context.js index bcf41005bd5..b8e8b7b8431 100644 --- a/electron/js/menu/context.js +++ b/electron/js/menu/context.js @@ -17,7 +17,6 @@ * */ - const {clipboard, remote, ipcRenderer, webFrame} = require('electron'); const Menu = remote.Menu; const webContents = remote.getCurrentWebContents(); @@ -25,12 +24,14 @@ const webContents = remote.getCurrentWebContents(); const config = require('./../config'); const locale = require('./../../locale/locale'); const settings = require('./../lib/settings'); +const EVENT_TYPE = require('./../lib/eventType'); let textMenu; /////////////////////////////////////////////////////////////////////////////// // Default /////////////////////////////////////////////////////////////////////////////// + let copyContext = ''; const defaultMenu = Menu.buildFromTemplate([ @@ -43,6 +44,7 @@ const defaultMenu = Menu.buildFromTemplate([ /////////////////////////////////////////////////////////////////////////////// // Text /////////////////////////////////////////////////////////////////////////////// + const selection = { isMisspelled: false, suggestions: [], @@ -97,6 +99,7 @@ const createTextMenu = () => { /////////////////////////////////////////////////////////////////////////////// // Images /////////////////////////////////////////////////////////////////////////////// + const imageMenu = Menu.buildFromTemplate([ { click: () => savePicture(imageMenu.file, imageMenu.image), @@ -141,31 +144,18 @@ window.addEventListener('contextmenu', (event) => { }, false); -window.addEventListener('click', (event) => { - const element = event.target; - - if (element.classList.contains('icon-more') && !element.classList.contains('context-menu') && element.parentElement.previousElementSibling) { - // get center-column - const id = element.parentElement.previousElementSibling.getAttribute('data-uie-uid'); - if (createConversationMenu(id)) { - event.stopPropagation(); - } - } -}, true); - - const savePicture = (fileName, url) => { fetch(url) .then((response) => response.arrayBuffer()) - .then((arrayBuffer) => ipcRenderer.send('save-picture', fileName, new Uint8Array(arrayBuffer))); + .then((arrayBuffer) => ipcRenderer.send(EVENT_TYPE.ACTION.SAVE_PICTURE, fileName, new Uint8Array(arrayBuffer))); }; - /////////////////////////////////////////////////////////////////////////////// // Spell Checker /////////////////////////////////////////////////////////////////////////////// -const is_spellcheck_supported = config.SPELLCHECK.SUPPORTED_LANGUAGES.includes(locale.getCurrent()); -if (is_spellcheck_supported) { + +const isSpellCheckSupported = config.SPELLCHECK.SUPPORTED_LANGUAGES.includes(locale.getCurrent()); +if (isSpellCheckSupported) { const spellchecker = require('spellchecker'); webFrame.setSpellCheckProvider(locale.getCurrent(), false, { diff --git a/electron/js/menu/developer.js b/electron/js/menu/developer.js index 1685c1de9cf..92572067a76 100644 --- a/electron/js/menu/developer.js +++ b/electron/js/menu/developer.js @@ -17,7 +17,6 @@ * */ - const {MenuItem} = require('electron'); const config = require('./../config'); const environment = require('./../environment'); diff --git a/electron/js/menu/system.js b/electron/js/menu/system.js index c96c17d2d23..04ba0c18d44 100644 --- a/electron/js/menu/system.js +++ b/electron/js/menu/system.js @@ -27,6 +27,7 @@ const environment = require('./../environment'); const locale = require('./../../locale/locale'); const windowManager = require('./../window-manager'); const settings = require('./../lib/settings'); +const EVENT_TYPE = require('./../lib/eventType'); let menu; @@ -36,23 +37,20 @@ const launcher = new autoLaunch({ path: launchCmd, }); - const getPrimaryWindow = () => windowManager.getPrimaryWindow(); // TODO: disable menus when not in focus const sendAction = (action) => { const primaryWindow = getPrimaryWindow(); if (primaryWindow) { - getPrimaryWindow().webContents.send('system-menu', action); + getPrimaryWindow().webContents.send(EVENT_TYPE.UI.SYSTEM_MENU, action); } }; - const separatorTemplate = { type: 'separator', }; - const createLanguageTemplate = (languageCode) => { return { click: () => changeLocale(languageCode), @@ -61,7 +59,7 @@ const createLanguageTemplate = (languageCode) => { }; }; -const createLanguageSubmenu = ()=> { +const createLanguageSubmenu = () => { return Object.keys(locale.SUPPORTED_LANGUAGES) .map((supportedLanguage) => createLanguageTemplate(supportedLanguage)); }; @@ -72,12 +70,12 @@ const localeTemplate = { }; const aboutTemplate = { - click: () => menu.emit('about-wire'), + click: () => menu.emit(EVENT_TYPE.ABOUT.SHOW), i18n: 'menuAbout', }; const signOutTemplate = { - click: () => sendAction('sign-out'), + click: () => sendAction(EVENT_TYPE.ACTION.SIGN_OUT), i18n: 'menuSignOut', }; @@ -86,45 +84,45 @@ const conversationTemplate = { submenu: [ { accelerator: 'CmdOrCtrl+N', - click: () => sendAction('conversation-start'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.START), i18n: 'menuStart', }, separatorTemplate, { accelerator: 'CmdOrCtrl+K', - click: () => sendAction('conversation-ping'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.PING), i18n: 'menuPing', }, { - click: () => sendAction('conversation-call'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.CALL), i18n: 'menuCall', }, { - click: () => sendAction('conversation-video-call'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.VIDEO_CALL), i18n: 'menuVideoCall', }, separatorTemplate, { accelerator: 'CmdOrCtrl+I', - click: () => sendAction('conversation-people'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.PEOPLE), i18n: 'menuPeople', }, { accelerator: 'Shift+CmdOrCtrl+K', - click: () => sendAction('conversation-add-people'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.ADD_PEOPLE), i18n: 'menuAddPeople', }, separatorTemplate, { accelerator: 'CmdOrCtrl+D', - click: () => sendAction('conversation-archive'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.ARCHIVE), i18n: 'menuArchive', }, { accelerator: 'CmdOrCtrl+Alt+M', - click: () => sendAction('conversation-silence'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.TOGGLE_MUTE), i18n: 'menuMute', }, { - click: () => sendAction('conversation-delete'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.DELETE), i18n: 'menuDelete', }, ], @@ -174,7 +172,7 @@ const toggleAutoLaunchTemplate = { type: 'checkbox', }; -const supportsSpellcheck = config.SPELLCHECK.SUPPORTED_LANGUAGES.includes(locale.getCurrent()); +const supportsSpellCheck = config.SPELLCHECK.SUPPORTED_LANGUAGES.includes(locale.getCurrent()); const editTemplate = { i18n: 'menuEdit', @@ -207,9 +205,9 @@ const editTemplate = { }, separatorTemplate, { - checked: supportsSpellcheck && settings.restore('spelling', false), + checked: supportsSpellCheck && settings.restore('spelling', false), click: (event) => settings.save('spelling', event.checked), - enabled: supportsSpellcheck, + enabled: supportsSpellCheck, i18n: 'menuSpelling', type: 'checkbox', }, @@ -231,12 +229,12 @@ const windowTemplate = { separatorTemplate, { accelerator: environment.platform.IS_MAC_OS ? 'Alt+Cmd+Up' : 'Alt+Shift+Up', - click: () => sendAction('conversation-next'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.SHOW_NEXT), i18n: 'menuNextConversation', }, { accelerator: environment.platform.IS_MAC_OS ? 'Alt+Cmd+Down' : 'Alt+Shift+Down', - click: () => sendAction('conversation-prev'), + click: () => sendAction(EVENT_TYPE.CONVERSATION.SHOW_PREVIOUS), i18n: 'menuPreviousConversation', }, ], @@ -247,23 +245,23 @@ const helpTemplate = { role: 'help', submenu: [ { - click: () => shell.openExternal(environment.web.get_url_website() + config.URL.LEGAL), + click: () => shell.openExternal(environment.web.getWebsiteUrl(config.URL.LEGAL)), i18n: 'menuLegal', }, { - click: () => shell.openExternal(environment.web.get_url_website() + config.URL.PRIVACY), + click: () => shell.openExternal(environment.web.getWebsiteUrl(config.URL.PRIVACY)), i18n: 'menuPrivacy', }, { - click: () => shell.openExternal(environment.web.get_url_website() + config.URL.LICENSES), + click: () => shell.openExternal(environment.web.getWebsiteUrl(config.URL.LICENSES)), i18n: 'menuLicense', }, { - click: () => shell.openExternal(environment.web.get_url_support()), + click: () => shell.openExternal(environment.web.getSupportUrl()), i18n: 'menuSupport', }, { - click: () => shell.openExternal(environment.web.get_url_website()), + click: () => shell.openExternal(environment.web.getWebsiteUrl()), i18n: 'menuWireURL', }, ], @@ -275,7 +273,7 @@ const darwinTemplate = { aboutTemplate, separatorTemplate, { accelerator: 'Command+,', - click: () => sendAction('preferences-show'), + click: () => sendAction(EVENT_TYPE.PREFERENCES.SHOW), i18n: 'menuPreferences', }, separatorTemplate, @@ -313,7 +311,7 @@ const win32Template = { submenu: [ { accelerator: 'Ctrl+,', - click: () => sendAction('preferences-show'), + click: () => sendAction(EVENT_TYPE.PREFERENCES.SHOW), i18n: 'menuSettings', }, localeTemplate, @@ -332,7 +330,7 @@ const linuxTemplate = { label: config.NAME, submenu: [ { - click: () => sendAction('preferences-show'), + click: () => sendAction(EVENT_TYPE.PREFERENCES.SHOW), i18n: 'menuPreferences', }, separatorTemplate, @@ -356,7 +354,6 @@ const menuTemplate = [ helpTemplate, ]; - const processMenu = (template, language) => { for (const item of template) { if (item.submenu) { @@ -395,7 +392,6 @@ const changeLocale = (language) => { }); }; - module.exports = { createMenu: () => { if (environment.platform.IS_MAC_OS) { @@ -421,7 +417,7 @@ module.exports = { if (environment.platform.IS_LINUX) { menuTemplate.unshift(linuxTemplate); editTemplate.submenu.push(separatorTemplate, { - click: () => sendAction('preferences-show'), + click: () => sendAction(EVENT_TYPE.PREFERENCES.SHOW), i18n: 'menuPreferences', }); windowTemplate.submenu.push( diff --git a/electron/js/menu/tray.js b/electron/js/menu/tray.js index 5bb301be79a..caa19a1b412 100644 --- a/electron/js/menu/tray.js +++ b/electron/js/menu/tray.js @@ -17,8 +17,6 @@ * */ - - const {app, Menu, Tray} = require('electron'); const path = require('path'); @@ -37,7 +35,7 @@ let lastUnreadCount = 0; let appIcon = null; -const _createTrayIcon = () => { +const createTrayIcon = () => { if (!environment.platform.IS_MAC_OS) { appIcon = new Tray(iconPath); const contextMenu = Menu.buildFromTemplate([ @@ -56,11 +54,11 @@ const _createTrayIcon = () => { } }; -const _updateBadgeIcon = (win, count) => { +const updateBadgeIcon = (win, count) => { if (count) { - _useBadgeIcon(); + useBadgeIcon(); } else { - _useDefaultIcon(); + useDefaultIcon(); } if (environment.platform.IS_WINDOWS) { @@ -72,19 +70,19 @@ const _updateBadgeIcon = (win, count) => { lastUnreadCount = count; }; -const _useDefaultIcon = () => { +const useDefaultIcon = () => { if (appIcon) { appIcon.setImage(iconPath); } }; -const _useBadgeIcon = () => { +const useBadgeIcon = () => { if (appIcon) { appIcon.setImage(iconBadgePath); } }; module.exports = { - createTrayIcon: _createTrayIcon, - updateBadgeIcon: _updateBadgeIcon, + createTrayIcon, + updateBadgeIcon, }; diff --git a/electron/js/preload-about.js b/electron/js/preload-about.js index 0d77e137510..0c07f4a6e69 100644 --- a/electron/js/preload-about.js +++ b/electron/js/preload-about.js @@ -18,21 +18,17 @@ */ const {ipcRenderer} = require('electron'); +const EVENT_TYPE = require('lib/eventType'); -ipcRenderer.once('about-locale-render', (sender, labels) => { +ipcRenderer.once(EVENT_TYPE.ABOUT.LOCALE_RENDER, (sender, labels) => { for (const label in labels) { document.querySelector(`[data-string="${label}"]`).innerHTML = labels[label]; } }); -ipcRenderer.once('about-loaded', (sender, details) => { +ipcRenderer.once(EVENT_TYPE.ABOUT.LOADED, (sender, details) => { document.getElementById('name').innerHTML = details.productName; - - if (details.electronVersion) { - document.getElementById('version').innerHTML = details.electronVersion; - } else { - document.getElementById('version').innerHTML = 'Development'; - } + document.getElementById('version').innerHTML = details.electronVersion || 'Development'; if (details.webappVersion) { document.getElementById('webappVersion').innerHTML = details.webappVersion; @@ -45,5 +41,5 @@ ipcRenderer.once('about-loaded', (sender, details) => { for (const label of document.querySelectorAll('[data-string]')) { labels.push(label.dataset.string); } - ipcRenderer.send('about-locale-values', labels); + ipcRenderer.send(EVENT_TYPE.ABOUT.LOCALE_VALUES, labels); }); diff --git a/electron/js/preload.js b/electron/js/preload.js index a3231c53d22..360a6a852f8 100644 --- a/electron/js/preload.js +++ b/electron/js/preload.js @@ -17,9 +17,10 @@ * */ -const { ipcRenderer, webFrame } = require('electron'); +const {ipcRenderer, webFrame} = require('electron'); const environment = require('./environment'); const locale = require('../locale/locale'); +const EVENT_TYPE = require('lib/eventType'); webFrame.setVisualZoomLevelLimits(1, 1); webFrame.setLayoutZoomLevelLimits(1, 1); @@ -33,7 +34,7 @@ const getSelectedWebview = () => document.querySelector('.Webview:not(.hide)'); const getWebviewById = id => document.querySelector(`.Webview[data-accountid="${id}"]`); const subscribeToMainProcessEvents = () => { - ipcRenderer.on('system-menu', (event, action) => { + ipcRenderer.on(EVENT_TYPE.UI.SYSTEM_MENU, (event, action) => { const selectedWebview = getSelectedWebview(); if (selectedWebview) { selectedWebview.send(action); @@ -43,19 +44,19 @@ const subscribeToMainProcessEvents = () => { const setupIpcInterface = () => { window.sendBadgeCount = count => { - ipcRenderer.send('badge-count', count); + ipcRenderer.send(EVENT_TYPE.UI.BADGE_COUNT, count); }; window.sendDeleteAccount = (accountID, sessionID) => { const accountWebview = getWebviewById(accountID); accountWebview.getWebContents().session.clearStorageData(); - ipcRenderer.send('delete-account-data', accountID, sessionID); + ipcRenderer.send(EVENT_TYPE.ACCOUNT.DELETE_DATA, accountID, sessionID); }; window.sendLogoutAccount = accountId => { const accountWebview = getWebviewById(accountId); if (accountWebview) { - accountWebview.send('sign-out'); + accountWebview.send(EVENT_TYPE.ACTION.SIGN_OUT); } }; }; diff --git a/electron/js/squirrel.js b/electron/js/squirrel.js index 54bab76aa28..50f813cbd40 100644 --- a/electron/js/squirrel.js +++ b/electron/js/squirrel.js @@ -17,7 +17,6 @@ * */ - // https://github.com/atom/atom/blob/master/src/main-process/squirrel-update.coffee const {app} = require('electron'); @@ -39,6 +38,16 @@ let linkName = config.NAME + '.lnk'; let taskbarLink = path.resolve(path.join(process.env.APPDATA, 'Microsoft', 'Internet Explorer', 'Quick Launch', 'User Pinned', 'TaskBar', linkName)); +const SQUIRREL_EVENT = { + CREATE_SHORTCUT: '--createShortcut', + INSTALL: '--squirrel-install', + OBSOLETE: '--squirrel-obsolete', + REMOVE_SHORTCUT: '--removeShortcut', + UNINSTALL: '--squirrel-uninstall', + UPDATE: '--update', + UPDATED: '--squirrel-updated', +}; + const spawn = (command, args, callback) => { let error; let spawnedProcess; @@ -49,22 +58,14 @@ const spawn = (command, args, callback) => { spawnedProcess = cp.spawn(command, args); } catch (_error) { error = _error; - process.nextTick(function() { - return typeof callback === 'function' ? callback(error, stdout) : void 0; - }); - return; - }; - - spawnedProcess.stdout.on('data', function(data) { - return stdout += data; - }); + return process.nextTick(() => typeof callback === 'function' ? callback(error, stdout) : void 0); + } - error = null; - spawnedProcess.on('error', function(processError) { - return error != null ? error : error = processError; - }); + spawnedProcess.stdout.on('data', data => stdout += data); - spawnedProcess.on('close', function(code, signal) { + error = null; + spawnedProcess.on('error', processError => error != null ? error : error = processError); + spawnedProcess.on('close', (code, signal) => { if (code !== 0) { if (error == null) { error = new Error('Command failed: ' + (signal != null ? signal : code)); @@ -84,61 +85,60 @@ const spawn = (command, args, callback) => { }); }; - const spawnUpdate = (args, callback) => { spawn(updateDotExe, args, callback); }; - -const createStartShortcut = (callback) => { - spawnUpdate(['--createShortcut', exeName, '-l=StartMenu'], callback); +const createStartShortcut = callback => { + spawnUpdate([SQUIRREL_EVENT.CREATE_SHORTCUT, exeName, '-l=StartMenu'], callback); }; - -const createDesktopShortcut = (callback) => { - spawnUpdate(['--createShortcut', exeName, '-l=Desktop'], callback); +const createDesktopShortcut = callback => { + spawnUpdate([SQUIRREL_EVENT.CREATE_SHORTCUT, exeName, '-l=Desktop'], callback); }; - -const removeShortcuts = (callback) => { - spawnUpdate(['--removeShortcut', exeName, '-l=Desktop,Startup,StartMenu'], () => fs.unlink(taskbarLink, callback)); +const removeShortcuts = callback => { + spawnUpdate([SQUIRREL_EVENT.REMOVE_SHORTCUT, exeName, '-l=Desktop,Startup,StartMenu'], () => fs.unlink(taskbarLink, callback)); }; - const installUpdate = () => { - spawnUpdate(['--update', environment.app.UPDATE_URL_WIN]); + spawnUpdate([SQUIRREL_EVENT.UPDATE, environment.app.UPDATE_URL_WIN]); }; - const scheduleUpdate = () => { setTimeout(installUpdate, config.UPDATE.DELAY); setInterval(installUpdate, config.UPDATE.INTERVAL); }; - -const handleSquirrelEvent = (shouldQuit) => { +const handleSquirrelEvent = shouldQuit => { const [, squirrelEvent] = process.argv; switch (squirrelEvent) { - case '--squirrel-install': + case SQUIRREL_EVENT.INSTALL: { createStartShortcut(() => { createDesktopShortcut(() => { app.quit(); }); }); return true; - case '--squirrel-updated': + } + + case SQUIRREL_EVENT.UPDATED: { app.exit(); return true; - case '--squirrel-uninstall': - removeShortcuts(() => { - app.quit(); - }); + } + + case SQUIRREL_EVENT.UNINSTALL: { + removeShortcuts(() => app.quit()); return true; - case '--squirrel-obsolete': + } + + case SQUIRREL_EVENT.OBSOLETE: { app.quit(); return true; + } } + if (shouldQuit) { // Using exit instead of quit for the time being // see: https://github.com/electron/electron/issues/8862#issuecomment-294303518 @@ -150,6 +150,6 @@ const handleSquirrelEvent = (shouldQuit) => { module.exports = { - handleSquirrelEvent: handleSquirrelEvent, - installUpdate: installUpdate, + handleSquirrelEvent, + installUpdate, }; diff --git a/electron/js/util.js b/electron/js/util.js index 7c63c48280e..bcdc3e1cf78 100644 --- a/electron/js/util.js +++ b/electron/js/util.js @@ -17,7 +17,6 @@ * */ - const electron = require('electron'); const url = require('url'); /*eslint-disable no-unused-vars*/ @@ -25,16 +24,12 @@ const debug = require('debug'); const utilDebug = debug('utilDebug'); /*eslint-enable no-unused-vars*/ -const config = require('./config'); -const environment = require('./environment'); const pointInRectangle = require('./lib/pointInRect'); module.exports = { - capitalize: (input) => { - return input.charAt(0).toUpperCase() + input.substr(1); - }, + capitalize: input => input.charAt(0).toUpperCase() + input.substr(1), - isInView: (win) => { + isInView: win => { const windowBounds = win.getBounds(); const nearestWorkArea = electron.screen.getDisplayMatching(windowBounds).workArea; @@ -44,64 +39,5 @@ module.exports = { return upperLeftVisible || lowerRightVisible; }, - isMatchingEmbed: (_url) => { - const hostname = url.parse(_url).hostname; - - for (const embedDomain of config.EMBED_DOMAINS) { - // If the hostname match - if (typeof embedDomain.hostname === 'object' && embedDomain.hostname.includes(hostname)) { - - utilDebug('Allowing %s', embedDomain.name); - return true; - } - } - - return false; - }, - - isMatchingEmbedOpenExternalWhitelist: (domain, _url) => { - const currentHostname = url.parse(domain).hostname; - const linkHostname = url.parse(_url).hostname; - - for (const embedDomain of config.EMBED_DOMAINS) { - // If the hostname match - if (typeof embedDomain.hostname === 'object' && embedDomain.hostname.includes(currentHostname)) { - - // And the link to open is allowed - return embedDomain.allowedExternalLinks.includes(linkHostname); - } - } - - return false; - }, - - isMatchingHost: (_url, _baseUrl) => { - return url.parse(_url).host === url.parse(_baseUrl).host; - }, - - resizeToBig: (win) => { - if (!environment.platform.IS_MAC_OS) { - win.setMenuBarVisibility(true); - } - - win.setMinimumSize(config.WINDOW.MAIN.MIN_WIDTH, config.WINDOW.MAIN.MIN_HEIGHT); - win.setSize(config.WINDOW.MAIN.DEFAULT_WIDTH, config.WINDOW.MAIN.DEFAULT_HEIGHT); - win.setResizable(true); - win.setMaximizable(true); - win.center(); - }, - - resizeToSmall: (win) => { - if (!environment.platform.IS_MAC_OS) { - win.setMenuBarVisibility(false); - } - - const height = config.WINDOW.AUTH.HEIGHT + (environment.platform.IS_WINDOWS ? 40 : 0); - win.setFullScreen(false); - win.setMaximizable(false); - win.setMinimumSize(config.WINDOW.AUTH.WIDTH, height); - win.setSize(config.WINDOW.AUTH.WIDTH, height); - win.setResizable(false); - win.center(); - }, + isMatchingHost: (_url, _baseUrl) => url.parse(_url).host === url.parse(_baseUrl).host, }; diff --git a/electron/js/window-manager.js b/electron/js/window-manager.js index 6a0e89fcc48..dda5a860198 100644 --- a/electron/js/window-manager.js +++ b/electron/js/window-manager.js @@ -17,18 +17,16 @@ * */ - const {BrowserWindow} = require('electron'); let primaryWindowId; +const getPrimaryWindow = () => primaryWindowId ? BrowserWindow.fromId(primaryWindowId) : BrowserWindow.getAllWindows()[0]; -const _getPrimaryWindow = () => primaryWindowId ? BrowserWindow.fromId(primaryWindowId) : BrowserWindow.getAllWindows()[0]; - -const _setPrimaryWindowId = (newPrimaryWindowId) => primaryWindowId = newPrimaryWindowId; +const setPrimaryWindowId = (newPrimaryWindowId) => primaryWindowId = newPrimaryWindowId; -const _showPrimaryWindow = () => { - const win = _getPrimaryWindow(); +const showPrimaryWindow = () => { + const win = getPrimaryWindow(); if (win.isMinimized()) { win.restore(); @@ -41,7 +39,7 @@ const _showPrimaryWindow = () => { module.exports = { - getPrimaryWindow: _getPrimaryWindow, - setPrimaryWindowId: _setPrimaryWindowId, - showPrimaryWindow: _showPrimaryWindow, + getPrimaryWindow, + setPrimaryWindowId, + showPrimaryWindow, }; diff --git a/electron/locale/locale.js b/electron/locale/locale.js index 95f8c9eaabc..3d253da7fd3 100644 --- a/electron/locale/locale.js +++ b/electron/locale/locale.js @@ -45,28 +45,28 @@ const tr = require('./strings-tr'); const uk = require('./strings-uk'); const SUPPORTED_LANGUAGES = { - 'en': 'English', - 'cs': 'Čeština', - 'da': 'Dansk', - 'de': 'Deutsch', - 'el': 'Ελληνικά', - 'et': 'Eesti', - 'es': 'Español', - 'fr': 'Français', - 'hr': 'Hrvatski', - 'it': 'Italiano', - 'lt': 'Lietuvos', - 'hu': 'Magyar', - 'nl': 'Nederlands', - 'pl': 'Polski', - 'pt': 'Português do Brasil', - 'ro': 'Română', - 'ru': 'Русский', - 'sk': 'Slovenčina', - 'sl': 'Slovenščina', - 'fi': 'Suomi', - 'tr': 'Türkçe', - 'uk': 'Українська', + en: 'English', + cs: 'Čeština', + da: 'Dansk', + de: 'Deutsch', + el: 'Ελληνικά', + et: 'Eesti', + es: 'Español', + fr: 'Français', + hr: 'Hrvatski', + it: 'Italiano', + lt: 'Lietuvos', + hu: 'Magyar', + nl: 'Nederlands', + pl: 'Polski', + pt: 'Português do Brasil', + ro: 'Română', + ru: 'Русский', + sk: 'Slovenčina', + sl: 'Slovenščina', + fi: 'Suomi', + tr: 'Türkçe', + uk: 'Українська', }; let current; @@ -81,7 +81,7 @@ const getCurrent = () => { return current; }; -const parseLocale = (locale) => { +const parseLocale = locale => { const languageKeys = getSupportedLanguageKeys(); return languageKeys.find((languageKey) => languageKey === locale) || languageKeys[0]; }; @@ -91,36 +91,36 @@ const getText = (string_identifier) => { return strings[string_identifier] || en[string_identifier] || ''; }; -const setLocale = (locale) => { +const setLocale = locale => { current = parseLocale(locale); settings.save('locale', current); }; module.exports = { - cs: cs, - da: da, - de: de, - el: el, - en: en, - es: es, - et: et, - fi: fi, - fr: fr, - hr: hr, - hu: hu, - it: it, - lt: lt, - nl: nl, - pl: pl, - pt: pt, - ro: ro, - ru: ru, - sk: sk, - sl: sl, - tr: tr, - uk: uk, - getCurrent: getCurrent, - getText: getText, - setLocale: setLocale, - SUPPORTED_LANGUAGES: SUPPORTED_LANGUAGES, + cs, + da, + de, + el, + en, + es, + et, + fi, + fr, + hr, + hu, + it, + lt, + nl, + pl, + pt, + ro, + ru, + sk, + sl, + tr, + uk, + getCurrent, + getText, + setLocale, + SUPPORTED_LANGUAGES, }; diff --git a/electron/main.js b/electron/main.js index a96a61ab943..5cb38218aae 100644 --- a/electron/main.js +++ b/electron/main.js @@ -56,10 +56,11 @@ const systemMenu = require('./js/menu/system'); const tray = require('./js/menu/tray'); const util = require('./js/util'); const windowManager = require('./js/window-manager'); +const EVENT_TYPE = require('./js/lib/eventType'); // Config const argv = minimist(process.argv.slice(1)); -const BASE_URL = environment.web.get_url_webapp(argv.env); +const BASE_URL = environment.web.getWebappUrl(argv.env); const pkg = require('./package.json'); // Icon @@ -121,7 +122,7 @@ if (environment.platform.IS_WINDOWS) { const squirrel = require('./js/squirrel'); squirrel.handleSquirrelEvent(shouldQuit); - ipcMain.on('wrapper-update', () => squirrel.installUpdate()); + ipcMain.on(EVENT_TYPE.WRAPPER.UPDATE, () => squirrel.installUpdate()); // Stop further execution on update to prevent second tray icon if (shouldQuit) { @@ -145,30 +146,30 @@ if (environment.platform.IS_LINUX) { /////////////////////////////////////////////////////////////////////////////// // IPC events /////////////////////////////////////////////////////////////////////////////// -ipcMain.once('webapp-version', (event, version) => { +ipcMain.once(EVENT_TYPE.UI.WEBAPP_VERSION, (event, version) => { webappVersion = version; }); -ipcMain.on('save-picture', (event, fileName, bytes) => { +ipcMain.on(EVENT_TYPE.ACTION.SAVE_PICTURE, (event, fileName, bytes) => { download(fileName, bytes); }); -ipcMain.on('notification-click', () => { +ipcMain.on(EVENT_TYPE.ACTION.NOTIFICATION_CLICK, () => { windowManager.showPrimaryWindow(); }); -ipcMain.on('badge-count', (event, count) => { +ipcMain.on(EVENT_TYPE.UI.BADGE_COUNT, (event, count) => { tray.updateBadgeIcon(main, count); }); -ipcMain.on('google-auth-request', event => { +ipcMain.on(EVENT_TYPE.GOOGLE_OAUTH.REQUEST, event => { googleAuth .getAccessToken(config.GOOGLE_SCOPES, config.GOOGLE_CLIENT_ID, config.GOOGLE_CLIENT_SECRET) .then(code => event.sender.send('google-auth-success', code.access_token)) .catch(error => event.sender.send('google-auth-error', error)); }); -ipcMain.on('delete-account-data', (e, accountID, sessionID) => { +ipcMain.on(EVENT_TYPE.ACCOUNT.DELETE_DATA, (event, accountID, sessionID) => { // delete webview partition try { if (sessionID) { @@ -191,7 +192,7 @@ ipcMain.on('delete-account-data', (e, accountID, sessionID) => { } }); -ipcMain.on('wrapper-relaunch', () => relaunchApp()); +ipcMain.on(EVENT_TYPE.WRAPPER.RELAUNCH, () => relaunchApp()); const relaunchApp = () => { app.relaunch(); @@ -353,7 +354,7 @@ const showAboutWindow = () => { }); // Locales - ipcMain.on('about-locale-values', (event, labels) => { + ipcMain.on(EVENT_TYPE.ABOUT.LOCALE_VALUES, (event, labels) => { if (event.sender.id !== about.webContents.id) { return; } @@ -361,7 +362,7 @@ const showAboutWindow = () => { for (const label of labels) { resultLabels[label] = locale.getText(label); } - event.sender.send('about-locale-render', resultLabels); + event.sender.send(EVENT_TYPE.ABOUT.LOCALE_RENDER, resultLabels); }); // Close window via escape @@ -378,7 +379,7 @@ const showAboutWindow = () => { about.loadURL(ABOUT_HTML); about.webContents.on('dom-ready', () => { - about.webContents.send('about-loaded', { + about.webContents.send(EVENT_TYPE.ABOUT.LOADED, { webappVersion: webappVersion, productName: pkg.productName, electronVersion: pkg.version, @@ -419,9 +420,7 @@ app.on('ready', () => { if (environment.app.IS_DEVELOPMENT) { appMenu.append(developerMenu); } - appMenu.on('about-wire', () => { - showAboutWindow(); - }); + appMenu.on(EVENT_TYPE.ABOUT.SHOW, () => showAboutWindow()); Menu.setApplicationMenu(appMenu); tray.createTrayIcon(); @@ -471,6 +470,7 @@ class ElectronWrapperInit { webviewProtectionDebug('Opening an external window from a webview. URL: %s', _url); shell.openExternal(_url); }; + const willNavigateInWebview = (event, _url) => { // Ensure navigation is to a whitelisted domain if (util.isMatchingHost(_url, BASE_URL)) { @@ -484,7 +484,7 @@ class ElectronWrapperInit { app.on('web-contents-created', (event, contents) => { switch (contents.getType()) { case 'window': - contents.on('will-attach-webview', (e, webPreferences, params) => { + contents.on('will-attach-webview', (event, webPreferences, params) => { const _url = params.src; // Use secure defaults @@ -497,7 +497,7 @@ class ElectronWrapperInit { // Verify the URL being loaded if (!util.isMatchingHost(_url, BASE_URL)) { - e.preventDefault(); + event.preventDefault(); webviewProtectionDebug('Prevented to show an unauthorized . URL: %s', _url); } }); @@ -505,12 +505,8 @@ class ElectronWrapperInit { case 'webview': // Open webview links outside of the app - contents.on('new-window', (e, _url) => { - openLinkInNewWindow(e, _url); - }); - contents.on('will-navigate', (e, _url) => { - willNavigateInWebview(e, _url); - }); + contents.on('new-window', openLinkInNewWindow); + contents.on('will-navigate', willNavigateInWebview); contents.session.setCertificateVerifyProc((request, cb) => { const {hostname = '', certificate = {}, error} = request; diff --git a/electron/renderer/src/components/Webviews.js b/electron/renderer/src/components/Webviews.js index 99e1cc500d4..da1128958e1 100644 --- a/electron/renderer/src/components/Webviews.js +++ b/electron/renderer/src/components/Webviews.js @@ -18,10 +18,9 @@ */ import React, {Component} from 'react'; - import Webview from './Webview'; - import './Webviews.css'; +import * as EVENT_TYPE from '../lib/eventType'; class Webviews extends Component { constructor(props) { @@ -84,29 +83,31 @@ class Webviews extends Component { _onIpcMessage(account, {channel, args}) { switch (channel) { - case 'notification-click': { - this.props.switchAccount(account.id); + case EVENT_TYPE.ACCOUNT.UPDATE_INFO: { + const [accountData] = args; + this.props.updateAccountData(account.id, accountData); break; } - case 'lifecycle-signed-in': - case 'lifecycle-signed-out': { - this.props.updateAccountLifecycle(account.id, channel); + case EVENT_TYPE.ACTION.NOTIFICATION_CLICK: { + this.props.switchAccount(account.id); break; } - case 'lifecycle-unread-count': { - this._onUnreadCountUpdated(account.id, args[0]); + case EVENT_TYPE.LIFECYCLE.SIGNED_IN: + case EVENT_TYPE.LIFECYCLE.SIGN_OUT: { + this.props.updateAccountLifecycle(account.id, channel); break; } - case 'signed-out': { + case EVENT_TYPE.LIFECYCLE.SIGNED_OUT: { this._deleteWebview(account); break; } - case 'team-info': { - this.props.updateAccountData(account.id, args[0]); + case EVENT_TYPE.LIFECYCLE.UNREAD_COUNT: { + const [badgeCount] = args; + this._onUnreadCountUpdated(account.id, badgeCount); break; } } diff --git a/electron/renderer/src/components/context/EditAccountMenu.js b/electron/renderer/src/components/context/EditAccountMenu.js index aecf05dc410..f6cb56f6b19 100644 --- a/electron/renderer/src/components/context/EditAccountMenu.js +++ b/electron/renderer/src/components/context/EditAccountMenu.js @@ -18,11 +18,12 @@ */ import React from 'react'; -import { connect } from 'react-redux'; -import { getText } from '../../lib/locale'; +import {connect} from 'react-redux'; +import {getText} from '../../lib/locale'; import ContextMenu from './ContextMenu'; import ContextMenuItem from './ContextMenuItem'; -import { abortAccountCreation, switchAccount } from '../../actions/'; +import {abortAccountCreation, switchAccount} from '../../actions/'; +import * as EVENT_TYPE from '../../lib/eventType'; function EditAccountMenu({ accountId, @@ -40,7 +41,7 @@ function EditAccountMenu({ {getText('wrapperManageTeam')} )} - {lifecycle === 'lifecycle-signed-in' && ( + {lifecycle === EVENT_TYPE.LIFECYCLE.SIGNED_IN && ( { connected.switchAccount(accountId); diff --git a/electron/renderer/src/index.js b/electron/renderer/src/index.js index 5f64f2cd70f..c58af035c5f 100644 --- a/electron/renderer/src/index.js +++ b/electron/renderer/src/index.js @@ -18,16 +18,16 @@ */ import React from 'react'; -import { render } from 'react-dom'; -import { applyMiddleware, createStore } from 'redux'; -import { Provider } from 'react-redux'; +import {render} from 'react-dom'; +import {applyMiddleware, createStore} from 'redux'; +import {Provider} from 'react-redux'; import thunk from 'redux-thunk'; import logger from 'redux-logger'; import throttle from 'lodash/throttle'; import App from './components/App'; import appStore from './reducers'; -import { loadState, saveState } from './lib/localStorage'; +import {loadState, saveState} from './lib/localStorage'; import './Index.css'; diff --git a/electron/renderer/src/lib/eventType.js b/electron/renderer/src/lib/eventType.js new file mode 100644 index 00000000000..87607b58ee3 --- /dev/null +++ b/electron/renderer/src/lib/eventType.js @@ -0,0 +1,31 @@ +/* + * Wire + * Copyright (C) 2018 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +export const ACCOUNT = { + UPDATE_INFO: 'EVENT_TYPE.ACCOUNT.UPDATE_INFO', +}; +export const ACTION = { + NOTIFICATION_CLICK: 'EVENT_TYPE.ACTION.NOTIFICATION_CLICK', +}; +export const LIFECYCLE = { + SIGN_OUT: 'EVENT_TYPE.LIFECYCLE.SIGN_OUT', + SIGNED_IN: 'EVENT_TYPE.LIFECYCLE.SIGNED_IN', + SIGNED_OUT: 'EVENT_TYPE.LIFECYCLE.SIGNED_OUT', + UNREAD_COUNT: 'EVENT_TYPE.LIFECYCLE.UNREAD_COUNT', +}; diff --git a/electron/renderer/src/reducers/accountReducer.js b/electron/renderer/src/reducers/accountReducer.js index c54c9f36515..14145678eee 100644 --- a/electron/renderer/src/reducers/accountReducer.js +++ b/electron/renderer/src/reducers/accountReducer.js @@ -38,7 +38,9 @@ const createAccount = sessionId => { const accountReducer = (state = [createAccount()], action) => { switch (action.type) { case ActionCreator.ADD_ACCOUNT: { - return state.map(account => ({...account, visible: false})).push(createAccount(action.sessionID)); + const newState = state.map(account => ({...account, visible: false})); + newState.push(createAccount(action.sessionID)); + return newState; } case ActionCreator.DELETE_ACCOUNT: { diff --git a/electron/renderer/static/webview-preload.js b/electron/renderer/static/webview-preload.js index 4bf0087e683..2a90720bdd9 100644 --- a/electron/renderer/static/webview-preload.js +++ b/electron/renderer/static/webview-preload.js @@ -22,6 +22,7 @@ const environment = require('../../js/environment'); const fs = require('fs-extra'); const path = require('path'); const winston = require('winston'); +const EVENT_TYPE = require('../../js/lib/eventType'); const {desktopCapturer, ipcRenderer, remote, webFrame} = require('electron'); const {app} = remote; @@ -33,81 +34,82 @@ webFrame.registerURLSchemeAsBypassingCSP('file'); const subscribeToWebappEvents = () => { amplify.subscribe(z.event.WebApp.LIFECYCLE.RESTART, update_source => { const isUpdateSourceDesktop = update_source === z.lifecycle.UPDATE_SOURCE.DESKTOP; - ipcRenderer.send(isUpdateSourceDesktop ? 'wrapper-update' : 'wrapper-relaunch'); + const eventType = isUpdateSourceDesktop ? EVENT_TYPE.WRAPPER.UPDATE : EVENT_TYPE.WRAPPER.RELAUNCH; + ipcRenderer.send(eventType); }); amplify.subscribe(z.event.WebApp.LIFECYCLE.LOADED, () => { - ipcRenderer.sendToHost('lifecycle-signed-in'); + ipcRenderer.sendToHost(EVENT_TYPE.LIFECYCLE.SIGNED_IN); }); amplify.subscribe(z.event.WebApp.LIFECYCLE.SIGN_OUT, () => { - ipcRenderer.sendToHost('lifecycle-signed-out'); + ipcRenderer.sendToHost(EVENT_TYPE.LIFECYCLE.SIGN_OUT); }); amplify.subscribe(z.event.WebApp.LIFECYCLE.SIGNED_OUT, clearData => { if (clearData) { - ipcRenderer.sendToHost('signed-out'); + ipcRenderer.sendToHost(EVENT_TYPE.LIFECYCLE.SIGNED_OUT); } }); amplify.subscribe(z.event.WebApp.LIFECYCLE.UNREAD_COUNT, count => { - ipcRenderer.sendToHost('lifecycle-unread-count', count); + ipcRenderer.sendToHost(EVENT_TYPE.LIFECYCLE.UNREAD_COUNT, count); }); amplify.subscribe(z.event.WebApp.NOTIFICATION.CLICK, () => { - ipcRenderer.send('notification-click'); - ipcRenderer.sendToHost('notification-click'); + ipcRenderer.send(EVENT_TYPE.ACTION.NOTIFICATION_CLICK); + ipcRenderer.sendToHost(EVENT_TYPE.ACTION.NOTIFICATION_CLICK); }); amplify.subscribe(z.event.WebApp.TEAM.INFO, info => { - ipcRenderer.sendToHost('team-info', info); + ipcRenderer.sendToHost(EVENT_TYPE.ACCOUNT.UPDATE_INFO, info); }); }; const subscribeToMainProcessEvents = () => { - ipcRenderer.on('conversation-add-people', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.ADD_PEOPLE, () => { amplify.publish(z.event.WebApp.SHORTCUT.ADD_PEOPLE); }); - ipcRenderer.on('conversation-archive', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.ARCHIVE, () => { amplify.publish(z.event.WebApp.SHORTCUT.ARCHIVE); }); - ipcRenderer.on('conversation-call', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.CALL, () => { amplify.publish(z.event.WebApp.CALL.STATE.TOGGLE, false); }); - ipcRenderer.on('conversation-delete', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.DELETE, () => { amplify.publish(z.event.WebApp.SHORTCUT.DELETE); }); - ipcRenderer.on('conversation-next', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.SHOW_NEXT, () => { amplify.publish(z.event.WebApp.SHORTCUT.NEXT); }); - ipcRenderer.on('conversation-people', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.PEOPLE, () => { amplify.publish(z.event.WebApp.SHORTCUT.PEOPLE); }); - ipcRenderer.on('conversation-ping', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.PING, () => { amplify.publish(z.event.WebApp.SHORTCUT.PING); }); - ipcRenderer.on('conversation-prev', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.SHOW_PREVIOUS, () => { amplify.publish(z.event.WebApp.SHORTCUT.PREV); }); - ipcRenderer.on('conversation-show', conversationId => { - amplify.publish(z.event.WebApp.CONVERSATION.SHOW, conversationId) + ipcRenderer.on(EVENT_TYPE.CONVERSATION.SHOW, conversationId => { + amplify.publish(z.event.WebApp.CONVERSATION.SHOW, conversationId); }); - ipcRenderer.on('conversation-silence', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.TOGGLE_MUTE, () => { amplify.publish(z.event.WebApp.SHORTCUT.SILENCE); }); - ipcRenderer.on('conversation-start', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.START, () => { amplify.publish(z.event.WebApp.SHORTCUT.START); }); - ipcRenderer.on('conversation-video-call', () => { + ipcRenderer.on(EVENT_TYPE.CONVERSATION.VIDEO_CALL, () => { amplify.publish(z.event.WebApp.CALL.STATE.TOGGLE, true); }); - ipcRenderer.on('preferences-show', () => { + ipcRenderer.on(EVENT_TYPE.PREFERENCES.SHOW, () => { amplify.publish(z.event.WebApp.PREFERENCES.MANAGE_ACCOUNT); }); - ipcRenderer.on('sign-out', () => { + ipcRenderer.on(EVENT_TYPE.ACTION.SIGN_OUT, () => { amplify.publish(z.event.WebApp.LIFECYCLE.ASK_TO_CLEAR_DATA); }); - ipcRenderer.on('wrapper-update-available', () => { + ipcRenderer.on(EVENT_TYPE.WRAPPER.UPDATE_AVAILABLE, () => { amplify.publish(z.event.WebApp.LIFECYCLE.UPDATE, z.lifecycle.UPDATE_SOURCE.DESKTOP); }); }; @@ -139,9 +141,9 @@ const replaceGoogleAuth = () => { // hijack google authenticate method window.wire.app.service.connect_google._authenticate = () => { return new Promise((resolve, reject) => { - ipcRenderer.send('google-auth-request'); - ipcRenderer.once('google-auth-success', (event, token) => resolve(token)); - ipcRenderer.once('google-auth-error', reject); + ipcRenderer.send(EVENT_TYPE.GOOGLE_OAUTH.REQUEST); + ipcRenderer.once(EVENT_TYPE.GOOGLE_OAUTH.SUCCESS, (event, token) => resolve(token)); + ipcRenderer.once(EVENT_TYPE.GOOGLE_OAUTH.ERROR, reject); }); }; }; @@ -166,7 +168,7 @@ const enableFileLogging = () => { } }; -const reportWebappVersion = () => ipcRenderer.send('webapp-version', z.util.Environment.version(false)); +const reportWebappVersion = () => ipcRenderer.send(EVENT_TYPE.UI.WEBAPP_VERSION, z.util.Environment.version(false)); const checkAvailability = callback => { const intervalId = setInterval(() => {