Unverified Commit 155fa078 authored by Tasso Evangelista's avatar Tasso Evangelista Committed by GitHub

[FIX] [NEW] Auto update fixes and settings enforcement (#837)

* Use electron-builder API instead of cli and remove build config from package.json

* Fix Windows setup file name

After electron-builder update, productName is prefered over package
name. This commit reverts that.

* Add Windows installer bitmaps

* Move Windows installer script

* Update the list of platforms which autoUpdater can be run

* Improve handling of update and auto update

* Add feature to force update settings from app to user

* Add check if user can set auto update setting

* Fix artifactName for macOS builds
parent a4faf590
......@@ -3,7 +3,6 @@
CreateShortCut "$SMSTARTUP\Rocket.Chat.lnk" "$INSTDIR\Rocket.Chat.exe" ""
FunctionEnd
; Using the read me setting as an easy way to add an add to startup option
!define MUI_FINISHPAGE_SHOWREADME
!define MUI_FINISHPAGE_SHOWREADME_TEXT "Run at startup"
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION AddToStartup
......@@ -21,11 +20,6 @@
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION un.AddAppData
!endif
!macro customInstall
; Required as electron-builder does not provide a way to specify it as of version 11.2.4
WriteRegStr SHCTX "${UNINSTALL_REGISTRY_KEY}" "DisplayIcon" '"$INSTDIR\resources\build\icon.ico"'
!macroend
!macro customUnInstall
${IfNot} ${Silent}
Delete "$SMSTARTUP\Rocket.Chat.lnk"
......
{
"appId": "chat.rocket",
"files": [
"app/**/*",
"node_modules/**/*",
"package.json"
],
"extraResources": [
"dictionaries/**/*",
"build/icon.ico",
"servers.json"
],
"mac": {
"bundleVersion": "30",
"helperBundleId": "chat.rocket.electron.helper",
"category": "public.app-category.productivity",
"target": [
"default",
"pkg",
"mas"
],
"artifactName": "rocketchat-${version}.${ext}"
},
"nsis": {
"oneClick": false,
"perMachine": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true,
"artifactName": "rocketchat-setup-${version}.${ext}"
},
"appx": {
"backgroundColor": "#2f343d",
"displayName": "Rocket.Chat",
"publisherDisplayName": "Rocket.Chat",
"languages": [
"en-US",
"en-GB",
"pt-BR"
],
"artifactName": "rocketchat-setup-${version}.${ext}"
},
"linux": {
"desktop": {
"StartupWMClass": "Rocket.Chat",
"MimeType": "x-scheme-handler/rocketchat"
},
"category": "GNOME;GTK;Network;InstantMessaging",
"target": [
"tar.gz",
"deb",
"rpm",
"snap"
]
},
"publish": [
{
"provider": "github",
"owner": "RocketChat",
"repo": "Rocket.Chat.Electron",
"vPrefixedTagName": false
}
]
}
......@@ -12,68 +12,6 @@
"type": "git",
"url": "https://github.com/RocketChat/Rocket.Chat.Electron.git"
},
"build": {
"appId": "chat.rocket",
"files": [
"app/**/*",
"node_modules/**/*",
"package.json"
],
"extraResources": [
"dictionaries/**/*",
"build/icon.ico",
"servers.json"
],
"mac": {
"bundleVersion": "30",
"helperBundleId": "chat.rocket.electron.helper",
"category": "public.app-category.productivity",
"target": [
"dmg",
"pkg",
"zip",
"mas"
]
},
"nsis": {
"include": "build/win/installer.nsh",
"oneClick": false,
"perMachine": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true
},
"appx": {
"backgroundColor": "#2f343d",
"displayName": "Rocket.Chat",
"publisherDisplayName": "Rocket.Chat",
"languages": [
"en-US",
"en-GB",
"pt-BR"
]
},
"linux": {
"desktop": {
"StartupWMClass": "Rocket.Chat",
"MimeType": "x-scheme-handler/rocketchat"
},
"category": "GNOME;GTK;Network;InstantMessaging",
"target": [
"tar.gz",
"deb",
"rpm",
"snap"
]
},
"publish": [
{
"provider": "github",
"owner": "RocketChat",
"repo": "Rocket.Chat.Electron",
"vPrefixedTagName": false
}
]
},
"scripts": {
"postinstall": "electron-builder install-app-deps",
"start": "gulp start",
......@@ -109,7 +47,6 @@
"gulp-less": "^4.0.1",
"gulp-plumber": "^1.2.0",
"gulp-rename": "^1.4.0",
"gulp-sequence": "^1.0.0",
"gulp-util": "^3.0.8",
"gulp-watch": "^5.0.1",
"istanbul": "^0.4.5",
......
......@@ -5,7 +5,7 @@ import jetpack from 'fs-jetpack';
import idle from '@paulcbetts/system-idle-time';
import { app, ipcMain, Menu } from 'electron';
import { canUpdate, checkForUpdates } from './background/autoUpdate';
import autoUpdate from './background/autoUpdate';
import certificate from './background/certificate';
import { addServer, createMainWindow, getMainWindow } from './background/mainWindow';
import './background/screenshare';
......@@ -98,9 +98,7 @@ app.on('ready', () => {
getMainWindow().then(mainWindow => certificate.initWindow(mainWindow));
if (canUpdate()) {
checkForUpdates();
}
autoUpdate();
});
app.on('window-all-closed', () => {
......
......@@ -3,21 +3,41 @@ import { autoUpdater } from 'electron-updater';
import jetpack from 'fs-jetpack';
import i18n from '../i18n/index.js';
const installDir = jetpack.cwd(app.getAppPath());
const appDir = jetpack.cwd(app.getAppPath());
const userDataDir = jetpack.cwd(app.getPath('userData'));
const updateStoreFile = 'update.json';
let checkForUpdatesEvent;
const updateSettingsFileName = 'update.json';
const loadUpdateSettings = (dir) => {
try {
return dir.read(updateSettingsFileName, 'json') || {};
} catch (error) {
console.error(error);
return {};
}
};
autoUpdater.autoDownload = false;
const appUpdateSettings = loadUpdateSettings(appDir);
const userUpdateSettings = loadUpdateSettings(userDataDir);
const updateSettings = (() => {
const defaultUpdateSettings = { autoUpdate: true };
let updateFile = {};
try {
const installUpdateFile = installDir.read(updateStoreFile, 'json');
const userUpdateFile = userDataDir.read(updateStoreFile, 'json');
updateFile = Object.assign({}, installUpdateFile, userUpdateFile);
} catch (err) {
console.error(err);
}
if (appUpdateSettings.forced) {
return Object.assign({}, defaultUpdateSettings, appUpdateSettings);
} else {
return Object.assign({}, defaultUpdateSettings, appUpdateSettings, userUpdateSettings);
}
})();
delete updateSettings.forced;
const saveUpdateSettings = () => {
if (appUpdateSettings.forced) {
return;
}
userDataDir.write(updateSettingsFileName, userUpdateSettings, { atomic: true });
};
let checkForUpdatesEvent;
function updateDownloaded () {
dialog.showMessageBox({
......@@ -52,7 +72,7 @@ function updateAvailable ({version}) {
if (checkForUpdatesEvent) {
checkForUpdatesEvent.sender.send('update-result', true);
checkForUpdatesEvent = null;
} else if (updateFile.skip === version) {
} else if (updateSettings.skip === version) {
return;
}
......@@ -78,8 +98,8 @@ function updateAvailable ({version}) {
ipcMain.once('update-response', (e, type) => {
switch (type) {
case 'skip':
updateFile.skip = version;
userDataDir.write(updateStoreFile, updateFile, { atomic: true });
userUpdateSettings.skip = version;
saveUpdateSettings();
dialog.showMessageBox({
title: i18n.__('Update_skip'),
message: i18n.__('Update_skip_message')
......@@ -107,35 +127,54 @@ function updateAvailable ({version}) {
});
}
function canUpdate () {
return !process.mas;
}
export const canUpdate = () =>
(process.platform === 'linux' && Boolean(process.env.APPIMAGE)) &&
(process.platform === 'win32' && !process.windowsStore) &&
(process.platform === 'darwin' && !process.mas);
function checkForUpdates () {
autoUpdater.on('update-available', updateAvailable);
autoUpdater.on('update-not-available', updateNotAvailable);
export const canAutoUpdate = () => updateSettings.autoUpdate !== false;
autoUpdater.on('update-downloaded', updateDownloaded);
export const canSetAutoUpdate = () => !appUpdateSettings.forced || appUpdateSettings.autoUpdate !== false;
// Event from about window
ipcMain.on('check-for-updates', (e, autoUpdate) => {
if (autoUpdate === true || autoUpdate === false) {
updateFile.autoUpdate = autoUpdate;
userDataDir.write(updateStoreFile, updateFile, { atomic: true });
} else if (autoUpdate === 'auto') {
e.returnValue = updateFile.autoUpdate !== false;
} else {
checkForUpdatesEvent = e;
autoUpdater.checkForUpdates();
}
});
export const setAutoUpdate = (canAutoUpdate) => {
if (!canSetAutoUpdate()) {
return;
}
updateSettings.autoUpdate = userUpdateSettings.autoUpdate = Boolean(canAutoUpdate);
saveUpdateSettings();
};
ipcMain.on('can-update', (event) => {
event.returnValue = canUpdate();
});
ipcMain.on('can-auto-update', (event) => {
event.returnValue = canAutoUpdate();
});
if (updateFile.autoUpdate !== false) {
ipcMain.on('can-set-auto-update', (event) => {
event.returnValue = canSetAutoUpdate();
});
ipcMain.on('set-auto-update', (event, canAutoUpdate) => {
setAutoUpdate(canAutoUpdate);
});
autoUpdater.autoDownload = false;
autoUpdater.on('update-available', updateAvailable);
autoUpdater.on('update-not-available', updateNotAvailable);
autoUpdater.on('update-downloaded', updateDownloaded);
ipcMain.on('check-for-updates', (event) => {
if (canAutoUpdate() && canUpdate()) {
checkForUpdatesEvent = event;
autoUpdater.checkForUpdates();
}
}
});
export {
canUpdate,
checkForUpdates
export default () => {
if (canAutoUpdate() && canUpdate()) {
autoUpdater.checkForUpdates();
}
};
......@@ -66,9 +66,7 @@
</head>
<body>
<img src="images/icon.png">
<div class="app-name">
</div>
<div class="app-name"></div>
<div class="app-version"></div>
<div class="update-container">
......@@ -83,23 +81,32 @@
document.querySelector('.app-name').innerHTML = remote.app.getName();
document.querySelector('.app-version').innerHTML = `${i18n.__('Version')} <span class="version">${remote.app.getVersion()}</span>`;
const canUpdate = !process.mas;
const canUpdate = ipcRenderer.sendSync('can-update');
if (canUpdate) {
const autoUpdate = ipcRenderer.sendSync('check-for-updates', 'auto');
if (!autoUpdate) {
const canAutoUpdate = ipcRenderer.sendSync('can-auto-update');
if (canAutoUpdate) {
document.querySelector('#auto-update').setAttribute('checked', 'checked');
} else {
document.querySelector('#auto-update').removeAttribute('checked');
}
const canSetAutoUpdate = ipcRenderer.sendSync('can-set-auto-update');
if (canSetAutoUpdate) {
document.querySelector('#auto-update').addEventListener('change', (event) => {
ipcRenderer.send('set-auto-update', event.target.checked);
});
} else {
document.querySelector('#auto-update').setAttribute('disabled', 'disabled');
}
document.querySelector('.update').onclick = function(e) {
document.querySelector('.update-spin').setAttribute('style', '');
document.querySelector('.update').setAttribute('disabled', 'disabled');
ipcRenderer.send('check-for-updates');
};
document.querySelector('#auto-update').onclick = function(e) {
ipcRenderer.send('check-for-updates', e.target.checked);
};
ipcRenderer.on('update-result', (e, updateAvailable) => {
document.querySelector('.update-spin').setAttribute('style', 'display:none');
document.querySelector('.update').removeAttribute('disabled');
......
'use strict';
const gulp = require('gulp');
const sequence = require('gulp-sequence');
const childProcess = require('child_process');
const os = require('os');
const path = require('path');
const { build } = require('electron-builder');
const config = require('../electron-builder.json');
const { getEnvName } = require('./utils');
const argv = process.argv.slice(3).filter(arg => !arg.startsWith('--env'));
const publishArgs = getEnvName() !== 'production' ? [ '--publish', 'never' ] : [];
const publish = getEnvName() !== 'production' ? 'never' : null;
gulp.task('release:darwin', () => build({ publish, x64: true, mac: [] }));
gulp.task('release:win32', () => build({ publish, ia32: true, x64: true, win: [ 'nsis', 'appx' ] }));
gulp.task('release:linux', () => build({ publish, x64: true, linux: [] })
.then(() => build({ publish, ia32: true, linux: config.linux.target.filter(target => target !== 'snap') }))
);
const buildRelease = (...args) => cb => {
const buildPath = path.join('node_modules', '.bin', os.platform() === 'win32' ? 'build.cmd' : 'build');
childProcess.spawn(buildPath, [ ...argv, ...publishArgs, ...args ], { stdio: 'inherit' })
.on('close', () => cb());
};
gulp.task('release:osx', [ 'build-app' ], buildRelease('--x64', '--mac'));
gulp.task('release:win', [ 'build-app' ], buildRelease('--ia32', '--x64', '--win', 'nsis', 'appx'));
gulp.task('release:linux-x64', buildRelease('--x64', '--linux'));
gulp.task('release:linux-ia32', buildRelease('--ia32', '--linux', 'tar.gz', 'deb', 'rpm'));
gulp.task('release:linux', [ 'build-app' ], sequence('release:linux-x64', 'release:linux-ia32'));
gulp.task('release', cb => {
switch (os.platform()) {
case 'darwin':
return gulp.start('release:osx', cb);
case 'win32':
return gulp.start('release:win', cb);
case 'linux':
return gulp.start('release:linux', cb);
}
});
gulp.task('release', [ 'build-app', `release:${ process.platform }` ]);
......@@ -2294,12 +2294,6 @@ gulp-rename@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.4.0.tgz#de1c718e7c4095ae861f7296ef4f3248648240bd"
gulp-sequence@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/gulp-sequence/-/gulp-sequence-1.0.0.tgz#862f93e6503e67c350a42948fa666953cf88ba67"
dependencies:
thunks "^4.9.0"
gulp-util@^3.0.0, gulp-util@^3.0.8:
version "3.0.8"
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
......@@ -4911,10 +4905,6 @@ through@2, "through@>=2.2.7 <3", through@^2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
thunks@^4.9.0:
version "4.9.2"
resolved "https://registry.yarnpkg.com/thunks/-/thunks-4.9.2.tgz#aac2d353812512160a4611e3008d7a96e3756f8e"
tildify@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment