Commit 0280405c authored by Gabriel Engel's avatar Gabriel Engel

Merge branch 'develop'

* develop: (51 commits)
  [FIX] Use Electron notifications (#1101)
  [FIX] Updates preloads scripts to be compatible with Rocket.Chat >0.74.0 (#1099)
  Update gulp
  Update dependencies
  [IMPROVE] i18next (#1096)
  [IMPROVE] New tray icons (#1093)
  [CHORE] Remove unused styles (#1092)
  [IMPROVE] Remove update-remind-later-dialog (#1076)
  Fix for basic-auth servers connect (#1074)
  Fix remember window state on load (#1080)
  Update provisioning profile
  Disable artifact collection by AppVeyor (#1081)
  Add workaround for webview readiness
  update dependencies electron => 4.0.1
  [improve] resolve requested changes
  Replace istanbul with nyc
  Work around icon window in e2e tests
  Add missing id in menu item
  Enable tests in CI
  Fix e2e tests
  ...
parents f12c0940 db4a1f8d
......@@ -13,7 +13,7 @@ indent_style = tab
[*.i18n.json]
indent_style = space
indent_size = 2
indent_size = 4
[*.md]
trim_trailing_whitespace = false
.DS_Store
Thumbs.db
*.log
*.autogenerated
/node_modules
/package-lock.json
......
language: node_js
node_js: 8
node_js: 10
cache:
yarn: true
directories:
......@@ -49,6 +49,8 @@ notifications:
install:
- yarn
- yarn test
- yarn e2e
script:
- if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then export CSC_IDENTITY_AUTO_DISCOVERY=false; fi
......
image: Visual Studio 2017
environment:
nodejs_version: "8"
nodejs_version: "10"
platform:
- x64
skip_tags: true
......@@ -21,11 +21,8 @@ install:
- ps: Install-Product node $env:nodejs_version $env:platform
- set CI=true
- yarn
- yarn list
- yarn test
- yarn e2e
build_script:
- yarn release
artifacts:
- path: 'dist\*.exe'
- path: 'dist\*.appx'
build/appx/Square150x150Logo.png

3.73 KB | W: | H:

build/appx/Square150x150Logo.png

6.76 KB | W: | H:

build/appx/Square150x150Logo.png
build/appx/Square150x150Logo.png
build/appx/Square150x150Logo.png
build/appx/Square150x150Logo.png
  • 2-up
  • Swipe
  • Onion skin
build/appx/Square44x44Logo.png

1.14 KB | W: | H:

build/appx/Square44x44Logo.png

1.87 KB | W: | H:

build/appx/Square44x44Logo.png
build/appx/Square44x44Logo.png
build/appx/Square44x44Logo.png
build/appx/Square44x44Logo.png
  • 2-up
  • Swipe
  • Onion skin
build/appx/StoreLogo.png

1.29 KB | W: | H:

build/appx/StoreLogo.png

2.15 KB | W: | H:

build/appx/StoreLogo.png
build/appx/StoreLogo.png
build/appx/StoreLogo.png
build/appx/StoreLogo.png
  • 2-up
  • Swipe
  • Onion skin
build/appx/Wide310x150Logo.png

4.4 KB | W: | H:

build/appx/Wide310x150Logo.png

7.09 KB | W: | H:

build/appx/Wide310x150Logo.png
build/appx/Wide310x150Logo.png
build/appx/Wide310x150Logo.png
build/appx/Wide310x150Logo.png
  • 2-up
  • Swipe
  • Onion skin
No preview for this file type
build/icon.ico

32.2 KB | W: | H:

build/icon.ico

353 KB | W: | H:

build/icon.ico
build/icon.ico
build/icon.ico
build/icon.ico
  • 2-up
  • Swipe
  • Onion skin
build/icons/512x512.png

50.1 KB | W: | H:

build/icons/512x512.png

29.2 KB | W: | H:

build/icons/512x512.png
build/icons/512x512.png
build/icons/512x512.png
build/icons/512x512.png
  • 2-up
  • Swipe
  • Onion skin
build/installerIcon.ico

32.2 KB | W: | H:

build/installerIcon.ico

353 KB | W: | H:

build/installerIcon.ico
build/installerIcon.ico
build/installerIcon.ico
build/installerIcon.ico
  • 2-up
  • Swipe
  • Onion skin
build/uninstallerIcon.ico

32.2 KB | W: | H:

build/uninstallerIcon.ico

353 KB | W: | H:

build/uninstallerIcon.ico
build/uninstallerIcon.ico
build/uninstallerIcon.ico
build/uninstallerIcon.ico
  • 2-up
  • Swipe
  • Onion skin
......@@ -19,7 +19,7 @@
"mas"
],
"icon": "build/icon.icns",
"bundleVersion": "44",
"bundleVersion": "46",
"helperBundleId": "chat.rocket.electron.helper",
"type": "distribution",
"artifactName": "rocketchat-${version}.${ext}",
......
'use strict';
require('./tasks/build-app');
require('./tasks/build-tests');
require('./tasks/release');
require('./tasks/start');
......@@ -2,7 +2,7 @@
"name": "rocketchat",
"productName": "Rocket.Chat",
"description": "Rocket.Chat Native Cross-Platform Desktop Application via Electron.",
"version": "2.14.7",
"version": "2.15.0-develop",
"author": "Rocket.Chat Support <support@rocket.chat>",
"copyright": "© 2018, Rocket.Chat",
"homepage": "https://rocket.chat",
......@@ -14,59 +14,73 @@
},
"scripts": {
"postinstall": "electron-builder install-app-deps",
"postremove": "electron-builder install-app-deps",
"start": "gulp start",
"build": "gulp build-app",
"build:icons": "node tasks/build-icons.js",
"changelog": "conventional-changelog --config .github/changelog.js -i HISTORY.md -s",
"release": "gulp release --env=production",
"release-dev": "gulp release --env=development",
"release-mas-dev": "build --publish never --mac mas-dev --c.mac.provisioningProfile=Development.provisionprofile",
"lint": "eslint src",
"pretest": "gulp build-unit-tests --env=test",
"test-main": "electron-mocha --require source-map-support/register app/main.specs.js",
"test-renderer": "electron-mocha --require source-map-support/register --renderer app/renderer.specs.js",
"test-main": "xvfb-maybe electron-mocha --require source-map-support/register app/main.specs.js",
"test-renderer": "xvfb-maybe electron-mocha --require source-map-support/register --renderer app/renderer.specs.js",
"test": "npm-run-all test-main test-renderer",
"coverage": "npm test -- -R scripts/istanbul-reporter",
"precoverage": "gulp build-coverage-tests --env=test",
"coverage-main": "xvfb-maybe electron-mocha --require source-map-support/register --reporter tasks/coverage-reporter app/main.specs.js",
"coverage-renderer": "xvfb-maybe electron-mocha --require source-map-support/register --reporter tasks/coverage-reporter app/renderer.specs.js",
"coverage": "npm-run-all coverage-main coverage-renderer",
"postcoverage": "node tasks/coverage-reporter",
"pree2e": "gulp build-e2e-tests --env=test",
"e2e": "mocha app/e2e.js.autogenerated --require source-map-support/register"
"e2e": "xvfb-maybe mocha --require source-map-support/register app/e2e.js"
},
"dependencies": {
"@paulcbetts/system-idle-time": "^1.0.4",
"electron-updater": "3.0.4",
"freedesktop-notifications": "^1.2.3",
"electron-updater": "^4.0.6",
"fs-jetpack": "^2.2.0",
"lodash": "^4.17.11",
"spellchecker": "^3.5.0",
"tmp": "^0.0.33"
"i18next": "^15.0.4",
"i18next-node-fs-backend": "^2.1.1",
"i18next-sync-fs-backend": "^1.1.0",
"mem": "^4.1.0",
"spellchecker": "^3.5.0"
},
"optionalDependencies": {},
"devDependencies": {
"@fiahfy/icns-convert": "^0.0.5",
"@rocket.chat/eslint-config": "^0.1.2",
"builtin-modules": "^3.0.0",
"chai": "^4.2.0",
"conventional-changelog-cli": "^2.0.11",
"electron": "^2.0.14",
"electron-builder": "^20.28.4",
"convert-svg-to-png": "^0.5.0",
"electron": "^4.0.1",
"electron-builder": "^20.38.4",
"electron-mocha": "^6.0.4",
"eslint": "^5.9.0",
"gulp": "^3.9.1",
"eslint": "^5.12.0",
"gulp": "^4.0.0",
"gulp-batch": "^1.0.5",
"gulp-cli": "^2.0.1",
"gulp-less": "^4.0.1",
"gulp-plumber": "^1.2.0",
"gulp-rename": "^1.4.0",
"gulp-util": "^3.0.8",
"gulp-watch": "^5.0.1",
"istanbul": "^0.4.5",
"minimist": "^1.2.0",
"mocha": "^5.2.0",
"mocha": "^6.0.1",
"npm-run-all": "^4.1.3",
"rollup": "^0.67.3",
"nyc": "^13.1.0",
"rollup": "^1.1.0",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-istanbul": "^2.0.1",
"rollup-plugin-json": "^3.1.0",
"rollup-plugin-node-resolve": "^4.0.0",
"rollup-plugin-replace": "^2.1.0",
"run-sequence": "^2.2.1",
"sinon": "^7.1.1",
"spectron": "^5.0.0"
"sinon": "^7.2.2",
"spectron": "^5.0.0",
"to-ico": "^1.1.5",
"xvfb-maybe": "^0.2.1"
},
"devEngines": {
"node": ">=7.x",
"node": ">=8.12.x",
"npm": ">=4.x",
"yarn": ">=0.21.3"
}
......
var istanbul = require('istanbul');
module.exports = function (runner, options) {
mocha.reporters.Base.call(this, runner);
var reporterOpts = { dir: 'coverage' },
reporters = ['text-summary', 'html'];
options = options || {};
if (options.reporters) reporters = options.reporters.split(',');
if (process.env.ISTANBUL_REPORTERS) reporters = process.env.ISTANBUL_REPORTERS.split(',');
if (options.reportDir) reporterOpts.dir = options.reportDir;
if (process.env.ISTANBUL_REPORT_DIR) reporterOpts.dir = process.env.ISTANBUL_REPORT_DIR;
runner.on('end', function(){
var cov = global.__coverage__ || {},
collector = new istanbul.Collector();
collector.add(cov);
reporters.forEach(function(reporter) {
istanbul.Report.create(reporter, reporterOpts).writeReport(collector, true);
});
});
};
import { start } from './scripts/start';
import './branding/branding.js';
start();
import { app, ipcMain, Menu } from 'electron';
import { app, ipcMain } from 'electron';
import querystring from 'querystring';
import url from 'url';
import idle from '@paulcbetts/system-idle-time';
import './background/aboutDialog';
import appData from './background/appData';
import autoUpdate from './background/autoUpdate';
import certificate from './background/certificate';
import dock from './background/dock';
export { default as dock } from './background/dock';
import { addServer, getMainWindow } from './background/mainWindow';
import menus from './background/menus';
import './background/notifications';
import './background/screenshare';
import tray from './background/tray';
import i18n from './i18n/index.js';
export { default as showAboutDialog } from './background/aboutDialog';
export { default as menus } from './background/menus';
export { default as notifications } from './background/notifications';
import './background/screenshareDialog';
export { default as remoteServers } from './background/servers';
export { certificate, dock, menus, tray };
export { default as tray } from './background/tray';
import './background/updateDialog';
import './background/updates';
import i18n from './i18n';
export { certificate };
process.env.GOOGLE_API_KEY = 'AIzaSyADqUh_c1Qhji3Cp1NE43YrcpuPkmhXD-c';
const unsetDefaultApplicationMenu = () => {
if (process.platform !== 'darwin') {
Menu.setApplicationMenu(null);
return;
}
const emptyMenuTemplate = [{
submenu: [
{
label: i18n.__('&Quit %s', app.getName()),
accelerator: 'CommandOrControl+Q',
click() {
app.quit();
},
},
],
}];
Menu.setApplicationMenu(Menu.buildFromTemplate(emptyMenuTemplate));
};
const parseProtocolUrls = (args) =>
args.filter((arg) => /^rocketchat:\/\/./.test(arg))
.map((uri) => url.parse(uri))
......@@ -53,15 +29,6 @@ const parseProtocolUrls = (args) =>
const addServers = (protocolUrls) => parseProtocolUrls(protocolUrls)
.forEach((serverUrl) => addServer(serverUrl));
const isSecondInstance = app.makeSingleInstance(async(argv) => {
(await getMainWindow()).show();
addServers(argv.slice(2));
});
if (isSecondInstance && !process.mas) {
app.quit();
}
// macOS only
app.on('open-url', (event, url) => {
event.preventDefault();
......@@ -80,20 +47,27 @@ app.setAppUserModelId('chat.rocket');
if (process.platform === 'linux') {
app.disableHardwareAcceleration();
}
app.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required');
app.on('ready', async() => {
unsetDefaultApplicationMenu();
process.on('unhandledRejection', console.error.bind(console));
appData.initialize();
const mainWindow = await getMainWindow();
certificate.initWindow(mainWindow);
const gotTheLock = app.requestSingleInstanceLock();
autoUpdate();
});
if (gotTheLock) {
app.on('second-instance', async(event, argv) => {
(await getMainWindow()).show();
addServers(argv.slice(2));
});
ipcMain.on('getSystemIdleTime', (event) => {
event.returnValue = idle.getIdleTime();
});
app.on('ready', async() => {
appData.initialize();
await i18n.initialize();
const mainWindow = await getMainWindow();
certificate.initWindow(mainWindow);
process.on('unhandledRejection', console.error.bind(console));
ipcMain.emit('check-for-updates');
});
} else {
app.quit();
}
import { app, BrowserWindow } from 'electron';
import { app, BrowserWindow, ipcMain } from 'electron';
import { getMainWindow } from './mainWindow';
import i18n from '../i18n/index.js';
import i18n from '../i18n';
let aboutWindow;
const openAboutDialog = async() => {
if (aboutWindow) {
return;
}
export default async() => {
const mainWindow = await getMainWindow();
const win = new BrowserWindow({
title: i18n.__('About %s', app.getName()),
aboutWindow = new BrowserWindow({
title: i18n.__('dialog.about.title', { appName: app.getName() }),
parent: mainWindow,
modal: process.platform !== 'darwin',
width: 400,
height: 300,
type: 'toolbar',
resizable: false,
fullscreenable: false,
maximizable: false,
minimizable: false,
center: true,
fullscreen: false,
show: false,
});
win.setMenuBarVisibility(false);
win.once('ready-to-show', () => win.show());
win.loadURL(`file://${ __dirname }/public/about.html`);
aboutWindow.setMenuBarVisibility(false);
aboutWindow.once('ready-to-show', () => {
aboutWindow.show();
});
aboutWindow.once('closed', () => {
aboutWindow = null;
});
aboutWindow.params = { appName: app.getName(), appVersion: app.getVersion() };
aboutWindow.loadFile(`${ __dirname }/public/about-dialog.html`);
};
const closeAboutDialog = () => {
aboutWindow && aboutWindow.destroy();
};
ipcMain.on('open-about-dialog', () => openAboutDialog());
ipcMain.on('close-about-dialog', () => closeAboutDialog());
import { app, ipcMain } from 'electron';
import jetpack from 'fs-jetpack';
import path from 'path';
import env from '../env';
const definePath = () => {
const appName = app.getName();
const dirName = env.name === 'production' ? appName : `${ appName } (${ env.name })`;
const dirName = process.env.NODE_ENV === 'production' ? appName : `${ appName } (${ process.env.NODE_ENV })`;
app.setPath('userData', path.join(app.getPath('appData'), dirName));
};
......@@ -20,7 +19,7 @@ const reset = () => {
const migrate = () => {
const olderAppName = 'Rocket.Chat+';
const dirName = env.name === 'production' ? olderAppName : `${ olderAppName } (${ env.name })`;
const dirName = process.env.NODE_ENV === 'production' ? olderAppName : `${ olderAppName } (${ process.env.NODE_ENV })`;
const olderUserDataPath = path.join(app.getPath('appData'), dirName);
try {
......
import { app, dialog } from 'electron';
import jetpack from 'fs-jetpack';
import url from 'url';
import i18n from '../i18n/index.js';
import i18n from '../i18n';
class CertificateStore {
initWindow(win) {
......@@ -31,17 +31,17 @@ class CertificateStore {
let detail = `URL: ${ url }\nError: ${ error }`;
if (this.isExisting(url)) {
detail = i18n.__('Certificate_error_different', detail);
detail = i18n.__('error.differentCertificate', { detail });
}
dialog.showMessageBox(this.window, {
title: i18n.__('Certificate_error'),
message: i18n.__('Certificate_error_message', certificate.issuerName),
title: i18n.__('dialog.certificateError.title'),
message: i18n.__('dialog.certificateError.message', { issuerName: certificate.issuerName }),
detail,
type: 'warning',
buttons: [
i18n.__('Yes'),
i18n.__('No'),
i18n.__('dialog.certificateError.yes'),
i18n.__('dialog.certificateError.no'),
],
cancelId: 1,
}, (response) => {
......
import { app } from 'electron';
import { EventEmitter } from 'events';
import { getMainWindow } from './mainWindow';
import icon from './icon';
import { getTrayIconImage, getAppIconImage } from './icon';
const getBadgeText = ({ badge: { title, count } }) => {
if (title === '') {
return '';
} else if (count > 0) {
return count > 9 ? '9+' : String(count);
} else if (title) {
return '!';
return String(count);
}
};
......@@ -19,7 +17,7 @@ let state = {
title: '',
count: 0,
},
status: 'online',
hasTrayIcon: false,
};
const instance = new (class Dock extends EventEmitter {});
......@@ -32,18 +30,6 @@ const update = async(previousState) => {
const mainWindow = await getMainWindow();
const badgeText = getBadgeText(state);
if (process.platform === 'win32') {
const image = badgeText ? await icon.render({
overlay: true,
size: 16,
badgeText,
}) : null;
mainWindow.setOverlayIcon(image, badgeText || '');
mainWindow.removeListener('show', update);
mainWindow.on('show', update);
}
if (process.platform === 'darwin') {
app.dock.setBadge(badgeText || '');
if (state.badge.count > 0 && previousState.badge.count === 0) {
......@@ -51,14 +37,9 @@ const update = async(previousState) => {
}
}
if (process.platform === 'linux') {
mainWindow.setIcon(await icon.render({
badgeText,
size: {
win32: [256, 128, 64, 48, 32, 24, 16],
linux: 128,
}[process.platform],
}));
if (process.platform === 'linux' || process.platform === 'win32') {
const image = state.hasTrayIcon ? getAppIconImage() : getTrayIconImage(state.badge);
mainWindow.setIcon(image);
}
if (!mainWindow.isFocused()) {
......
import { BrowserWindow, nativeImage } from 'electron';
import jetpack from 'fs-jetpack';
import { whenReadyToShow } from './utils';
import { nativeImage, systemPreferences } from 'electron';
let rendererWindow = null;
const getRendererWindow = async() => {
if (!rendererWindow) {
rendererWindow = new BrowserWindow({ show: false });
const dataURL = `data:text/html,<!doctype html>
${ jetpack.read(`${ __dirname }/public/images/icon.svg`) }`;
rendererWindow.loadURL(dataURL);
await whenReadyToShow(rendererWindow);
function getTrayIconSet({ platform, dark }) {
if (platform === 'darwin') {
return `darwin${ dark ? '-dark' : '' }`;
}
return rendererWindow;
};
const renderInWindow = async(style) => {
const statusColors = {
offline: null,
away: 'yellow',
busy: 'red',
online: 'lime',
};
const create = ({ overlay, template, status, badgeText } = {}) => {
const svg = document.querySelector('#icon').cloneNode(true);
svg.querySelector('.logo .baloon').style.fill = template ? '#FFFFFF' : '#DB2323';
svg.querySelector('.logo .circles').style.fill = template ? '#FFFFFF' : '#DB2323';
svg.querySelector('.status .away').style.fill = template ? '#FFFFFF' : '#DB2323';
svg.querySelector('.status .busy').style.fill = template ? '#FFFFFF' : '#DB2323';
svg.querySelector('.logo .bubble').style.display = template ? 'none' : null;
svg.querySelector('.badge').style.display = (!template && badgeText) ? null : 'none';
svg.querySelector('.badge text').innerHTML = badgeText;
svg.querySelector('.logo .circles').style.display = (template && status && status !== 'online') ? 'none' : '';
svg.querySelector('.status circle').style.display = (template || !status) ? 'none' : null;
svg.querySelector('.status .away').style.display = (template && status === 'away') ? null : 'none';
svg.querySelector('.status .busy').style.display = (template && status === 'busy') ? null : 'none';
svg.querySelector('.status circle').style.fill = statusColors[status];
return platform;
}
if (overlay) {
const overlaySVG = svg.cloneNode(true);
svg.remove();
overlaySVG.querySelector('.logo').remove();
overlaySVG.querySelector('.status').remove();
overlaySVG.setAttribute('viewBox', '96 -32 160 160');
return overlaySVG;
}
return svg;
};
const rasterize = async(svg, size) => {
const image = new Image();
image.src = `data:image/svg+xml,${ encodeURIComponent(svg.outerHTML) }`;
image.width = image.height = size;
await new Promise((resolve, reject) => {
image.onload = resolve;
image.onerror = reject;
});
function getTrayIconName({ title, count, platform }) {
if (platform === 'darwin') {
return (title || count) ? 'notification' : 'default';
}
const canvas = document.createElement('canvas');
canvas.width = canvas.height = size;
if (title === '') {
return 'notification-dot';
} else if (count > 0) {
return count > 9 ? 'notification-plus-9' : `notification-${ String(count) }`;
}