Skip to content

Commit

Permalink
Use same hazel endpoint to notify update to Linux users (#2497)
Browse files Browse the repository at this point in the history
Add a pseudo auto-updater for Linux

Fixes #2476
  • Loading branch information
chabou committed Nov 29, 2017
1 parent 59273dd commit 1fbc857
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 33 deletions.
50 changes: 50 additions & 0 deletions app/auto-updater-linux.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

const fetch = require('node-fetch');
const {EventEmitter} = require('events');

class AutoUpdater extends EventEmitter {
quitAndInstall() {
this.emitError('QuitAndInstall unimplemented');
}
getFeedURL() {
return this.updateURL;
}

setFeedURL(updateURL) {
this.updateURL = updateURL;
}

checkForUpdates() {
if (!this.updateURL) {
return this.emitError('Update URL is not set');
}
this.emit('checking-for-update');

fetch(this.updateURL)
.then(res => {
if (res.status === 204) {
return this.emit('update-not-available');
}
return res.json().then(({name, notes, pub_date}) => {
// Only name is mandatory, needed to construct release URL.
if (!name) {
throw new Error('Malformed server response: release name is missing.');
}
// If `null` is passed to Date constructor, current time will be used. This doesn't work with `undefined`
const date = new Date(pub_date || null);
this.emit('update-available', {}, notes, name, date);
});
})
.catch(this.emitError.bind(this));
}

emitError(error) {
if (typeof error === 'string') {
error = new Error(error);
}
this.emit('error', error, error.message);
}
}

module.exports = new AutoUpdater();
6 changes: 3 additions & 3 deletions app/ui/window.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const {parse: parseUrl} = require('url');
const uuid = require('uuid');
const fileUriToPath = require('file-uri-to-path');
const isDev = require('electron-is-dev');
const AutoUpdater = require('../auto-updater');
const updater = require('../updater');
const toElectronBackgroundColor = require('../utils/to-electron-background-color');
const {icon, cfgDir} = require('../config/paths');
const createRPC = require('../rpc');
Expand Down Expand Up @@ -76,8 +76,8 @@ module.exports = class Window {
delete app.windowCallback;
fetchNotifications(window);
// auto updates
if (!isDev && process.platform !== 'linux') {
AutoUpdater(window);
if (!isDev) {
updater(window);
} else {
//eslint-disable-next-line no-console
console.log('ignoring auto updates during dev');
Expand Down
33 changes: 20 additions & 13 deletions app/auto-updater.js → app/updater.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
// Packages
const {autoUpdater, app} = require('electron');
const electron = require('electron');
const {app} = electron;
const ms = require('ms');
const retry = require('async-retry');

// Utilities
// eslint-disable-next-line no-unused-vars
const notify = require('./notify');
const {version} = require('./package');
const {getConfig} = require('./config');
const {getDecoratedConfig} = require('./plugins');

const {platform} = process;
const isLinux = platform === 'linux';

const autoUpdater = isLinux ? require('./auto-updater-linux') : electron.autoUpdater;

let isInit = false;
// Default to the "stable" update channel
let canaryUpdates = false;

const buildFeedUrl = canary => {
const buildFeedUrl = (canary, currentVersion) => {
const updatePrefix = canary ? 'releases-canary' : 'releases';
return `https://${updatePrefix}.hyper.is/update/${platform}`;
return `https://${updatePrefix}.hyper.is/update/${isLinux ? 'deb' : platform}/${currentVersion}`;
};

const isCanary = updateChannel => updateChannel === 'canary';
Expand All @@ -29,7 +33,7 @@ async function init() {
});

const config = await retry(async () => {
const content = await getConfig();
const content = await getDecoratedConfig();

if (!content) {
throw new Error('No config content loaded');
Expand All @@ -43,9 +47,9 @@ async function init() {
canaryUpdates = true;
}

const feedURL = buildFeedUrl(canaryUpdates);
const feedURL = buildFeedUrl(canaryUpdates, version);

autoUpdater.setFeedURL(`${feedURL}/${version}`);
autoUpdater.setFeedURL(feedURL);

setTimeout(() => {
autoUpdater.checkForUpdates();
Expand All @@ -65,11 +69,14 @@ module.exports = win => {

const {rpc} = win;

const onupdate = (ev, releaseNotes, releaseName) => {
rpc.emit('update available', {releaseNotes, releaseName});
const onupdate = (ev, releaseNotes, releaseName, date, updateUrl, onQuitAndInstall) => {
const releaseUrl = updateUrl || `https://github.com/zeit/hyper/releases/tag/${releaseName}`;
rpc.emit('update available', {releaseNotes, releaseName, releaseUrl, canInstall: !!onQuitAndInstall});
};

autoUpdater.on('update-downloaded', onupdate);
const eventName = isLinux ? 'update-available' : 'update-downloaded';

autoUpdater.on(eventName, onupdate);

rpc.once('quit and install', () => {
autoUpdater.quitAndInstall();
Expand All @@ -80,16 +87,16 @@ module.exports = win => {
const newUpdateIsCanary = isCanary(updateChannel);

if (newUpdateIsCanary !== canaryUpdates) {
const feedURL = buildFeedUrl(newUpdateIsCanary);
const feedURL = buildFeedUrl(newUpdateIsCanary, version);

autoUpdater.setFeedURL(`${feedURL}/${version}`);
autoUpdater.setFeedURL(feedURL);
autoUpdater.checkForUpdates();

canaryUpdates = newUpdateIsCanary;
}
});

win.on('close', () => {
autoUpdater.removeListener('update-downloaded', onupdate);
autoUpdater.removeListener(eventName, onupdate);
});
};
6 changes: 4 additions & 2 deletions lib/actions/updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ export function installUpdate() {
};
}

export function updateAvailable(version, notes) {
export function updateAvailable(version, notes, releaseUrl, canInstall) {
return {
type: UPDATE_AVAILABLE,
version,
notes
notes,
releaseUrl,
canInstall
};
}
40 changes: 29 additions & 11 deletions lib/components/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,38 @@ export default class Notifications extends PureComponent {
window.require('electron').shell.openExternal(ev.target.href);
ev.preventDefault();
}}
href={`https://github.com/zeit/hyper/releases/tag/${this.props.updateVersion}`}
href={this.props.updateReleaseUrl}
>
notes
</a>).{' '}
<a
style={{
cursor: 'pointer',
textDecoration: 'underline',
fontWeight: 'bold'
}}
onClick={this.props.onUpdateInstall}
>
Restart
</a>.{' '}
{this.props.updateCanInstall ? (
<a
style={{
cursor: 'pointer',
textDecoration: 'underline',
fontWeight: 'bold'
}}
onClick={this.props.onUpdateInstall}
>
Restart
</a>
) : (
<a
style={{
color: '#fff',
cursor: 'pointer',
textDecoration: 'underline',
fontWeight: 'bold'
}}
onClick={ev => {
window.require('electron').shell.openExternal(ev.target.href);
ev.preventDefault();
}}
href={this.props.updateReleaseUrl}
>
Download
</a>
)}.{' '}
</Notification>
)}
{this.props.customChildren}
Expand Down
4 changes: 3 additions & 1 deletion lib/containers/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ const NotificationsContainer = connect(
Object.assign(state_, {
updateShowing: true,
updateVersion: ui.updateVersion,
updateNote: ui.updateNotes.split('\n')[0]
updateNote: ui.updateNotes.split('\n')[0],
updateReleaseUrl: ui.updateReleaseUrl,
updateCanInstall: ui.updateCanInstall
});
} else if (notifications.message) {
Object.assign(state_, {
Expand Down
4 changes: 2 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ rpc.on('open file', ({path}) => {
store_.dispatch(uiActions.openFile(path));
});

rpc.on('update available', ({releaseName, releaseNotes}) => {
store_.dispatch(updaterActions.updateAvailable(releaseName, releaseNotes));
rpc.on('update available', ({releaseName, releaseNotes, releaseUrl, canInstall}) => {
store_.dispatch(updaterActions.updateAvailable(releaseName, releaseNotes, releaseUrl, canInstall));
});

rpc.on('move', () => {
Expand Down
4 changes: 3 additions & 1 deletion lib/reducers/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,9 @@ const reducer = (state = initial, action) => {
case UPDATE_AVAILABLE:
state_ = state.merge({
updateVersion: action.version,
updateNotes: action.notes || ''
updateNotes: action.notes || '',
updateReleaseUrl: action.releaseUrl,
updateCanInstall: !!action.canInstall
});
break;
}
Expand Down

0 comments on commit 1fbc857

Please sign in to comment.