Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move 'new version' support into Platform #2532

Merged
merged 8 commits into from
Nov 3, 2016
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 37 additions & 15 deletions src/components/views/globals/NewVersionBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ limitations under the License.
var React = require('react');
var sdk = require('matrix-react-sdk');
import Modal from 'matrix-react-sdk/lib/Modal';
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';

/**
* Check a version string is compatible with the Changelog
Expand All @@ -31,35 +32,56 @@ function checkVersion(ver) {

export default function NewVersionBar(props) {
const onChangelogClicked = () => {
const ChangelogDialog = sdk.getComponent('dialogs.ChangelogDialog');

Modal.createDialog(ChangelogDialog, {
version: props.version,
newVersion: props.newVersion,
onFinished: (update) => {
if(update) {
window.location.reload();
if (props.releaseNotes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I feel like this should be two separate functions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still think this needs splitting

const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
Modal.createDialog(QuestionDialog, {
title: "What's New",
description: <pre className="changelog_text">{props.releaseNotes}</pre>,
button: "Update",
onFinished: (update) => {
if(update && PlatformPeg.get()) {
PlatformPeg.get().installUpdate();
}
}
});
} else {
const ChangelogDialog = sdk.getComponent('dialogs.ChangelogDialog');
Modal.createDialog(ChangelogDialog, {
version: props.version,
newVersion: props.newVersion,
releaseNotes: releaseNotes,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

releaseNotes seems to be undefined here.

onFinished: (update) => {
if(update && PlatformPeg.get()) {
PlatformPeg.get().installUpdate();
}
}
}
});
});
}
};

const onUpdateClicked = () => {
PlatformPeg.get().installUpdate();
};

let changelog_button;
if (checkVersion(props.version) && checkVersion(props.newVersion)) {
changelog_button = <button className="mx_MatrixToolbar_action" onClick={onChangelogClicked}>Changelog</button>;
let action_button;
if (props.releaseNotes || (checkVersion(props.version) && checkVersion(props.newVersion))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could do with a comment here explaining that we show a questiondialog if we have releasenotes, or a changelogdialog if we don't.

action_button = <button className="mx_MatrixToolbar_action" onClick={onChangelogClicked}>What's new?</button>;
} else if (PlatformPeg.get()) {
action_button = <button className="mx_MatrixToolbar_action" onClick={onUpdateClicked}>Update</button>;
}
return (
<div className="mx_MatrixToolbar">
<img className="mx_MatrixToolbar_warning" src="img/warning.svg" width="24" height="23" alt="/!\"/>
<div className="mx_MatrixToolbar_content">
A new version of Riot is available. Refresh your browser.
A new version of Riot is available.
</div>
{changelog_button}
{action_button}
</div>
);
}

NewVersionBar.propTypes = {
version: React.PropTypes.string.isRequired,
newVersion: React.PropTypes.string.isRequired,
releaseNotes: React.PropTypes.string,
};
4 changes: 4 additions & 0 deletions src/skins/vector/css/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,7 @@ textarea {
cursor: pointer;
display: inline;
}

.changelog_text {
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
}
7 changes: 1 addition & 6 deletions src/vector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ function onHashChange(ev) {
routeUrl(window.location);
}

function onVersion(current, latest) {
window.matrixChat.onVersion(current, latest);
}

var loaded = false;
var lastLoadedScreen = null;

Expand Down Expand Up @@ -165,8 +161,7 @@ window.onload = function() {
if (!validBrowser) {
return;
}
UpdateChecker.setVersionListener(onVersion);
UpdateChecker.run();
UpdateChecker.start();
routeUrl(window.location);
loaded = true;
if (lastLoadedScreen) {
Expand Down
41 changes: 41 additions & 0 deletions src/vector/platform/VectorBasePlatform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// @flow

/*
Copyright 2016 Aviral Dasgupta and OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import BasePlatform from 'matrix-react-sdk/lib/BasePlatform'

/**
* Vector-specific extensions to the BasePlatform template
*/
export default class VectorBasePlatform extends BasePlatform {
/**
* Check for the availability of an update to the version of the
* app that's currently running.
* If an update is available, this function should dispatch the
* 'new_version' action.
*/
pollForUpdate() {
}

/**
* Update the currently running app to the latest available
* version and replace this instance of the app with the
* new version.
*/
installUpdate() {
}
}
44 changes: 42 additions & 2 deletions src/vector/platform/WebPlatform.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import BasePlatform from 'matrix-react-sdk/lib/BasePlatform';
import VectorBasePlatform from './VectorBasePlatform';
import Favico from 'favico.js';
import request from 'browser-request';
import dis from 'matrix-react-sdk/lib/dispatcher.js';
import q from 'q';

export default class WebPlatform extends BasePlatform {
export default class WebPlatform extends VectorBasePlatform {
constructor() {
super();
this.runningVersion = null;
// The 'animations' are really low framerate and look terrible.
// Also it re-starts the animationb every time you set the badge,
// and we set the state each time, even if the value hasn't changed,
Expand Down Expand Up @@ -88,4 +90,42 @@ export default class WebPlatform extends BasePlatform {
notification.close();
}, 5 * 1000);
}

_getVersion() {
const deferred = q.defer();
request(
{ method: "GET", url: "version" },
(err, response, body) => {
if (err || response.status < 200 || response.status >= 300) {
if (err == null) err = { status: response.status };
deferred.reject(err);
return;
}

const ver = body.trim();
deferred.resolve(ver);
}
);
return deferred.promise;
}

pollForUpdate() {
this._getVersion().done((ver) => {
if (this.runningVersion == null) {
this.runningVersion = ver;
} else if (this.runningVersion != ver) {
dis.dispatch({
action: 'new_version',
currentVersion: this.runningVersion,
newVersion: ver,
});
}
}, (err) => {
console.error("Failed to poll for update", err);
});
}

installUpdate() {
window.location.reload();
}
}
46 changes: 8 additions & 38 deletions src/vector/updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,18 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var POKE_RATE_MS = 10 * 60 * 1000; // 10 min
var currentVersion = null;
var latestVersion = null;
var listener = function(){}; // NOP

module.exports = {
setVersionListener: function(fn) { // invoked with fn(currentVer, newVer)
listener = fn;
},

run: function() {
var req = new XMLHttpRequest();
req.addEventListener("load", function() {
if (!req.responseText) {
return;
}
var ver = req.responseText.trim();
if (!currentVersion) {
currentVersion = ver;
listener(currentVersion, currentVersion);
}
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';

if (ver !== latestVersion) {
latestVersion = ver;
if (module.exports.hasNewVersion()) {
console.log("Current=%s Latest=%s", currentVersion, latestVersion);
listener(currentVersion, latestVersion);
}
}
});
var cacheBuster = "?ts=" + new Date().getTime();
req.open("GET", "version" + cacheBuster);
req.send(); // can't suppress 404s from being logged.

setTimeout(module.exports.run, POKE_RATE_MS);
},
var POKE_RATE_MS = 10 * 60 * 1000; // 10 min

getCurrentVersion: function() {
return currentVersion;
module.exports = {
start: function() {
module.exports.poll();
setInterval(module.exports.poll, POKE_RATE_MS);
},

hasNewVersion: function() {
return currentVersion && latestVersion && (currentVersion !== latestVersion);
poll: function() {
PlatformPeg.get().pollForUpdate();
}
};