Skip to content

Commit

Permalink
Electron: Fixes #292: Removed buggy electron-updater and implemented …
Browse files Browse the repository at this point in the history
…custom check
  • Loading branch information
laurent22 committed Mar 14, 2018
1 parent 7937fab commit 0317171
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 159 deletions.
144 changes: 52 additions & 92 deletions ElectronClient/app/checkForUpdates.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,15 @@
const { dialog } = require('electron')
const { autoUpdater } = require('electron-updater')
const { Logger } = require('lib/logger.js');
const { _ } = require('lib/locale.js');
const fetch = require('node-fetch');
const packageInfo = require('./packageInfo.js');
const compareVersions = require('compare-versions');

let autoUpdateLogger_ = new Logger();
let checkInBackground_ = false;
let isCheckingForUpdate_ = false;
let parentWindow_ = null;

// Note: Electron Builder's autoUpdater is incredibly buggy so currently it's only used
// to detect if a new version is present. If it is, the download link is simply opened
// in a new browser window.
autoUpdater.autoDownload = false;

function htmlToText_(html) {
let output = html.replace(/\n/g, '');
output = output.replace(/<li>/g, '- ');
output = output.replace(/<p>/g, '');
output = output.replace(/<\/p>/g, '\n');
output = output.replace(/<\/li>/g, '\n');
output = output.replace(/<ul>/g, '');
output = output.replace(/<\/ul>/g, '');
output = output.replace(/<.*?>/g, '');
output = output.replace(/<\/.*?>/g, '');
return output;
}

function showErrorMessageBox(message) {
return dialog.showMessageBox(parentWindow_, {
type: 'error',
Expand All @@ -43,80 +27,44 @@ function onCheckEnded() {
isCheckingForUpdate_ = false;
}

autoUpdater.on('error', (error) => {
autoUpdateLogger_.error(error);
if (checkInBackground_) return onCheckEnded();

let msg = error == null ? "unknown" : (error.stack || error).toString();
// Error messages can be very long even without stack trace so shorten
// then so that the dialog box doesn't take the whole screen.
msg = msg.substr(0,512).replace(/\\n/g, '\n');
showErrorMessageBox(msg)

onCheckEnded();
})

function findDownloadFilename_(info) {
// { version: '1.0.64',
// files:
// [ { url: 'Joplin-1.0.64-mac.zip',
// sha512: 'OlemXqhq/fSifx7EutvMzfoCI/1kGNl10i8nkvACEDfVXwP8hankDBXEC0+GxSArsZuxOh3U1+C+4j72SfIUew==' },
// { url: 'Joplin-1.0.64.dmg',
// sha512: 'jAewQQoJ3nCaOj8hWDgf0sc3LBbAWQtiKqfTflK8Hc3Dh7fAy9jRHfFAZKFUZ9ll95Bun0DVsLq8wLSUrdsMXw==',
// size: 77104485 } ],
// path: 'Joplin-1.0.64-mac.zip',
// sha512: 'OlemXqhq/fSifx7EutvMzfoCI/1kGNl10i8nkvACEDfVXwP8hankDBXEC0+GxSArsZuxOh3U1+C+4j72SfIUew==',
// releaseDate: '2018-02-16T00:13:01.634Z',
// releaseName: 'v1.0.64',
// releaseNotes: '<p>Still more fixes and im...' }

if (!info) return null;

if (!info.files) {
// info.path seems to contain a default, though not a good one,
// so the loop below if preferable to find the right file.
return info.path;
}
async function fetchLatestRelease() {
const response = await fetch('https://api.github.com/repos/laurent22/joplin/releases/latest');

for (let i = 0; i < info.files.length; i++) {
const f = info.files[i].url; // Annoyingly this is called "url" but it's obviously not a url, so hopefully it won't change later on and become one.
if (f.indexOf('.exe') >= 0) return f;
if (f.indexOf('.dmg') >= 0) return f;
if (!response.ok) {
const responseText = await response.text();
throw new Error('Cannot get latest release info: ' + responseText.substr(0,500));
}

return info.path;
}

autoUpdater.on('update-available', (info) => {
const filename = findDownloadFilename_(info);

if (!info.version || !filename) {
if (checkInBackground_) return onCheckEnded();
showErrorMessageBox(('Could not get version info: ' + JSON.stringify(info)));
return onCheckEnded();
const json = await response.json();

const version = json.tag_name.substr(1);
let downloadUrl = null;
const platform = process.platform;
for (let i = 0; i < json.assets.length; i++) {
const asset = json.assets[i];
let found = false;
if (platform === 'win32' && asset.name.indexOf('.exe') >= 0) {
found = true;
} else if (platform === 'darwin' && asset.name.indexOf('.dmg') >= 0) {
found = true;
} else if (platform === 'linux' && asset.name.indexOf('.AppImage') >= 0) {
found = true;
}

if (found) {
downloadUrl = asset.browser_download_url;
break;
}
}

const downloadUrl = 'https://github.com/laurent22/joplin/releases/download/v' + info.version + '/' + filename;
if (!downloadUrl) throw new Error('Cannot find download Url: ' + JSON.stringify(json).substr(0,500));

let releaseNotes = info.releaseNotes + '';
if (releaseNotes) releaseNotes = '\n\n' + _('Release notes:\n\n%s', htmlToText_(releaseNotes));

const buttonIndex = dialog.showMessageBox(parentWindow_, {
type: 'info',
message: _('An update is available, do you want to download it now?' + releaseNotes),
buttons: [_('Yes'), _('No')]
});

onCheckEnded();

if (buttonIndex === 0) require('electron').shell.openExternal(downloadUrl);
})

autoUpdater.on('update-not-available', () => {
if (checkInBackground_) return onCheckEnded();
dialog.showMessageBox({ message: _('Current version is up-to-date.') })
onCheckEnded();
})
return {
version: version,
downloadUrl: downloadUrl,
notes: json.body,
};
}

function checkForUpdates(inBackground, window, logFilePath) {
if (isCheckingForUpdate_) {
Expand All @@ -133,18 +81,30 @@ function checkForUpdates(inBackground, window, logFilePath) {
autoUpdateLogger_.addTarget('file', { path: logFilePath });
autoUpdateLogger_.setLevel(Logger.LEVEL_DEBUG);
autoUpdateLogger_.info('checkForUpdates: Initializing...');
autoUpdater.logger = autoUpdateLogger_;
}

checkInBackground_ = inBackground;

try {
autoUpdater.checkForUpdates()
} catch (error) {
fetchLatestRelease().then(release => {
if (compareVersions(release.version, packageInfo.version) <= 0) {
if (!checkInBackground_) dialog.showMessageBox({ message: _('Current version is up-to-date.') })
} else {
const releaseNotes = release.notes.trim() ? "\n\n" + release.notes.trim() : '';

const buttonIndex = dialog.showMessageBox(parentWindow_, {
type: 'info',
message: _('An update is available, do you want to download it now?' + releaseNotes),
buttons: [_('Yes'), _('No')]
});

if (buttonIndex === 0) require('electron').shell.openExternal(release.downloadUrl);
}
}).catch(error => {
autoUpdateLogger_.error(error);
if (!checkInBackground_) showErrorMessageBox(error.message);
}).then(() => {
onCheckEnded();
}
});
}

module.exports.checkForUpdates = checkForUpdates
81 changes: 16 additions & 65 deletions ElectronClient/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions ElectronClient/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@
"app-module-path": "^2.2.0",
"async-mutex": "^0.1.3",
"base-64": "^0.1.0",
"compare-versions": "^3.1.0",
"electron-context-menu": "^0.9.1",
"electron-log": "^2.2.11",
"electron-updater": "^2.18.2",
"electron-window-state": "^4.1.1",
"follow-redirects": "^1.2.5",
"form-data": "^2.3.1",
Expand Down

0 comments on commit 0317171

Please sign in to comment.