mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-12 20:18:41 -09:00
Use same hazel endpoint to notify update to Linux users (#2497)
Add a pseudo auto-updater for Linux Fixes #2476
This commit is contained in:
parent
59273ddb2a
commit
1fbc85760b
8 changed files with 114 additions and 33 deletions
50
app/auto-updater-linux.js
Normal file
50
app/auto-updater-linux.js
Normal file
|
|
@ -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();
|
||||
|
|
@ -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');
|
||||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// Packages
|
||||
const {autoUpdater, app} = require('electron');
|
||||
const electron = require('electron');
|
||||
const {app} = electron;
|
||||
const ms = require('ms');
|
||||
const retry = require('async-retry');
|
||||
|
||||
|
|
@ -7,17 +8,20 @@ const retry = require('async-retry');
|
|||
// 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';
|
||||
|
|
@ -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');
|
||||
|
|
@ -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();
|
||||
|
|
@ -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();
|
||||
|
|
@ -80,9 +87,9 @@ 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;
|
||||
|
|
@ -90,6 +97,6 @@ module.exports = win => {
|
|||
});
|
||||
|
||||
win.on('close', () => {
|
||||
autoUpdater.removeListener('update-downloaded', onupdate);
|
||||
autoUpdater.removeListener(eventName, onupdate);
|
||||
});
|
||||
};
|
||||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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_, {
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue