Skip to content

Commit

Permalink
Improve auto updater (#869)
Browse files Browse the repository at this point in the history
* Auto format file

* Replace auto-updater with electron-updater

* Ignore `dev-app-update.yml`

* Reset version

* Format releaseNotes to markdown

* Replace manual updater & refactoring

* Trigger build

* Fix downloadUrl

* Retrigger build

* Fix & in onConfirm button on Windows

* Set `autoInstallOnAppQuit` to false

* Update url to changelog

Co-Authored-By: adlk <stefan@adlk.io>

* Bring package-lock in sync

* To revert: set version to 1.0.0

* Revert "To revert: set version to 1.0.0"

This reverts commit 0edacd0.

* Fix path

* Fix changelog URL

* Update electron-updater (fix macOS timing issue)

* Remove appdmg as an optional dependency

* Use npm ci
  • Loading branch information
adlk committed Nov 12, 2018
1 parent f01f684 commit c9b8d4a
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 562 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -57,7 +57,7 @@ jobs:
at: ~/simplenote
- *npm_restore_cache
- *install_linux_deps
- run: npm install
- run: npm ci
- *npm_save_cache
- run: make package-linux SKIP_BUILD=true
- run:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -8,3 +8,4 @@ release/
*.tgz
.idea
.DS_Store
dev-app-update.yml
2 changes: 1 addition & 1 deletion appveyor.yml
Expand Up @@ -12,7 +12,7 @@ image: Visual Studio 2017
install:
- ps: Install-Product node 10
- cinst make
- npm install
- npm ci

before_build:
- openssl aes-256-cbc -d -in .\resources\certificates\win.p12.enc -out %CSC_LINK% -k "%CSC_ENC_KEY%"
Expand Down
6 changes: 3 additions & 3 deletions desktop/config-updater.json
@@ -1,8 +1,8 @@
{
"forceUpdate": false,
"updater": {
"url":
"https://app.simplenote.com/desktop/{platform}/version?compare={version}",
"downloadUrl": "https://github.com/Automattic/simplenote-electron/releases/latest",
"changelogUrl": "https://github.com/Automattic/simplenote-electron/blob/master/CHANGELOG.md",
"apiUrl": "https://api.github.com/repos/automattic/simplenote-electron/releases/latest",
"delay": 2000,
"interval": 600000
}
Expand Down
67 changes: 20 additions & 47 deletions desktop/updater/auto-updater/index.js
Expand Up @@ -3,60 +3,33 @@
/**
* External Dependencies
*/
const EventEmitter = require('events').EventEmitter;
const util = require('util');
const electron = require( 'electron' );
const autoUpdater = electron.autoUpdater;
const dialog = electron.dialog;
const { autoUpdater } = require('electron-updater');

/**
* Internal dependencies
*/
const AppQuit = require( '../..//app-quit' );
const Updater = require('../lib/Updater');
const AppQuit = require('../../app-quit');

function AutoUpdater( url ) {
this.hasPrompted = false;
this.url = url;
class AutoUpdater extends Updater {
constructor({ changelogUrl, options = {} }) {
super(changelogUrl, options);

autoUpdater.on( 'error', () => this.emit( 'end' ) );
autoUpdater.on( 'update-not-available', () => this.emit( 'end' ) );
autoUpdater.on( 'update-downloaded', this.onDownloaded.bind( this ) );
autoUpdater.on('error', this.onError.bind(this));
autoUpdater.on('update-not-available', this.onNotAvailable.bind(this));
autoUpdater.on('update-downloaded', this.onDownloaded.bind(this));

try {
autoUpdater.setFeedURL( url );
} catch (e) {
console.log( e.message );
}
}
autoUpdater.autoInstallOnAppQuit = false;
}

ping() {
autoUpdater.checkForUpdates();
}

util.inherits(AutoUpdater, EventEmitter);

AutoUpdater.prototype.ping = function() {
autoUpdater.checkForUpdates();
};

AutoUpdater.prototype.onDownloaded = function( event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate ) {
const updateDialogOptions = {
buttons: [ 'Update & Restart', 'Cancel' ],
title: 'Update Available',
message: releaseName,
detail: releaseNotes
};

if ( this.hasPrompted === false ) {
this.hasPrompted = true;

dialog.showMessageBox( updateDialogOptions, button => {
this.hasPrompted = false;

if ( button === 0 ) {
AppQuit.allowQuit();
quitAndUpdate();
} else {
this.emit( 'end' );
}
} );
}
};
onConfirm() {
AppQuit.allowQuit();
autoUpdater.quitAndInstall();
}
}

module.exports = AutoUpdater;
41 changes: 15 additions & 26 deletions desktop/updater/index.js
Expand Up @@ -3,9 +3,7 @@
/**
* External Dependencies
*/
const electron = require('electron');
const app = electron.app;
const dialog = electron.dialog;
const { app } = require('electron');

/**
* Internal dependencies
Expand All @@ -17,32 +15,23 @@ const ManualUpdater = require('./manual-updater');

let updater = false;

function urlBuilder(version) {
let platformString = 'osx';

if (platform.isWindows()) {
platformString = 'windows';
} else if (platform.isLinux()) {
platformString = 'linux';
}

if (config.forceUpdate) {
version = '0.0.1';
}

return config.updater.url
.replace('{platform}', platformString)
.replace('{version}', version);
}

module.exports = function() {
app.on('will-finish-launching', function() {
let url = urlBuilder(app.getVersion());

if (platform.isOSX()) {
updater = new AutoUpdater(url);
if (platform.isOSX() || platform.isWindows() || process.env.APPIMAGE) {
updater = new AutoUpdater({
changelogUrl: config.updater.changelogUrl,
});
} else {
updater = new ManualUpdater(url);
updater = new ManualUpdater({
downloadUrl: config.updater.downloadUrl,
apiUrl: config.updater.apiUrl,
changelogUrl: config.updater.changelogUrl,
options: {
dialogMessage:
'{name} {newVersion} is now available — you have {currentVersion}. Would you like to download it now?',
confirmLabel: 'Download',
},
});
}

// Start one straight away
Expand Down
114 changes: 114 additions & 0 deletions desktop/updater/lib/Updater.js
@@ -0,0 +1,114 @@
const EventEmitter = require('events').EventEmitter;
const { app, dialog, shell } = require('electron');
const platform = require('../../platform');

class Updater extends EventEmitter {
constructor(changelogUrl, options) {
super();

this.changelogUrl = changelogUrl;
this.confirmLabel = options.confirmLabel || 'Update & Restart';
this.dialogTitle =
options.dialogTitle || 'A new version of {name} is available!';
this.dialogMessage =
options.dialogMessage ||
'{name} {newVersion} is now available — you have {currentVersion}. Would you like to update now?';

this._version = '';
this._hasPrompted = false;
}

ping() {}

onDownloaded(event) {
console.log('Update downloaded');

// electron-updater provides us with new version
if (event.version) {
this.setVersion(event.version);
}

this.notify();
}

onNotAvailable() {
console.log('Update is not available');
}

onError(event) {
console.log('Update error', event);
}

onConfirm() {}

onCancel() {}

onChangelog() {
shell.openExternal(this.changelogUrl);
}

notify() {
const updateDialogOptions = {
buttons: [
this.sanitizeButtonLabel(this.confirmLabel),
'Cancel',
'Release notes',
],
title: 'Update Available',
message: this.expandMacros(this.dialogTitle),
detail: this.expandMacros(this.dialogMessage),
};

if (!this._hasPrompted) {
this._hasPrompted = true;

dialog.showMessageBox(updateDialogOptions, button => {
this._hasPrompted = false;

if (button === 0) {
// Confirm
this.onConfirm();
} else if (button === 2) {
// Open changelog
this.onChangelog();
} else {
this.onCancel();
}

this.emit('end');
});
}
}

setVersion(version) {
this._version = version;
}

expandMacros(originalText) {
const macros = {
name: app.getName(),
currentVersion: app.getVersion(),
newVersion: this._version,
};

let text = originalText;

for (const key in macros) {
if (macros.hasOwnProperty(key)) {
text = text.replace(new RegExp(`{${key}}`, 'ig'), macros[key]);
}
}

return text;
}

sanitizeButtonLabel(value) {
if (platform.isWindows()) {
return value.replace('&', '&&');
}

return value;
}
}

module.exports = Updater;

0 comments on commit c9b8d4a

Please sign in to comment.